[英]How to construct a binary tree from just the level order traversal string
考慮具有以下屬性的二叉樹:
在樹上進行級別順序遍歷將生成1和0的字符串(通過在訪問每個節點時打印怪異的值)。 現在給定該字符串,構造二叉樹並在該樹上執行后順序遍歷。 后訂單字符串應為程序的輸出。
例如:輸入字符串為
111001000
。 由此創建一個二叉樹。 然后在樹上執行后遍歷,這將導致輸出:001001011
問題的“關鍵”是僅從級別順序字符串創建二叉樹。 我該怎么做?
以您的級別順序遍歷為例-111001000樹將如下所示
A
/ \
B C
/\ /\
D E F G
/\
H I
邏輯如下。
1)如果它的1(根)是第一位,那么接下來的2 ^ 1是該父級的子級的值。 因此,第二和第三位是A(根)的子代。
2)轉到下一個位(B的1),因為它的值也是1,它也有2個孩子,然后下一個位(C的1)也有2個孩子。 第二級結束了,因為我們有2 1,所以2 ^ 2下一位是3級。
3) 111 001000,所以我們遍歷了這一點,接下來的4位是3級的子級。 第4位和第5位為0(D和E是葉節點,沒有子代-這些將是B的子代),然后F的位值為1,因此1110010 00 (粗體數字)將是F的子代。第7位是0因此G也將是葉節點。
4)再次遍歷或嘗試重新設置-從第4、5、6和7位開始,只有一位是1,因此下2 ^ 1位將進入下一級,而這些位將是F的子級。
樹制作完成后,輕松轉換為PostFix。
一種可能的解決方案(不到一個小時):
import java.util.ArrayList;
import java.util.List;
public class Main {
private static class Node {
private Node left;
private Node right;
}
private static Node buildTree(String input) {
char chars[] = input.toCharArray();
if (chars.length == 0) {
return null;
} else {
Node root = new Node();
List<Node> nodeList = new ArrayList<Node>();
nodeList.add(root);
int pos = 0;
while (!nodeList.isEmpty()) {
List<Node> nextList = new ArrayList<Node>();
for (Node n: nodeList) {
if (pos >= chars.length) {
throw new RuntimeException("Invalid input string");
}
char c = chars[pos++];
if (c == '1') {
n.left = new Node();
n.right = new Node();
nextList.add(n.left);
nextList.add(n.right);
} else if (c != '0') {
throw new RuntimeException("Invalid input string");
}
}
nodeList = nextList;
}
return root;
}
}
private static String postTraverse(Node n) {
if (n == null) {
return "";
} else if (n.left == null && n.right == null) {
return "0";
} else {
return postTraverse(n.left) + postTraverse(n.right) + "1";
}
}
public static void main(String[] args) {
Node tree = buildTree(args[0]);
System.out.println(postTraverse(tree));
}
}
如果允許,我將在此處使用二進制堆作為幫助器。 在使用標准表實現的二進制堆中,給定元素的索引,我們可以輕松計算其父級的索引: int parent = (index-1)/2;
。 知道這一點之后,我們需要從表的開頭開始並進行以下操作:
對於輸入流中的所有其余元素:
do{ binaryHeap[heapIndex] = -1; if (parent(heapIndex) = 1) binaryHeap[heapIndex] = nextElementFromTheInputStream; heapIndex++; } while(binaryHeap[heapIndex - 1] == 0);
因此,基本上,我們遍歷表格。 我們將每個字段(root除外,在0處)初始化為-1,這意味着那里沒有節點。 然后,我們檢查該字段的父級是否為1。如果是,則將輸入流中的下一個元素放在堆中當前索引(heapIndex)上。 如果當前字段的父級為0,則我們走得更遠,因為這意味着我們的父級是葉子並且不應有任何子級。
然后,我們可以在堆上運行后置算法(可能值得實現一些安全代碼,因此在輸出流中不會放置任何帶有“ -1”的元素。只需解釋leftChild(heapIndex)== -1;或rightChild(heapIndex)== -1;為NULL)。
就內存而言,此算法可能效率很低,但我希望它很容易理解。
首先,我假設您的level order traversal
基本上是BFS。
現在,讓我們看一下字符串。 執行BFS時,如果當前節點有兩個兒子,我們將打印“ 1”。 否則,它是一片葉子,我們打印0,從而終止當前分支的處理。
因此,在反向任務期間,我們可以記住開放分支的最后一個節點列表,並將傳入的節點追加到那里。
讓我們在一個示例上演示這種方法:
Level 1:
Tree :
1 - id 0
Open branches : 0 0 (left and right son)
Remaining string : 11001000
*********
Level 2:
Tree :
1
1 1
Open branches : 1 1 2 2
Remaining string : 001000
*********
Level 3:
Tree :
1
1 1
0 0 1 0
Open branches : 5 5
Remaining string : 00
Level 4:
Tree :
1
1 1
0 0 1 0
0 0
No more input, we're done.
有了樹,后遍歷就變得微不足道了。
和代碼(它假定樹非常密集,否則它的內存效率不是很高):
import java.util.ArrayDeque;
import java.util.Queue;
public class Main {
static final int MAX_CONST = 50;
public static void main(String[] args) {
String evilString = "111001000"; // Assuming this string is a correct input
char[] treeRepr = new char[MAX_CONST];
Queue<Integer> q = new ArrayDeque<Integer>();
q.add(0);
for (int i = 0; i < evilString.length(); ++i) {
int index = q.remove();
char ch = evilString.charAt(i);
if (ch == '1') {
q.add(2*(index+1)-1);
q.add(2*(index+1));
}
treeRepr[index] = ch;
// System.out.println(q.size());
}
System.out.println(arrToString(treeRepr, 0, new StringBuilder()));
}
public static StringBuilder arrToString(char[] array, int index, StringBuilder sb) {
if (array[index] == '1')
{
arrToString(array, 2*(index+1)-1, sb);
arrToString(array, 2*(index+1), sb);
}
sb.append(array[index]);
return sb;
}
}
這是一個非常簡單的解決方案。 並不是很理想
尊重內存,因為我首先構建完整/完整樹
然后標記我們樹中實際存在的節點。 所以這
我想可以優化一點。
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
class Node {
public Node left;
public Node right;
public Integer id;
public boolean exists;
}
public class Test32 {
public static void main(String[] args) {
HashMap<Integer, Node> mp = new HashMap<Integer, Node>();
String str = "110101000";
int sz = (int)Math.pow(2, str.length() + 1);
for (int i=0; i<sz; i++){
Node nd = new Node();
nd.id = i;
mp.put(nd.id, nd);
}
for (int i=0; i<sz; i++){
Node nd = mp.get(i);
if (2*i < sz) nd.left = mp.get(2*i + 1);
if (2*i + 1 < sz) nd.right = mp.get(2*i + 2);
}
Queue<Integer> visit = new LinkedList<Integer>();
visit.add(0); // id = 0;
int j = 0;
int id = -1;
while (!visit.isEmpty()){
id = visit.poll();
if (str.charAt(j) == '1'){
mp.get(id).exists = true;
visit.add(2*id + 1);
visit.add(2*id + 2);
}else{
mp.get(id).exists = true;
}
j++;
}
System.out.println("NODES:");
for (int i=0; i<sz; i++){
if (mp.get(i).exists){
System.out.println(i);
}
}
System.out.println();
System.out.println("EDGES:");
for (int i=0; i<sz; i++){
if (mp.get(i).exists){
if (mp.get(2 * i + 1).exists){
System.out.println(i + " --> " + (2*i+1));
}
if (mp.get(2 * i + 2).exists){
System.out.println(i + " --> " + (2*i+2));
}
}
}
}
}
這是相同的解決方案簡化版。
沒有樹或地圖,只是一個布爾數組。 如果某個節點
k有孩子,這些孩子是2 * k + 1和2 * k + 2。
在最后一個循環中,在打印邊緣時還可以
構造一個實際的二叉樹。
import java.util.LinkedList;
import java.util.Queue;
public class Test32 {
public static void main(String[] args) {
String str = "110101000";
int sz = (int)Math.pow(2, str.length() + 1);
boolean exists[] = new boolean[sz];
Queue<Integer> visit = new LinkedList<Integer>();
visit.add(0); // id = 0;
if (str.charAt(0) == '1'){
exists[0] = true;
}
int j = 0;
int id = -1;
while (!visit.isEmpty()){
id = visit.poll();
if (str.charAt(j) == '1'){
exists[id] = true;
visit.add(2*id + 1);
visit.add(2*id + 2);
}else{
exists[id] = true;
}
j++;
}
// System.out.println("");
System.out.println("NODES:");
for (int i=0; i<sz; i++){
if (exists[i]){
System.out.println(i);
}
}
System.out.println("");
System.out.println("EDGES:");
for (int i=0; i<sz; i++){
if (exists[i]){
if (exists[2*i+1]){
System.out.println(i + " --> " + (2*i+1));
}
if (exists[2*i+2]){
System.out.println(i + " --> " + (2*i+2));
}
}
}
}
}
我認為從概念上講更簡單。
import java.util.LinkedList;
import java.util.Queue;
class WeirdBinaryTree
{
static class Node
{
private Node right;
private Node left;
private int weirdValue;
public void setWeirdValue(int value)
{
weirdValue=value;
}
}
private static Node makeTree(String str)throws Exception
{
char[] array=str.toCharArray();
Node root=new Node();
Queue<Node> list=new LinkedList();
list.add(root);
int i=0;
Queue<Node> nextList=new LinkedList<Node>();
while(!list.isEmpty())
{
if(array[i++]=='1')
{
Node temp=list.poll();
temp.left=new Node();
temp.right=new Node();
temp.setWeirdValue(1);
nextList.add(temp.left);
nextList.add(temp.right);
}
else
{
list.poll();
}
if(list.isEmpty())
{
list=nextList;
nextList=new LinkedList<Node>();
}
}
return root;
}
private static void postTraversal(Node localRoot)
{
if(localRoot!=null)
{
postTraversal(localRoot.left);
postTraversal(localRoot.right);
System.out.print(localRoot.weirdValue);
}
}
public static void main(String[] args)throws Exception
{
postTraversal(makeTree("111001000"));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.