编程之美——3.9、重建二叉树 and 3.10、分层遍历二叉树
(Java and C++)
给定一个前序和中序变量的结果,写一个算法重建这棵树:如:
1、根据前序遍历结果和中序遍历结果重建二叉树:
前序: a b d c e f
中序: d b a e c f
前序遍历的每一个节点,都是当前子树的根节点,同时,以对应的节点
为边界,就会把前序遍历的结果分为左子树和右子树。
a是前序中第一个节点,以a为中界,把中序的结果分成:
左:db
右:ecf
对于db,由于在前序中b在d前面,所以,b是d的父亲。
对于ecf,前序中c在前面,c为父亲,c把e和f分开。
2、从上之下按层遍历二叉树:
Java代码:
import java.util.LinkedList;
import java.util.Queue;
import java.util.Vector;
public class Main {
static Main instance =new Main();
public static void main(String[] arg){
char[] preOrder={'a','b','d','c','e','f'};
char[] inOrder ={'d','b','a','e','c','f'};
Node root = buildTree(preOrder,inOrder,0,0,preOrder.length,null);
preOrderTraversal(root);
System.out.println("\n===============================");
inOrderTraversal(root);
System.out.println("\n===============================");
traversalAtLevel(root, 2);
System.out.println("\n===============================");
TraversalByLevel(root, 3);
System.out.println("\n===============================");
TraversalByLevelUnknowDeep(root);
System.out.println("\n===============================");
TraversalByLevel_2(root);
System.out.println("\n===============================");
System.out.println("BFS_000");
BFS_000(root);
System.out.println("BFS_1");
BFS_1(root);
System.out.println("BFS_2");
BFS_2(root);
}
public static Node buildTree(char[] preOrder,char[] inOrder
,int pPreOrder ,int pInOrder
,int treeLen ,Node root){
if(root ==null){
root = instance.new Node(preOrder[pPreOrder]);//前序遍历的第一个节点作为Root
}
//! 如果当前的树长度为1,那么已经是最后一个节点了
if(treeLen==1){
return root;
}
int pInOrder_bak =pInOrder;
while(inOrder[pInOrder]!= preOrder[pPreOrder]){
pInOrder++;
if(pInOrder-pInOrder_bak>treeLen){
break;
}
}
int leftLength =pInOrder-pInOrder_bak;
int rightlength =treeLen- leftLength -1;
if(leftLength>0){
root.left =buildTree(preOrder,inOrder,pPreOrder+1,pInOrder_bak,leftLength,root.left);
}
if(rightlength>0){
root.right=buildTree(preOrder,inOrder,pPreOrder+leftLength+1,pInOrder_bak+leftLength+1,rightlength,root.right);
}
return root;
}
//前序遍历
public static void preOrderTraversal(Node node){
if(node!=null){
System.out.print(node.getVal()+" ");
if(node.left!=null){
preOrderTraversal(node.left);
}
if(node.right != null){
preOrderTraversal(node.right);
}
}
}
//中序遍历
public static void inOrderTraversal(Node node){
if(node!=null){
if(node.left != null){
inOrderTraversal(node.left);
}
System.out.print(node.getVal()+" ");
if(node.right !=null){
inOrderTraversal(node.right);
}
}
}
//特定层输出
public static int traversalAtLevel(Node root,int level){
//节点为空 或者 层数已经小于0,直接返回
if(root == null || level <0){
return 0;
}
//Level==0,说明已经减了,减了level次到达想要输出的层,输出。
//指定层才输出的判断条件
if(level == 0){
System.out.print(root.val+" ");
return 1;
}
return traversalAtLevel(root.left , level-1) //去下一层的左孩子
+traversalAtLevel(root.right, level-1);//去下一层的右孩子
}
//已经深度的层遍历
public static void TraversalByLevel(Node root ,int deep){
for(int level=0;level<deep;level++){
traversalAtLevel(root, level);
if(level!=deep-1)
System.out.println();
}
}
//未知深度的层遍历
//前提是traversalAtLevel(root, level)有返回值,以判断是否成功遍历了特定一行(行非空)
public static void TraversalByLevelUnknowDeep(Node root){
boolean b=false;
for(int level=0; ;level++){
if(traversalAtLevel(root, level) == 0){
b =true;
break;
}
if(!b){
System.out.println();
}
}
}
//不使用递归,提升效率的的层遍历
//使用vector容器来储存n个节点信息,并用一个游标变量last记录前一层的访问结束条
public static void TraversalByLevel_2(Node root){
if(root == null){
return ;
}
Vector<Node> vc =new Vector<Node>();
vc.add(root);
int last =vc.size();
int cur =0;
while(cur<vc.size()){
last =vc.size();
while(cur < last){
System.out.print(vc.get(cur).val+" ");
if(vc.get(cur).left != null){
vc.add(vc.get(cur).left);
}
if(vc.get(cur).right != null){
vc.add(vc.get(cur).right);
}
cur++;
}
System.out.println();
}
}
//使用Queue将二叉树按层顺序加入到队列中,再出队,这里没有换行,关键是如何换行输出
public static void BFS_000(Node root){
queue1.clear();
if(root == null){
return ;
}
queue1.add(root);
while (!queue1.isEmpty()){
if(queue1.peek().left !=null){
queue1.add(queue1.peek().left);
}
if(queue1.peek().right != null){
queue1.add(queue1.peek().right);
}
System.out.print(queue1.poll().val+" ");
}
}
static Queue<Node> queue1 =new LinkedList<Node>();
static Queue<Node> queue2 =new LinkedList<Node>();
//两个Queue来实现换行,queue1存放当前输出行,queue2存放下一行
public static void BFS_1(Node root){
queue1.clear();
queue2.clear();
if(root == null){
return ;
}
queue1.add(root);
while (!queue1.isEmpty()){
if(queue1.peek().left !=null){
queue2.add(queue1.peek().left);
}
if(queue1.peek().right != null){
queue2.add(queue1.peek().right);
}
System.out.print(queue1.poll().val+" ");
if(queue1.isEmpty()){
System.out.println();
while(!queue2.isEmpty()){
queue1.add(queue2.poll());
}
}
}
}
//类比使用cur,在每行结束的时候加一个标记节点‘@’
public static void BFS_2(Node root){
if(root == null){
return ;
}
queue1.clear();
queue1.add(root);
Node changLine =instance.new Node('@');
queue1.add(changLine);
while(queue1.peek()!= changLine){
if( queue1.peek().left!= null){
queue1.add(queue1.peek().left);
}
if( queue1.peek().right !=null){
queue1.add(queue1.peek().right);
}
System.out.print(queue1.poll().val+" ");
if(queue1.peek() ==changLine){
queue1.poll();
System.out.println();
queue1.add(changLine);
}
}
}
class Node{
char val;
Node left;
Node right;
public Node(char c){
val =c;
left =null;
right=null;
}
public char getVal() {
return val;
}
public void setVal(char val) {
this.val = val;
}
}
}
C++:
分层遍历的另两个实现:http://www.cnblogs.com/miloyip/archive/2010/05/12/binary_tree_traversal.html
http://blog.csdn.net/luyafei_89430/article/details/12967411
http://www.cnblogs.com/youxin/p/3288261.html