java 二叉樹 實現 數據結構 筆試

筆試常考數據結構,所以最近複習了一下數據結構,今天覆習到了二叉樹,所以寫一下筆記。

順便做了一下測試,參考了網上的一些例子~~~


實現了:二叉樹的創建,二叉樹的遍歷(遞歸與非遞歸),求二叉樹深度,判斷是否爲完全二叉樹


不說了,直接上代碼。

結構大概這樣:


最主要的的類:

package binaryTreeTest;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/** 
 * @author  5354xyz
 * @version 2014-5-4 下午5:27:10 
 * @E5354xyz-mail: [email protected]
 */
public class BinaryTree {
	
	 public String nodevalue;   
     public BinaryTree leftchild, rightchild;  
     private Visit onVisitListener ;
     public BinaryTree()   
     { }   
     public BinaryTree(String value)   
     {   
         nodevalue = value;   
     }  
     public void setVisitListener(Visit onVisitListener)
     {
    	 this.onVisitListener = onVisitListener;
     }
     public void assignchild(BinaryTree left, BinaryTree right)//設定左右孩子   
     {   
         this.leftchild = left;   
         this.rightchild = right;   
     }  

     public boolean hasleftchild()//是否有左孩子   
     {   
        
             return (this.leftchild != null);   
          
     }  

     public boolean hasrightchild()//是否有右孩子   
     {   
         
             return (this.rightchild != null);   
           
     }  

     public boolean haschild()//是否有孩子   
     {   
          
             return hasleftchild() || hasrightchild();   
          
     } 
     
   /**
    * 計算深度   
    * 2014-5-4
    * 
    * @author:5354xyz
    */
     public int maxDepth(BinaryTree root)   
     {   
         if (root == null)   
         {   
             return 0;   
         }   
         else   
         {   
             int leftdepth = maxDepth(root.leftchild);//遞歸計算左孩子的深度   
             int rightdepth = maxDepth(root.rightchild);//遞歸計算右孩子的深度  

             if (leftdepth >= rightdepth)   
             {   
                 return leftdepth + 1;   
             }   
             else   
             {   
                 return rightdepth + 1;   
             }   
         }   
     }
     
     /**
      * 計算節點數
      * 2014-5-4
      * 
      * @author:5354xyz
      */
     public int count(BinaryTree subTree){  
         if(subTree==null){  
             return 0;  
         }else{  
             return 1+count(subTree.leftchild)  
                     +count(subTree.rightchild);  
         }  
     }
     
     /**
      * 求二叉樹第K層的節點個數
      * 2014-5-4
      * 
      * @author:5354xyz
      */
     int GetNodeNumKthLevel(BinaryTree pRoot, int k)  
     {  
         if(pRoot == null || k < 1)  
             return 0;  
         if(k == 1)  
             return 1;  
         int numLeft = GetNodeNumKthLevel(pRoot.leftchild, k-1); // 左子樹中k-1層的節點個數  
         int numRight = GetNodeNumKthLevel(pRoot.rightchild, k-1); // 右子樹中k-1層的節點個數  
         return (numLeft + numRight);  
     }
     
   /**
    * 前序遍歷  
    * 2014-5-4
    * 
    * @author:5354xyz
    */
     public void preOrder(BinaryTree subTree){  
         if(subTree!=null){  
        	 onVisitListener.visit(subTree);  
             preOrder(subTree.leftchild);  
             preOrder(subTree.rightchild);  
         }  
     }  
       
     /**
      * 中序遍歷  
      * 2014-5-4
      * 
      * @author:5354xyz
      */
     public void inOrder(BinaryTree subTree){  
         if(subTree!=null){  
             inOrder(subTree.leftchild);  
             onVisitListener.visit(subTree);   
             inOrder(subTree.rightchild);  
         }  
     }  
       
     /**
      * 後續遍歷  
      * 2014-5-4
      * 
      * @author:5354xyz
      */
     public void postOrder(BinaryTree subTree) {  
         if (subTree != null) {  
             postOrder(subTree.leftchild);  
             postOrder(subTree.rightchild);  
             onVisitListener.visit(subTree);   
         }  
     }
     
   /**
    * 前序遍歷的非遞歸實現  
    * 2014-5-4
    * 
    * @author:5354xyz
    */
     public void nonRecPreOrder(BinaryTree p){  
         Stack<BinaryTree> stack=new Stack<BinaryTree>();  
         if (p != null) {  
             stack.push(p);  
             while (!stack.empty()) {  
                 p = stack.pop();  
                 onVisitListener.visit(p); 
                 if (p.rightchild != null)  //先push,在棧底,實現了根左右
                     stack.push(p.rightchild);  
                 if (p.leftchild != null)  
                     stack.push(p.leftchild);  
             }  
         }   
     }  
     
     /** 
      * 非遞歸實現前序遍歷2 */  
     public void nonRecPreOrder2(BinaryTree p){    
    	 Stack<BinaryTree> stack=new Stack<BinaryTree>();   
    	 BinaryTree node = p;  
         while (node != null || stack.size() > 0) {  
             while (node != null) {//壓入所有的左節點,壓入前訪問它  
            	 onVisitListener.visit(node); 
                 stack.push(node);  
                 node = node.leftchild;  
             }  
             if (stack.size() > 0) {//  
                 node = stack.pop();  
                 node = node.rightchild;  
             }  
         }  
     } 
     /**
      * 中序遍歷的非遞歸實現  
      * 2014-5-4
      * 
      * @author:5354xyz
      */
     public void nonRecInOrder(BinaryTree p){  
         Stack<BinaryTree> stack =new Stack<BinaryTree>();  
         BinaryTree node =p;  
         while(node!=null||stack.size()>0){  
             //存在左子樹  
             while(node!=null){  
                 stack.push(node);  
                 node=node.leftchild;  
             }  
             //棧非空  
             if(stack.size()>0){  
                 node=stack.pop();  
                 onVisitListener.visit(node); 
                 node=node.rightchild;  
             }  
         }  
     }  
       
     //後序遍歷的非遞歸實現  
     public void noRecPostOrder(BinaryTree p){  
         Stack<BinaryTree> stack=new Stack<BinaryTree>();  
         BinaryTree node =p;  
         while(p!=null){  
             //左子樹入棧  
             for(;p.leftchild!=null;p=p.leftchild){  
                 stack.push(p);  
             }  
             //當前結點無右子樹或右子樹已經輸出  
             while(p!=null&&(p.rightchild==null||p.rightchild==node)){  
            	 onVisitListener.visit(p);
                 //紀錄上一個已輸出結點  
                 node =p;  
                 if(stack.empty())  
                     return;  
                 p=stack.pop();  
             }  
             //處理右子樹  
             stack.push(p);  
             p=p.rightchild;  
         }  
     }
     
     /**
      * 按層遍歷二叉樹
      * 2014-5-4
      * 
      * @author:5354xyz
      */
     public void levelTraverse(BinaryTree bTree)
     {  
         if(bTree == null )  
             return;  
         Queue<BinaryTree> queue = new LinkedList<BinaryTree>();  
         queue.offer(bTree);  
         while(!queue.isEmpty())  
         {  
        	 BinaryTree pNode = queue.poll();  
               
        	 onVisitListener.visit(pNode); // 訪問節點  
             if(pNode.leftchild != null)  
            	 queue.offer(pNode.leftchild);  
             if(pNode.rightchild != null)  
            	 queue.offer(pNode.rightchild);  
         }  
         return;  
     } 
     /**
      * 判斷二叉樹是否爲完全二叉樹
      * 2014-5-4
      * 
      * @author:5354xyz
      */
     boolean IsCompleteBinaryTree(BinaryTree pRoot)  
     {  
         if(pRoot == null)  
             return false;  
         Queue<BinaryTree> q = new LinkedList<BinaryTree>();;  
         q.offer(pRoot);  
         boolean mustHaveNoChild = false;  
         boolean result = true;  
         while(!q.isEmpty())  
         {  
        	 BinaryTree pNode = q.poll();  
             if(mustHaveNoChild) // 已經出現了有空子樹的節點了,後面出現的必須爲葉節點(左右子樹都爲空)  
             {  
                 if(pNode.leftchild != null || pNode.rightchild != null)  
                 {  
                     result = false;  
                     break;  
                 }  
             }  
             else  
             {  
                 if(pNode.leftchild != null && pNode.rightchild != null)  
                 {  
                     q.offer(pNode.leftchild);  
                     q.offer(pNode.rightchild);  
                 }  
                 else if(pNode.leftchild != null && pNode.rightchild == null)  
                 {  
                     mustHaveNoChild = true;  
                     q.offer(pNode.leftchild);  
                 }  
                 else if(pNode.leftchild == null && pNode.rightchild != null)  
                 {  
                     result = false;  
                     break;  
                 }  
                 else  
                 {  
                     mustHaveNoChild = true;  
                 }  
             }  
         }  
         return result;  
     } 

}

測試程序:

package binaryTreeTest;
/** 
 * @author  5354xyz
 * @version 2014-5-4 下午5:26:20 
 * @E5354xyz-mail: [email protected]
 */
public class BinaryTreeTest implements Visit
{

	/**
	 * 2014-5-4
	 * 
	 * @author:5354xyz
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		BinaryTree node_a = new BinaryTree("a");   
		BinaryTree node_b = new BinaryTree("b");   
		BinaryTree node_c = new BinaryTree("c");   
		BinaryTree node_d = new BinaryTree("d");   
		BinaryTree node_e = new BinaryTree("e");   
		BinaryTree node_f = new BinaryTree("f");   
		BinaryTree node_g = new BinaryTree("g");   
		BinaryTree node_h = new BinaryTree("h");   
		BinaryTree node_i = new BinaryTree("i");
		BinaryTree node_j = new BinaryTree("j");
        //構造一棵二叉樹   
        node_a.assignchild(node_b, node_c);   
        node_b.assignchild(node_d, node_e);   
        node_c.assignchild(node_f, node_g);   
        node_e.assignchild(node_h, node_i);
        node_h.assignchild(node_j, null);
        
        /* 					A
         * 			B				C
         * 	    D  		 E   	F    	G
         * 			   H   I
         * 			 j
         * 
         */
        BinaryTreeTest binaryTreeTest =new BinaryTreeTest();
        node_a.setVisitListener(binaryTreeTest);
        //輸出樹的深度
        System.out.println("二叉樹的深度:"+node_a.maxDepth(node_a));
        System.out.println("二叉樹的總結點數:"+node_a.count(node_a));
        int ceng=4;
        System.out.println("二叉樹的第"+ceng+"層結點數:"+node_a.GetNodeNumKthLevel(node_a,ceng));
        //這個跟
        System.out.println("是否是完全二叉樹呢?"+node_a.IsCompleteBinaryTree(node_a));
        //先序遍歷
        node_a.preOrder(node_a);
        System.out.print(" 遞歸|非遞歸     ");
        node_a.nonRecPreOrder(node_a);
        System.out.print(" 非遞歸 2 ");
        node_a.nonRecPreOrder2(node_a);
        System.out.println("先序遍歷");
        //中序遍歷
        node_a.inOrder(node_a);
        System.out.print(" 遞歸|非遞歸     ");
        node_a.nonRecInOrder(node_a);
        System.out.println("中序遍歷");
        //後序遍歷
        node_a.postOrder(node_a);
        System.out.print(" 遞歸|非遞歸     ");
        node_a.noRecPostOrder(node_a);
        System.out.println("後序遍歷");
        //按層遍歷
        node_a.levelTraverse(node_a);
        System.out.println("按層遍歷");
        
	}

		@Override
		public void visit(BinaryTree binaryTreeNode) {
			// TODO Auto-generated method stub
			System.out.print(binaryTreeNode.nodevalue+" ");
		}
	
}
最後還有個訪問的接口:

package binaryTreeTest;
/** 
 * @author  5354xyz
 * @version 2014-5-4 下午5:37:21 
 * @E5354xyz-mail: [email protected]
 */
public interface Visit {
	
	/**
	 * visit接口
	 */
	public void visit(BinaryTree binaryTreeNode);

}


測試的效果:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章