樹的定義
樹是n(n>=0)個(gè)元素的的有限集合。在任何一顆非空樹中:
- 有且僅有一個(gè)節(jié)點(diǎn)被稱為根節(jié)點(diǎn),在整棵樹最上面
- 當(dāng) n>1時(shí),除根節(jié)點(diǎn)以外的其他節(jié)點(diǎn)可被分為 m(m>0)個(gè)互不相交的有限集合T1...Tn,其中每個(gè)集合本身又是一顆樹,并且稱為根的子數(shù)。
樹的相關(guān)術(shù)語(yǔ)
- 節(jié)點(diǎn):樹中的數(shù)據(jù)元素稱為節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)都保存了該節(jié)點(diǎn)的信息,即數(shù)據(jù)元素和數(shù)據(jù)項(xiàng)與數(shù)據(jù)元素之間的關(guān)系
- 節(jié)點(diǎn)的度:節(jié)點(diǎn)擁有子樹的個(gè)數(shù)
二叉樹
樹型結(jié)構(gòu)中有一種特殊的樹叫做二叉樹,二叉樹的結(jié)構(gòu)也比較簡(jiǎn)單,規(guī)律性較強(qiáng),并且可以證明,即使一般的樹也能轉(zhuǎn)化成二叉樹。而且許多實(shí)際問題抽象出來(lái)的數(shù)據(jù)結(jié)構(gòu)往往就是二叉樹的形式。
二叉樹的定義
二叉樹是個(gè)有限元素的集合,該集合為空或者由一個(gè)根和兩個(gè)互不相交的左子樹和右子樹組成。在二叉樹中,一個(gè)元素也稱為一個(gè)節(jié)點(diǎn)。
二叉樹基本特征
- 每個(gè)節(jié)點(diǎn)最多只有兩棵子樹,即不存在度大于 2 的節(jié)點(diǎn)
- 左子樹和右子樹次序不能顛倒,即二叉樹是有序樹,而且哪怕只有
一顆子樹,也要區(qū)分是左子樹還是右子樹。
二叉樹的 5 種基本形態(tài)
- 空集
- 根有兩顆子樹
- 根只有一顆子樹(左子樹或右子樹)
- 根沒有子樹
二叉樹的性質(zhì)
- 在二叉樹的第 i 層上至多有 **2^(i-1) **個(gè)結(jié)點(diǎn) (i>0)
一棵深度為 k 的二叉樹中,最多有 2^k-1 個(gè)結(jié)點(diǎn)
具有 n 個(gè)結(jié)點(diǎn)的完全二叉樹的深度 k 為 [log2n]+1
對(duì)于一棵非空的二叉樹,如果葉子結(jié)點(diǎn)數(shù)為 n0,度為 2 的結(jié)點(diǎn)數(shù)為 n2,
則 n0 = n2+1-
對(duì)于具有n個(gè)節(jié)點(diǎn)的完全二叉樹,如果按照從上至下和從左至右的順序?qū)Χ鏄渲兴薪Y(jié)點(diǎn)進(jìn)行從1的編號(hào),則對(duì)于任意的序號(hào)為i結(jié)點(diǎn),有:
如果 i>1,則序號(hào)為 i 的結(jié)點(diǎn)的雙親結(jié)點(diǎn)為 i/2,如果 i==1,則序號(hào)為 i 的結(jié)點(diǎn)是根節(jié)點(diǎn),無(wú)雙親結(jié)點(diǎn)
如果 2i<=n,則序號(hào)為i的結(jié)點(diǎn)的左孩子節(jié)點(diǎn)的序號(hào)為 2i,否則i結(jié)點(diǎn)無(wú)左孩子
如果 2i+1<=n,則序號(hào)為i的結(jié)點(diǎn)的右孩子節(jié)點(diǎn)的序號(hào)為 2i,否則i結(jié)點(diǎn)無(wú)右孩子注意:性質(zhì) 1,2,4 所有二叉樹都通用,性質(zhì) 3,5 只有完全二叉樹適用
二叉樹的存儲(chǔ)結(jié)構(gòu)
- 順序存儲(chǔ)結(jié)構(gòu)
- 鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)
順序存儲(chǔ)結(jié)構(gòu)
一組連續(xù)的存儲(chǔ)單元依次從上至下,從左至右存儲(chǔ)二叉樹上的節(jié)點(diǎn)元素。對(duì)于完全二叉樹來(lái)說(shuō),樹中結(jié)點(diǎn)的序號(hào)都是按照從上至下,從左至右進(jìn)行編排的,所以結(jié)點(diǎn)的序號(hào)可以唯一的反映節(jié)點(diǎn)之間的邏輯關(guān)系(性質(zhì)5)
存儲(chǔ)在數(shù)組中,數(shù)組下標(biāo)從零開始
數(shù)組下標(biāo) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
數(shù)據(jù) | A | B | C | D | E | F | G | H | I |
如果是一般的二叉樹的話,如果我在對(duì)他進(jìn)行從上至下,從左至右進(jìn)行編號(hào)時(shí)就不能很好的反映數(shù)組元素之間的關(guān)系了,如果我們進(jìn)行適當(dāng)?shù)母脑?,通過添加一些結(jié)點(diǎn),把他補(bǔ)成一顆完全二叉樹,那么再進(jìn)行編號(hào),就可以進(jìn)行順序存儲(chǔ)了
數(shù)組下標(biāo) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|
數(shù)據(jù) | A | B | C | D | E | 0 | 0 | 0 | 0 | 0 | F |
此可以看出,這樣的存儲(chǔ)方式,會(huì)造成很多空間的浪費(fèi),而且如果要進(jìn)行對(duì)樹上元素進(jìn)行刪除、插入操作需要移動(dòng)大量的數(shù)據(jù)元素,因此二叉樹不宜采用順序存儲(chǔ)結(jié)構(gòu)
二叉樹的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)
用類似于鏈表的存儲(chǔ)方法來(lái)存儲(chǔ)樹上元素的邏輯關(guān)系,即用指針來(lái)表示元素之間的邏輯關(guān)系
data 是數(shù)據(jù)域,leftChild 和 rightChild 是指針域,leftChild 是指向左兒子的指針,rightChild 是指向右兒子的指針,當(dāng)左兒子或右兒子為空時(shí),相應(yīng)的指針域也為空
代碼描述
//存儲(chǔ)的數(shù)據(jù)類型
typedef char DataType
typedef struct node
{
DataType data; //數(shù)據(jù)域
struct node* leftChild; //左兒子
struct node* rightChild; //右兒子
}BinNode;
typedef BinNode* BinTree;
這是二叉鏈表的定義,除此之外還有三叉鏈表,三叉鏈表比起二叉鏈表多了一個(gè)指向雙親結(jié)點(diǎn)的指針域,如圖所示
代碼描述
//存儲(chǔ)的數(shù)據(jù)類型
typedef char DataType
typedef struct node
{
DataType data; //數(shù)據(jù)域
struct node* leftChild; //左兒子
struct node* rightChild; //右兒子
struct node* parent; //雙親
}BinNode;
typedef BinNode* BinTree;
在二叉樹中有兩種特殊的二叉樹 >>> 滿二叉樹和完全二叉樹
滿二叉樹
在一棵樹中所有的分支節(jié)點(diǎn)都存在左子樹和右子樹,并且所有的葉子節(jié)點(diǎn)都在同一層上,這樣的二叉樹稱為滿二叉樹。
完全二叉樹
一棵深度為 k 且具有 n 個(gè)節(jié)點(diǎn)的二叉樹,對(duì)樹中節(jié)點(diǎn)按從上至下,從左至右的順序進(jìn)行編號(hào),當(dāng)且僅當(dāng)節(jié)點(diǎn)都與深度為 k 的滿二叉樹中編號(hào)從 1 至 n 的節(jié)點(diǎn)一一對(duì)應(yīng)
時(shí),才稱這棵二叉樹為完全二叉樹。顯然滿二叉樹也是完全二叉樹的一種。
完全二叉樹的特點(diǎn):
- 葉子節(jié)點(diǎn)只可能在層次最大的兩層上出現(xiàn)
- 對(duì)任一節(jié)點(diǎn),其右分支下的兒子的最大層次為 h,則其左分支下的兒子最大層次為 h 或 h+1