已知二叉树的先序遍历和中序遍历,构建一颗二叉树。
例如:
先序遍历:1 2 3 4 5 6 7 8 9
中序遍历:3 2 5 4 1 6 8 7 9
因为先序遍历是先遍历根节点,再遍历左右子树,所以第一个就是根结点是1。中序遍历是先遍历完左子树再遍历根节点,所以中序遍历中1的左边是左子树,1的右边是右子树。
找到左子树、根节点和右子树后,再在先序遍历中查找左子树的根节点2,在中序遍历中找到2的左边就是这个结点的左子树,2个右边是这个结点的右子树。然后就这样一直递归下去。
最后构建出来的树就是这个样子:
具体代码
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();//节点的数目
in.nextLine();
char[] pre = in.nextLine().toCharArray();//前序遍历
char[] mid = in.nextLine().toCharArray();//中序遍历
Tree tree = new Tree(pre,mid);
tree.root = tree.RecreatTree(0, 0, n-1);
System.out.print("层序遍历:");
tree.LevelorderTraversal(tree.root);
}
}
class Tree{
static Node root;
char[] pre;
char[] mid;
public Tree(char[] pre, char[] mid) {
this.pre = pre;
this.mid = mid;
}
/**
* @param p1 pre数组的索引
* @param m1 m2 mid数组的索引
* @return 节点
*/
public Node RecreatTree(int p1,int m1,int m2) {
if(p1==pre.length) return null;
Node h = new Node(pre[p1]);
for (int i = m1; i <= m2; i++) {
if(mid[i] == pre[p1]) {//在中序遍历中找到pre[p1]的位置
//如果i==m1,左子树肯定为空
if(i!=m1)
h.leftNode = RecreatTree(p1+1, m1, i-1);
//如果i==m2,右子树肯定为空
if(i!=m2)
h.rightNode = RecreatTree(p1+i-m1+1, i+1, m2);
break;
}
}
return h;
}
//层序遍历
public void LevelorderTraversal(Node T) {
Queue<Node> queue = new LinkedList<Node>();
if(T==null) {
System.out.println("树为空");
return;
}
queue.offer(root);
while(!queue.isEmpty()) {
Node n = queue.poll();
if(n.leftNode!=null) {
queue.offer(n.leftNode);
}
if(n.rightNode!=null) {
queue.offer(n.rightNode);
}
System.out.print(n.c);
}
System.out.println();
}
}
class Node{
char c;
Node leftNode;
Node rightNode;
public Node(char c) {
this.c = c;
}
}
输入:
9
123456789
325416879
输出:
层序遍历:126347589
注:已知后序遍历和中序遍历类似,但是一定要知道中序遍历才可以。