數據結構|二叉樹基本篇

二叉樹

1 什麼是樹以及樹的相關概念

樹(Tree)是n(n>=0)個結點的有限集。n=0時稱爲空樹。在任意一顆非空樹中:
1)有且僅有一個特定的稱爲根(Root)的結點;
2)當n>1時,其餘結點可分爲m(m>0)個互不相交的有限集T1、T2、…、Tn,其中每一個集合本身又是一棵樹,並且稱爲根的子樹。

此外,樹的定義還需要強調以下兩點:

  • n>0時根結點是唯一的,不可能存在多個根結點,數據結構中的樹只能有一個根結點。
  • m>0時,子樹的個數沒有限制,但它們一定是互不相交的。
    圖1
    由樹的定義可以看出,樹的定義使用了遞歸的方式。遞歸在樹的學習過程中起着重要作用。
樹中常用的概念:

結點的度:結點擁有的子樹數目。
上面樹中,結點A和C的度爲2,結點B的度爲3,結點D的度爲1。

結點子樹的根結點爲該結點的孩子結點,相應該結點稱爲孩子結點的雙親結點;且同一個雙親結點的孩子結點間互稱兄弟結點
上面樹中,結點A是結點B和結點C的雙親結點,結點B和結點C是結點A的孩子結點。結點B和結點C是兄弟結點。

結點層次:從根結點起,定義其爲樹的第一層,根的孩子結點處於樹的第二層,以此類推。
圖2
樹的深度或者高度:樹中結點的最大層次樹。

2 二叉樹的概念和特點

二叉樹是n(n>=0)個結點的有限集合,該集合或者爲空集(稱爲空二叉樹),或者由一個根結點和兩棵互不相交的、分別稱爲根結點的左子樹和右子樹組成。
圖3
二叉樹具有以下幾個特點:

  • 每個結點最多有兩顆子樹,所以二叉樹中不存在度大於2的結點;
  • 二叉樹區分左子樹和右子樹,其順序不能顛倒;

3 二叉樹的性質

二叉樹的性質有以下幾點:

  • 在二叉樹的第i層上最多有2^(i-1)個結點。(i >= 1)
    當二叉樹的非葉子結點都有左右結點時,表明每層的結點都是滿的,第一層結點最多爲1個,第二層結點最多爲2個,第三層結點最多爲4個,第四層結點最多爲8個;所以第i層結點最多爲2^(i-1)個。
  • 如果二叉樹的深度爲k,那麼樹最多有2^k – 1個結點。(k >= 1)
    這個是性質一推導出來的,即對1到i層的結點數相加得到總結點數。等比數列求和公式可推導出2^k-1。
  • 二叉樹中,度數爲0的結點數(n0)等於度數爲2的結點數(n2)加1,即n0 = n2 + 1。
    這個性質可以根據兩個等式推導出來:
    a 二叉樹中只存在3種度的結點,即度爲0的結點,度爲1的結點,度爲2的結點;那麼二叉樹中結點總數爲三種度的個數和:sum = N0 + N1 + N2;
    b 二叉樹中,度爲2的結點產生2個結點,度爲1的結點產生1個結點,還有一個不是由結點產生的跟節點;那麼結點總數爲:sum = N1 + 2N2 + 1;
    那麼根據以上兩個公式可以計算出N0 = N2 + 1.

4 特殊的二叉樹

4.1斜樹

顧名思義,樹中結點都位於左節點的二叉樹稱爲左斜樹,樹中結點都位於右結點的二叉樹稱爲右斜樹。
圖4

4.2滿二叉樹

在二叉樹中,所有的分支結點都存在左右子樹且葉子結點都在同一層上,這樣的二叉樹稱爲滿二叉樹。
圖5
滿二叉樹具有如下幾個特點:

  • 滿二叉樹中的葉子結點只能出現在同一層;
  • 滿二叉樹中的非葉子結點的度都爲2;
  • 滿二叉樹的總結點數是二叉樹中最多的一類;
4.3完全二叉樹

對一顆具有n個節點的二叉樹按層編號,如果編號爲i(0<i<=n)的節點與同樣深度的滿二叉樹中編號爲i的結點在二叉樹中位置完全相同,則這顆二叉樹稱爲完全二叉樹。
圖6
完全二叉樹具有如下性質:

  • 完全二叉樹的葉子結點只能出現在最底層或者次層,且深度相差不能大於1;
  • 完全二叉樹中度爲1的分支結點,其子結點必須爲左節點;
  • 同樣結點數目的二叉樹,完全二叉樹深度最小;

注意:滿二叉樹一定是完全二叉樹,但反過來不一定成立。

5 二叉樹的兩種存儲形式

5.1 順序存儲

順序存儲最簡單的方式就是使用一維數組,二叉樹按照從上往下從左往右順序編號存儲到數組內,可見數組內元素的下標就是樹結點的位置。如下面的加了編號的滿二叉樹:
圖7
其數組存儲形式爲:[A,B,C,D,E,F,G];某結點i的左結點爲2i+1,右結點爲2i+2;此刻,數組的空間正好被滿二叉樹填滿。
或許此刻你會想到:對於普通的非滿二叉樹該如何存儲呢?
按照順序存儲,爲了保證二叉樹中結點的位置可以通過數組元素的下標計算出來,所以它會利用空結點補足空缺的子結點而構造一顆滿二叉樹或者完全二叉樹;如下面的二叉樹所示:
圖8
結點N代表補充的空結點,所以上面二叉樹用數組存儲形式爲:
圖9
數組中存儲兩個空結點,導致數組空間浪費;這還不是最壞的情況,類似於右斜樹是浪費最嚴重的情況。因此,順序存儲不適用於普通二叉樹(非滿二叉樹/非完全二叉樹)。

5.2 鏈表存儲

二叉樹的重點在於維持父結點與左右子結點的關係,既然用線性數組的形式存儲二叉樹浪費空間,那麼可以採用非線性的鏈表存儲。鏈表中,通過結點的指針域指向下一個結點,從而避免開闢連續的空間存儲結點。
用Java語言定義一個結點對象:

public class Node {
    private Node leftNode;
    private Node rightNode;
    private String content;
}

上圖中二叉樹使用鏈表存儲形式。
圖10
鏈表形式的存儲可以避免空間浪費的問題,所以比較適合二叉樹的存儲。

6 二叉樹的遍歷

二叉樹的遍歷是指從二叉樹的根節點出發,按照某種次序依次訪問二叉樹中的所有結點,使得每個結點被訪問一次且僅被訪問一次。二叉樹的訪問次序有四種:前序遍歷,中序遍歷,後續遍歷和層次遍歷。

6.1 前序遍歷

前序遍歷是從二叉樹的根結點出發,當第一次到達結點時就輸出結點數據,按照先向左再向右的方向訪問。
圖11
上圖的前序遍歷順序爲:

  1. 第一次訪問根節點A,便輸出結點A;然後訪問左結點B,第一次訪問便輸出左結點B;
  2. 訪問結點B的左結點D,第一次訪問便輸出結點D,接着訪問結點D的左結點G,第一次訪問便輸出結點G,結點G沒有左結點也沒有右結點,便返回父結點D,此時結點D是第二次訪問,再訪問右結點H,第一次訪問便輸出結點H;然後再返回父結點D,此時是第三次訪問結點D;
  3. 返回父結點B,此時第二次訪問父結點B,結點B沒有右結點,便返回父結點A;接着訪問父結點A的右結點c;
  4. 第一次訪問結點C便輸出結點C;然後訪問左結點E第一次便輸出結點E;再訪問結點E的左結點I,第一次訪問便輸出結點I;返回父結點E,再訪問父結點E的右結點,右結點不存在,便返回結點E的父節點C,第二次訪問結點C;
  5. 然後訪問結點C的右結點F,便輸出結點F;其沒有左右結點便返回父結點C,在返回結點C的父節點A。
  6. 此時,二叉樹遍歷結束。最終的前序遍歷結果爲:ABDGHCEIF
    前序遍歷有個簡單的法則,先父結點,再左結點,然後右結點,同時採用遞歸方法,就很容易得出前序遍歷。
6.2 中序遍歷

中序遍歷是從二叉樹的根結點出發,當第二次到達結點時就輸出結點數據,按照先向左再向右的方向訪問。
上圖中序遍歷的過程爲:

  1. 首先從根結點A開始訪問,然後訪問它的左結點B,再訪問結點B子樹的左結點D,再訪問結點D子樹的左結點G,到這裏,以上結點都是第一次訪問,不輸出;
  2. 訪問結點G的左結點,其爲空便返回結點G,此時第二次訪問結點G,便輸出該結點;然後訪問結點G的右結點,其爲空便返回結點G,此時第三次訪問結點G;
  3. 結點G訪問結束,返回其父結點D,第二次訪問便輸出結點D,接着訪問結點D的右結點H,其左結點爲空便返回結點H,第二次訪問便輸出結點H;然後返回結點D,這是第三次訪問結點D;
  4. 返回結點D的父結點B,這是第二次訪問便輸出結點B,沒有右結點便返回結點A,第二次訪問便輸出結點A;
  5. 接着按照順序訪問結點IECF;最終的中序遍歷結果爲:GDHBAIECF;
    中序遍歷也有個簡單的法則,先左結點,再父結點,然後右結點,同時採用遞歸方法,就很容易得出中序遍歷。
6.3 後序遍歷

後序遍歷是從二叉樹的根結點出發,當第三次到達結點時就輸出結點數據,按照先向左再向右的方向訪問。
上圖中的後序遍歷過程爲:

  1. 先訪問根節點A,然後訪問其左結點B,再訪問結點B子樹的左結點D,再訪問結點D子樹的左結點G;然後訪問結點G的左結點,爲空便返回結點G,再訪問結點G的右結點,也爲空便返回結點G,此時是第三次訪問結點G,便輸出結點G;
  2. 返回結點G的父結點D,訪問父結點D的右結點H,按照結點G的訪問方式輸出右結點H,返回父結點D,此時第三次訪問結點D,便輸出結點D;
  3. 返回結點D的父結點B,訪問結點B的右結點,爲空便返回結點B,此時第三次訪問結點B,便輸出結點B;
  4. 返回結點B的父結點A,訪問父結點A的右結點C,訪問結點C的左結點E,訪問結點E的左結點I,訪問結點I的左結點爲空,返回結點I,訪問結點I的右結點爲空,返回結點I,此時第三次訪問結點I,便輸出結點I;
  5. 返回結點I的父結點E,訪問結點E的右結點,爲空便返回結點E,第三次訪問結點E,便輸出結點E;
  6. 返回結點E的父結點C,訪問結點C的右結點F,與結點I類似左右結點爲空便返回結點F;
  7. 返回結點F的父結點C,此時第三次訪問,便輸出結點C;
  8. 返回結點C的父結點A,此時第三次訪問,便輸出結點A;
  9. 二叉樹訪問結束,最後輸出結果爲:GHDBIEFCA
    後序遍歷也有個簡單的法則,先左結點,再右結點,然後父結點,同時採用遞歸方法,就很容易得出後序遍歷。
6.4 層次遍歷

層次遍歷是最簡單的遍歷方式,按照從上往下從左往右的方式遍歷。所以上圖的層次遍歷爲:ABCDEFGHI。

6.5 遍歷總結

根據上面的遍歷知識,得到前序遍歷第一個元素即爲根節點,而後序遍歷最後一個元素即爲根節點,而中序遍歷的根節點在中間;所以,我們可以根據前序遍歷和中序遍歷獲得二叉樹的結構,也可以根據中序遍歷和後序遍歷獲得二叉樹的結構;但是前序遍歷和後序遍歷無法獲得二叉樹的結構。

7 總結

這裏簡單的瞭解下樹以及二叉樹的基本概念、特點和性質;然後主要學習幾種特殊的二叉樹,如斜樹、滿二叉樹和完全二叉樹;然後講到二叉樹的兩種存儲形式,即順序存儲和鏈表存儲;最後講到二叉樹的四種遍歷方式,即前序遍歷、後序遍歷、中序遍歷以及層次遍歷。

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