编程之美——3.9重建二叉树和3.10分层遍历二叉树(Java and C++)

编程之美——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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值