數據結構——樹與二叉樹

三、樹與二叉樹

這篇總結的主要是棧和隊列的知識點,可以收藏下來,哪些地方概念不是特別清楚的時候翻出來看看。如果想看本章涉及到的代碼部分,見文章下方超鏈接。

另外這一部分總結的有點亂,都是乾巴巴的知識,有些地方還是很難理解的,如需討論的,隨時評論區可以討論。

(一)樹的基本概念
  1. 樹的定義

    • 樹是一種非線性的數據結構。
    • 它是由若干個結點構成的集合(樹是n>=0個結點的有限集),由唯一的根若干棵互不相交的子樹組成的。每一個子樹又是一棵樹,同樣它也是由唯一的根結點和若干棵互不相交的子樹組成。
    • 樹的結點數爲0,稱之爲空樹。
  2. 樹的基本術語

    [外鏈圖失敗片(img-GQq0LcS2565620033949)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565186901188.png)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565186901188.png)]

    • 結點:A,B,C都是結點,結點不僅包含數據元素,而且包含指子樹的分支。例如A結點,不僅包含數據元素A,還包含3個指向子樹的分支。
    • 結點的度:結點擁有的子樹的個數或者分支的個數。
    • 樹的度:樹中各結點度的最大值。
    • 葉子結點:又叫做終端結點,度爲0的結點。
    • 非終端結點:又叫做分支結點,度不爲0的結點。
    • 孩子結點:結點的子樹的根。例如A的孩子結點爲B,C,D
    • 雙親結點:與孩子結點定義對應,B,C,D的雙親都是A結點
    • 兄弟結點:同一個雙親的孩子之間互爲兄弟。如B,C,D爲兄弟結點。
    • 堂兄弟結點:雙親在同一層的結點互爲堂兄弟。如G和H爲堂兄弟,其它們的雙親爲C和D在同一層上。
    • 祖先:從根到某一個結點路徑上所有的結點,這是這個結點的祖先。
    • 子孫:以某結點爲根的子樹中的所有結點。
    • 層次:從根開始,根爲第一層,根的孩子爲第二層,以此類推。
    • 樹的高度:樹種結點的最大層次。
    • 結點的深度:從根結點到該結點路徑上的結點個數。
    • 結點的高度:從某結點往下走可能到達多個葉子結點,對應了多條路徑,其中最長的路徑即爲結點的高度。例如結點D的高度爲3,也就是D到M的路徑長度。根結點的高度就是樹的高度。、
    • 有序樹:樹中結點的子樹從左到右是有次序的,不能交換。
    • 無序樹:樹中結點的子樹沒有順序,可以任意交換。
    • 豐滿樹:是理想平衡樹,要求除最底層外,其他層都是滿的。
    • 森林:若干棵互不相交的樹的集合。
