樹是一種比較重要的數據結構,尤其是二叉樹。二叉樹是一種特殊的樹,在二叉樹中每個節點最多有兩個子節點,一般稱為左子節點和右子節點(或左孩子和右孩子),並且二叉樹的子樹有左右之分,其次序不能任意顛倒。本篇博客將詳細為大家解析二叉樹。
首先介紹兩個概念:
滿二叉樹:在一棵二叉樹中,如果所有分支結點都有左孩子和右孩子結點,並且葉子結點都集中在二叉樹的最下層,這樣的樹叫做滿二叉樹
如:

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

區別:滿二叉樹是完全二叉樹的特例,因為滿二叉樹已經滿了,而完全並不代表滿。所以形態你也應該想象出來了吧,滿指的是出了葉子節點外每個節點都有兩個孩子,而完全的含義則是最后一層沒有滿,並沒有滿。
二叉樹的鏈式存儲結構是一類重要的數據結構,定義結果為:
- //定義樹的結構
- struct node
- {
- node * lchild;
- node * rchild;
- string data;
- //初始化
- node()
- {
- lchild=rchild=NULL;
- }
- };
二叉樹的建立
首先我們用戶輸入生成一棵二叉樹,要生的的二叉樹如下圖所示:
#代表空結點。
下面我們根據上面圖中所示的二叉樹,利用先序依次輸入ABDG###E#H##C#F##(即先序遍歷)
生成二叉樹的代碼如下:
- //二叉樹生成--先序遍歷輸入要生成的二叉樹數據,#代表空結點
- void CreateTree(node * & root)
- {
- char data;
- cin>>data;
- if(data!='#')
- {
- root=new node;
- root->data=data;
- CreateTree(root->lchild);
- CreateTree(root->rchild);
- }
- }
二叉樹節點查找
采用遞歸的方法在二叉樹root里查找只為aim的結點,若找到此節點則返回其指針,否則返回NULL
查找代碼如下:
- //檢查二叉樹是否包含數據aim,有則返回其指針
- node * Findnode(node * & root,string aim)
- {
- node * p;
- if(root==NULL)//空樹
- return NULL;
- else if(root->data==aim)
- return root;
- else
- {
- p=Findnode(root->lchild,aim);
- if(p!=NULL)
- return p;
- else
- return Findnode(root->rchild,aim);
- }
- }
這里解釋一下遞歸中的return的意思:
return 對當前函數來說是結束了,對調用它的父函數來說你這個函數執行完成了,父函數就會接着執行下一語句。
沒想到父函數馬上又遇到一個return,父函數結束了,對爺爺函數來說父函數執行完成了,爺爺函數就接着執行下一個語句
二叉樹遍歷
1.先序遍歷
先序遍歷過程是:
1)訪問根結點
2)先序遍歷左子樹
3)先序遍歷右子樹
先序遍歷代碼為:
- void PreOrder(node * root)//先序遍歷
- {
- if(root!=NULL)
- {
- cout<<root->data;
- PreOrder(root->lchild);
- PreOrder(root->rchild);
- }
- }
2.中序遍歷
中序遍歷過程是:1)中序遍歷左子樹
2)訪問根結點
3)中序遍歷右子樹
中序遍歷的代碼:
- void InOrder(node * root)//中序遍歷
- {
- if(root!=NULL)
- {
- InOrder(root->lchild);
- cout<<root->data;
- InOrder(root->rchild);
- }
- }
3.后續遍歷后序遍歷過程是:
1)后序遍歷左子樹
2)后序遍歷右子樹3)訪問根結點
后序遍歷代碼為:
- void PostOrder(node * root)//后序遍歷
- {
- if(root!=NULL)
- {
- PostOrder(root->lchild);
- PostOrder(root->rchild);
- cout<<root->data;
- }
- }
二叉樹高度計算
遞歸解法:
(1)如果二叉樹為空,二叉樹的深度為0
(2)如果二叉樹不為空,二叉樹的深度 = max(左子樹深度, 右子樹深度) + 1
代碼如下:
- int NodeHeight(node * root)//計算二叉樹高度
- {
- int lchild,rchlid;
- if(root==NULL)
- return 0;
- else
- {
- lchild=NodeHeight(root->lchild);
- rchlid=NodeHeight(root->rchild);
- return (lchild>rchlid)?(lchild+1):(rchlid+1);
- }
- }
輸出二叉樹葉子節點
遞歸解法:
參考代碼如下:
- void Showleaf(node * root)
- {
- if(root!=NULL)
- {
- if(root->lchild==NULL&&root->rchild==NULL)
- cout<<root->data;
- Showleaf(root->lchild);//輸出左子樹葉子節點
- Showleaf(root->rchild);//輸出右子樹葉子節點
- }
- }
運行結果為:

附上源代碼地址:https://github.com/longpo/algorithm/tree/master/Btree
遞歸分析
上面源代碼中,大量運用了遞歸算法,
下面我們來分析其中一個遞歸的過程。
二叉樹結構為:

利用先序遍歷,即代碼為:
- void PreOrder(node * root)//先序遍歷
- {
- if(root!=NULL)
- {
- cout<<root->data;
- PreOrder(root->lchild);
- PreOrder(root->rchild);
- }
- }
畫出其運行狀態圖:


