二叉樹的定義
二叉樹是每個節點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(left subtree)和“右子樹”(right subtree)。二叉樹常被用於實現二叉查找樹和二叉堆。
二叉樹的每個結點至多只有二棵子樹(不存在度大於2的結點),二叉樹的子樹有左右之分,次序不能顛倒。
特殊二叉樹
1. 斜樹
所有結點都只有左子樹的二叉樹叫左斜樹,所有結點都只有右子樹的二叉樹叫右斜樹。斜樹的每一層都只有一個結點,結點的個數與斜樹的深度相同。
2. 滿二叉樹
在一棵二叉樹中,如果所有分支結點都存在左子樹和右子樹,並且所有葉子結點都在同一層上,這樣的二叉樹稱為滿二叉樹。(上圖中所示的二叉樹,就是一棵滿二叉樹)
3. 完全二叉樹
對一棵具有n個結點的二叉樹按層序編號,如果編號為i(1≤i≤n)的結點與同樣深度的滿二叉樹中的編號為i的結點在二叉樹中的位置完全相同,則這棵二叉樹稱為完全二叉樹。
二叉樹的性質
性質1:在二叉樹的第i層上至多有2i-1個結點(i≥1)。(數學歸納法可證)
性質2:深度為k的二叉樹最多有2k-1個結點(k≥1)。(由性質1,通過等比數列求和可證)
性質3:一棵二叉樹的葉子結點數為n0,度為2的結點數為n2,則n0 = n2 + 1。
證:結點總數n = n0 + n1 + n2。設B為分支總數,因為除根節點外,其余結點都有一個分支進入,所以n = B + 1。又因為分支是由度為1或2的結點射出,所以B = n1 + 2n2。綜上:n = n0 + n1 + n2 = B + 1 = n1 + 2n2 + 1,得出:n0 = n2 + 1。
性質4:具有n個結點的完全二叉樹的深度為floor(log2n) + 1 。
性質5:如果對一棵有n個結點的完全二叉樹(其深度為floor(log2n) + 1 )的結點按層序編號,則對任一結點i(1≤i≤n)有:
(1) 如果i = 1,則結點i是二叉樹的根,無雙親;如果i > 1,則其雙親PARENT(i)是結點 floor((i)/2)。
(2)如果2i > n,則結點i無左孩子;否則其左孩子LCHILD(i)是結點2i。
(3)如果2i + 1 > n,則結點i無右孩子;否則其右孩子RCHILD(i)是結點2i + 1。
二叉樹的存儲
1. 順序存儲結構
二叉樹可以用一維數組或線性表來存儲,而且如果這是完全二叉樹,這種方法不會浪費空間。
並且這種緊湊排列,如果一個結點的索引為i,則它的子結點能在索引2i+1和2i+2找到,並且它的父節點(如果有)能在索引floor((i-1)/2)找到(假設根節點的索引為0)。
對於一般的二叉樹,其層序編號不能反映出邏輯關系,但是可以將其按照完全二叉樹編號,只不過把不存在的結點設置為NULL即可。但這么做有一個問題,就是會浪費存儲空間。最壞情況下,一個深度為k的斜樹(只有k個結點),卻需要長度為2k-1的一維數組。所以順序存儲結構一般只用於完全二叉樹。
2. 鏈式存儲結構
每個結點含有一個數據域和兩個指針域(分別指向左右子樹)。
// 二叉樹的二叉鏈表存儲表示
typedef struct BiTNode
{
TElemType data;
struct BiTNode *lchild,*rchild; // 左右孩子指針
}BiTNode,*BiTree;
利用這種結點結構所得的二叉樹存儲結構稱之為二叉鏈表。在二叉鏈表中,如果想找到某個結點的雙親,需要從根節點開始遍歷,所以有時為了便於找到結點的雙親,還可以在結點結構中增加一個指向其雙親結點的指針域,相應的二叉樹存儲結構稱之為三叉鏈表。
Reference:
[1] 《大話數據結構》
[2] 《數據結構 嚴蔚敏》
[3] wikipedia(二叉樹):http://zh.wikipedia.org/wiki/%E4%BA%8C%E5%8F%89%E6%A0%91