(二)二叉樹
  1. 二叉樹的定義

    • 二叉樹是另一種樹型結構,是在一般的樹上加上兩個限制條件就得到了二叉樹。
      • 每個結點最多有兩棵子樹,即二叉樹中,每個結點的度最大是2,可以是0,1,2
      • 子樹有順序之分,不能顛倒
    • 滿二叉樹:如果所有的結點都有左孩子和右孩子,並且葉子結點都集中在二叉樹的最下一層。
    • 完全二叉樹:將二叉樹進行編號,從上到下,從左到右,此二叉樹與滿二叉樹再相同位置的結點的編號相同,即爲完全二叉樹。完全二叉樹沒有要求所有結點都必須有左孩子和右孩子,只要求與滿二叉樹編號相同即可。
    • 通常來說,一棵完全二叉樹一定是由一棵滿二叉樹從右到左,從下到上,挨個刪除結點得到的。
  2. 二叉樹的性質

    • 非空二叉樹上的葉子結點數等於雙分支結點數加1

    • 二叉樹的第 i 層上最多有2^(i-1) (i >= 1)個結點。

    • 高度爲k的二叉樹最多有2^ k - 1 (k >= 1)個結點。

    • 函數Catalan() 給定n的結點,能構成h(n)種不同的二叉樹。
      h(n)=C2nnn+1 h(n) = \frac{C_{2n}^{n}}{n+1}

    • 具有n (n >= 1)的結點的完全二叉樹,高度爲
      log2n+1 \lfloor log_2n +1\rfloor 向下取整

    • 有n個結點的完全二叉樹,對各結點從上到下,從左到右進行編號。 若 i 爲某結點 a 的編號,i ≠ 1 則 a 的雙親結點的編號爲
      i/2 \lfloor i/2\rfloor 向下取整

      • 如果 2i ≤ n,則 a 的左孩子的編號爲 2i , 如果 2i > n , 則 a 無 左孩子

      • 如果 2i ≤ n,則 a 的右孩子的編號爲 2i + 1 ,如果 2i > n , 則 a 無 右孩子

  3. 二叉樹的順序存儲結構和鏈式存儲結構

    • 順序存儲結構:
      用一組地址連續的存儲單元依次自上而下,自左而右存儲完全二叉樹上的元素。(最適合存儲完全二叉樹)
    • 鏈式存儲結構:
      • 觀察二叉樹的形態,發現是由一個根節點與兩棵子樹之間的關係,因此用一個數據域和兩個指針域的鏈式存儲結構。
      • 數據域用來存儲結點的數據,指針域用來存儲左右孩子的結點的位置。
      • 這種存儲結構稱爲二叉鏈表存儲結構
  4. 二叉樹的遍歷

    • 先(根)序遍歷
      • 若二叉樹爲空,則空操作。否則
      • 訪問根結點
      • 先序遍歷左子樹
      • 先序遍歷右子樹
    • 中(根)序遍歷
      • 若二叉樹爲空,則空操作。否則
      • 中序遍歷左子樹
      • 訪問根結點
      • 中序遍歷右子樹
    • 後(根)序遍歷
      • 若二叉樹爲空,則空操作。否則
      • 後序遍歷左子樹
      • 後序遍歷右子樹
      • 訪問根結點
    • 層次遍歷
      • 按層遍歷,每層從左往右或從右往左挨個遍歷
  5. 線索二叉樹的基本概念和構造

    • 首先明白兩個概念:

      • 直接前驅:當前結點的前一個結點,
      • 直接後繼:當前結點的後一個結點

    [外鏈圖片轉存失敗(img-1uURo8u5-1565620033958)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565614898521.png)]

    • n個結點的二叉鏈表中,有n+1個指針域爲空

        因爲:n個結點,每個結點有兩個指針域(左右孩子指針域),共有2n個指針域;然而,n個結點中,有n-1個孩子(根結點不是孩子),所以2n個指針域中,有n-1個指針域用來表示結點的左右孩子,其餘n+1個指針域爲空。

    • 何爲線索?

        如果某個結點的左孩子爲空,則將空的左孩子指針域指向其前驅;如果某結點的右孩子爲空,則將空的右孩子指針域指向其後繼。這種改變指向的指針稱爲線索。

    • 線索二叉樹

        加上了線索的二叉樹叫做線索二叉樹

    • 線索化

         對二叉樹按照某種遍歷次序使其爲線索二叉樹的過程叫做線索化。

    • 線索二叉樹結點的結構如下

      • Ltag = 0表示lchild爲指針,指向左孩子結點;Ltag = 1表示lchild爲線索,指向結點的直接前驅
      • Rtag = 0表示rchild爲指針,指向右孩子結點; Rtag = 1表示rchild爲線索,指向結點的直接後繼
    前驅或者左子樹 0左孩子,1前驅 數據 0右孩子,1後繼 後繼或者右子樹
    lchild Ltag data Rtag rchild
    1. 線索二叉樹又有:前序線索二叉樹,中序線索二叉樹,後序線索二叉樹。中序二叉樹考查最頻繁。對一個二叉樹所有的空指針域按照某種遍歷方式加線索的過程稱爲線索化
(三)樹、樹林
  1. 樹的存儲結構

    • 順序存儲結構
      • 樹的順序存儲結構雙親表示法——雙親存儲結構
        • 用數組下標表示樹中的結點,用數據元素表示該結點的雙親結點。這樣就有了結點以及結點之間的關係,就可以表示一棵樹了。
      • 鏈式存儲結構
        • 樹的鏈式存儲結構孩子表示法——孩子存儲結構
        • 樹的鏈式存儲結構孩子兄弟表示法——孩子兄弟存儲結構
  2. 森林與二叉樹的轉換

    • 樹轉換爲二叉樹

      在這裏插入圖片描述
      1、將同一結點的各孩子用線串起來,即所有兄弟結點之間

      [外鏈圖片轉存失敗(img-ypqySlE1-1565620033964)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565533768325.png)]

      2、將每個結點的分支從左到右除了第一個以外,其餘都剪掉

      [外鏈圖片轉存失敗(img-H73oWJCP-1565620033966)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565533790470.png)]

      3、調整結點位置,使其符合二叉樹的層次結構。

      [外鏈圖片轉存失敗(img-3bIImEbv-1565620033968)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565533827820.png)]

    • 二叉樹轉換爲樹

      1、先將其從左上到右下分爲若干層,然後調整爲水平方向

      [外鏈圖片轉存失敗(img-OfeoksbW-1565620033969)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565613306504.png)]

      2、找到每一層結點在其上一層的父結點,並且將每一層的結點與其父結點相連接

      [外鏈圖片轉存失敗(img-PpM4pfdY-1565620033971)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565613390505.png)]

      3、然後刪除每一層結點之間的連線,即兄弟結點之間的連線

      在這裏插入圖片描述

      4、調整位置
      在這裏插入圖片描述

    • 森林轉化爲二叉樹

      [外鏈圖片轉存失敗(img-1dPxFh3l-1565620033974)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565613850890.png)]

      1、先將森林中的多棵樹分別轉化爲二叉樹
      2、將第二棵二叉樹作爲第一棵二叉樹的右孩子,第三棵二叉樹作爲第二棵二叉樹的右孩子,以此類推。(圖中藍線部分)
      [外鏈圖片轉存失敗(img-Y26jrqND-1565620033977)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565613859160.png)]

      3、調整位置

      [外鏈圖片轉存失敗(img-mXxS6IkT-1565620033979)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565613913873.png)]

    • 二叉樹轉化爲森林

      [外鏈圖片轉存失敗(img-yysZbJuu-1565620033980)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565613981151.png)]

      1、不斷的將根節點有右孩子的二叉樹斷開,直到不存在根結點有右孩子的二叉樹爲止。

      [外鏈圖片轉存失敗(img-0LdyEN3R-1565620033981)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565613991648.png)]

      2、將斷開的樹調整位置成森林

      [外鏈圖片轉存失敗(img-7MH0nqSq-1565620033984)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565614020054.png)]

  3. 樹和森林的遍歷

    • 樹的遍歷
      • 先序(根)遍歷
        先訪問樹的根節點,然後再依次訪問根結點的每棵子樹訪問子樹時仍然遵循先根再子樹的規則。
      • 後序(根)遍歷
        先依次根結點遍歷每棵子樹,然後再訪問根結點訪問子樹時仍然遵循先子樹再根的規則。
    • 森林的遍歷
      • 先序(根)遍歷
        先訪問森林中第一棵樹的根節點,然後再先序遍歷第一棵子樹中的根結點的每棵子樹,最後先序遍歷森林中除第一棵子樹外的其他樹
      • 後序(根)遍歷
        後序遍歷第一棵樹中的根結點的子樹,然後訪問第一棵樹的根結點,最後後序遍歷森林中除第一棵樹以後的其他樹
(四)樹與二叉樹的應用
  1. 二叉排序樹——詳細請看這裏

    • 二叉排序樹又稱二叉查找樹。具有以下性質:
      • 若左子樹非空,則左子樹上所有結點關鍵字值均小於根結點的關鍵字值
      • 若右子樹非空,則右子樹上所有結點關鍵字值均大於根結點的關鍵字值
      • 左、右子樹各是一棵二叉排序樹

      由此定義可知,二叉排序樹是一個遞歸的數據結構,有左子樹結點值<根結點值<右子樹結點值。所以,對二叉排序樹進行中序遍歷,可以得到一個遞增的有序序列。

  2. 平衡二叉樹(AVL樹)——詳細請看這裏

    • 任意結點的左、右子樹高度差的絕對值不超過1,將這樣的二叉樹稱爲平衡二叉樹,簡稱平衡樹(AVL樹)。
    • 一個結點的平衡因子左子樹的高度減去右子樹的高度。因此平衡因子取值只能是1,-1,0.
  3. 赫夫曼(Huffman)樹和赫夫曼編碼

    • 赫夫曼樹

      • 赫夫曼樹又叫做最優二叉樹,特點是帶權路徑最短。什麼是路徑?什麼是最短路徑?

        [外鏈圖片轉存失敗(img-Ds513tnk-1565620033985)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565611367162.png)]

        • 路徑:指從樹中的一個結點到另一個結點的分支所構成的路徑。
        • 路徑長度:路徑長度是指路徑上分支的數目。——a 結點到根結點分支數目爲2,所以路徑長度爲2.
        • 樹的路徑長度:指從根到每個結點的路徑長度之和。
        • 帶權路徑長度:結點具有權值,從該結點到根結點之間的路徑長度乘以結點的權值。——a的帶權路徑長度爲7*2=14
        • 樹的帶權路徑長度(WPL):樹種所有的葉子結點帶權路徑之和。——這棵樹的帶權路徑長度爲WPL=7 * 2+5 * 2 + 2 * 2 + 4 * 2 = 38
      • 赫夫曼樹的構造方法

        1、 先將A,B,C,D看成只有根的4棵二叉樹

        [外鏈圖片轉存失敗(img-3sQMTOYx-1565620033987)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565611883954.png)]

        2、選出權值最小的A,C兩個結點,將他們作爲左右子樹構造除一棵新的二叉樹,新的二叉樹的根結點權值爲A ,C 的權值之和,刪除A,C兩個結點,同時將新構造的二叉樹加入集合中

        [外鏈圖片轉存失敗(img-svs25LvW-1565620033988)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565611922029.png)]

        3、繼續選擇兩個權值最小的樹,按照同樣的方法構造二叉樹。依次類推

        [外鏈圖片轉存失敗(img-43bRLfVc-1565620033989)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565611977854.png)]

        [外鏈圖片轉存失敗(img-Sv89qC4r-1565620033991)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565612091663.png)]

        4、此時,集合中就剩下了一棵二叉樹,這棵二叉樹就是赫夫曼樹

      • 赫夫曼樹的特點

        • 權值越大的結點,距離根結點越近
        • 樹種沒有度爲1的結點,這類書又叫做正則(嚴格)二叉樹
        • 樹中帶權路徑長度WPL最短
    • 赫夫曼編碼

      • 赫夫曼編碼是一種可變字長的編碼。

        • 如果一組編碼中,任一編碼都不是其他任何一個編碼的前綴,我們稱這組編碼爲前綴編碼赫夫曼樹可用於構造最短的不等長編碼方案

        • 規定赫夫曼編碼的樹左分支代表0,右分支代表1,則從根結點到每個葉子結點所經過的路徑組成的0和1序列便成爲了該葉子結點對應字符的編碼。如下:

          [外鏈圖片轉存失敗(img-Y3jr6TXC-1565620033993)(C:\Users\DONG\AppData\Roaming\Typora\typora-user-images\1565612621899.png)]

        • 哈夫曼編碼樹中,樹的帶權路徑長度的含義是各個字符的碼長與其出現次數的乘積之和,所以採用哈夫曼樹構造的編碼是一種能使字符串的編碼總長度最短的不等長編碼

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