二叉樹詳解


   樹是一種比較重要的數據結構,尤其是二叉樹。二叉樹是一種特殊的樹,在二叉樹中每個節點最多有兩個子節點,一般稱為左子節點和右子節點(或左孩子和右孩子),並且二叉樹的子樹有左右之分,其次序不能任意顛倒。本篇博客將詳細為大家解析二叉樹。

 

首先介紹兩個概念:

滿二叉樹:在一棵二叉樹中,如果所有分支結點都有左孩子和右孩子結點,並且葉子結點都集中在二叉樹的最下層,這樣的樹叫做滿二叉樹

 

如:



 

完全二叉樹:若二叉樹中最多只有最下面兩層的結點的度數可以小於2,並且最下面一層的葉子結點都是依次排列在該層最左邊的位置上,則稱為完全二叉樹

 

如:



 區別:滿二叉樹是完全二叉樹的特例,因為滿二叉樹已經滿了,而完全並不代表滿。所以形態你也應該想象出來了吧,滿指的是出了葉子節點外每個節點都有兩個孩子,而完全的含義則是最后一層沒有滿,並沒有滿。

 

      

二叉樹的鏈式存儲結構是一類重要的數據結構,定義結果為:

Cpp代碼   收藏代碼
  1. //定義樹的結構  
  2. struct node  
  3. {  
  4.     node * lchild;  
  5.     node * rchild;  
  6.     string data;  
  7.     //初始化  
  8.     node()  
  9.     {  
  10.         lchild=rchild=NULL;  
  11.     }  
  12. };  

 

二叉樹的建立

 

首先我們用戶輸入生成一棵二叉樹,要生的的二叉樹如下圖所示:

#代表空結點。

 下面我們根據上面圖中所示的二叉樹,利用先序依次輸入ABDG###E#H##C#F##(即先序遍歷)

生成二叉樹的代碼如下:

Cpp代碼   收藏代碼
  1. //二叉樹生成--先序遍歷輸入要生成的二叉樹數據,#代表空結點  
  2. void CreateTree(node * & root)  
  3. {  
  4.      char data;  
  5.      cin>>data;  
  6.      if(data!='#')  
  7.      {  
  8.          root=new node;  
  9.          root->data=data;  
  10.            
  11.          CreateTree(root->lchild);  
  12.           
  13.          CreateTree(root->rchild);  
  14.           
  15.      }  
  16. }  

 

二叉樹節點查找

采用遞歸的方法在二叉樹root里查找只為aim的結點,若找到此節點則返回其指針,否則返回NULL

查找代碼如下:

Cpp代碼   收藏代碼
  1. //檢查二叉樹是否包含數據aim,有則返回其指針  
  2. node * Findnode(node * & root,string aim)  
  3. {  
  4.     node * p;  
  5.     if(root==NULL)//空樹  
  6.         return NULL;  
  7.     else if(root->data==aim)  
  8.         return root;  
  9.     else  
  10.     {     
  11.         p=Findnode(root->lchild,aim);  
  12.         if(p!=NULL)  
  13.             return p;  
  14.         else  
  15.             return Findnode(root->rchild,aim);     
  16.     }  
  17. }  

 這里解釋一下遞歸中的return的意思:

return 對當前函數來說是結束了,對調用它的父函數來說你這個函數執行完成了,父函數就會接着執行下一語句。
沒想到父函數馬上又遇到一個return,父函數結束了,對爺爺函數來說父函數執行完成了,爺爺函數就接着執行下一個語句

 

二叉樹遍歷

1.先序遍歷

先序遍歷過程是:

1)訪問根結點

2)先序遍歷左子樹

3)先序遍歷右子樹

先序遍歷代碼為:

 

Cpp代碼   收藏代碼
  1. void  PreOrder(node * root)//先序遍歷  
  2. {  
  3.     if(root!=NULL)  
  4.     {  
  5.         cout<<root->data;  
  6.         PreOrder(root->lchild);  
  7.         PreOrder(root->rchild);  
  8.     }  
  9. }  

 

2.中序遍歷

中序遍歷過程是:1)中序遍歷左子樹

2)訪問根結點

3)中序遍歷右子樹

 

中序遍歷的代碼:

 

Cpp代碼   收藏代碼
  1. void  InOrder(node * root)//中序遍歷  
  2. {  
  3.     if(root!=NULL)  
  4.     {  
  5.           
  6.         InOrder(root->lchild);  
  7.         cout<<root->data;  
  8.         InOrder(root->rchild);  
  9.     }  
  10. }  

 

3.后續遍歷后序遍歷過程是:

1)后序遍歷左子樹

2)后序遍歷右子樹3)訪問根結點

 

后序遍歷代碼為:

 

Cpp代碼   收藏代碼
  1. void  PostOrder(node * root)//后序遍歷  
  2. {  
  3.     if(root!=NULL)  
  4.     {  
  5.           
  6.         PostOrder(root->lchild);  
  7.         PostOrder(root->rchild);  
  8.         cout<<root->data;  
  9.     }  
  10. }  

 

二叉樹高度計算

遞歸解法:
(1)如果二叉樹為空,二叉樹的深度為0
(2)如果二叉樹不為空,二叉樹的深度 = max(左子樹深度, 右子樹深度) + 1

代碼如下:

Cpp代碼   收藏代碼
  1. int NodeHeight(node * root)//計算二叉樹高度  
  2. {  
  3.     int lchild,rchlid;  
  4.     if(root==NULL)  
  5.         return 0;  
  6.     else  
  7.     {  
  8.         lchild=NodeHeight(root->lchild);  
  9.         rchlid=NodeHeight(root->rchild);  
  10.         return (lchild>rchlid)?(lchild+1):(rchlid+1);  
  11.     }  
  12. }  

 

 

輸出二叉樹葉子節點

遞歸解法:
參考代碼如下:

Cpp代碼   收藏代碼
  1. void Showleaf(node * root)  
  2. {  
  3.     if(root!=NULL)  
  4.     {  
  5.         if(root->lchild==NULL&&root->rchild==NULL)  
  6.             cout<<root->data;  
  7.         Showleaf(root->lchild);//輸出左子樹葉子節點  
  8.         Showleaf(root->rchild);//輸出右子樹葉子節點  
  9.     }  
  10. }  

 

運行結果為:



 

附上源代碼地址:https://github.com/longpo/algorithm/tree/master/Btree

 

遞歸分析

上面源代碼中,大量運用了遞歸算法,

下面我們來分析其中一個遞歸的過程。

二叉樹結構為:



 利用先序遍歷,即代碼為:

Cpp代碼   收藏代碼
  1. void  PreOrder(node * root)//先序遍歷  
  2. {  
  3.     if(root!=NULL)  
  4.     {  
  5.         cout<<root->data;  
  6.         PreOrder(root->lchild);  
  7.         PreOrder(root->rchild);  
  8.     }  
  9. }  

 

畫出其運行狀態圖:



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM