【學習總結】《大話數據結構》- 第6章-樹

【學習總結】《大話數據結構》- 總

第6章樹-代碼連接

啓示:

目錄

<!-- GFM-TOC -->html

<!-- GFM-TOC -->git

========================================github

6.1 開場白

  • 一些能夠略過的場面話...

========================================算法

6.2 樹的定義

  • 定義

  • 注意:

    • n>0時:根節點是惟一的,不可能存在多個根節點。

    • m>0時:子樹的個數沒有限制,但它們必定互不相交。

  • 結點分類

    • 結點的度(degree):結點擁有的子樹數

    • 葉結點(leaf)或終結點:度爲0的結點

    • 非終端結點或分支結點:度不爲0的結點

    • 內部結點:除根節點外,分支結點也稱爲內部結點

    • 樹的度:樹內各結點的度的最大值

  • 結點間關係

    • 孩子(child):結點的子樹的根稱爲該結點的孩子

    • 雙親(parent):該結點稱爲孩子的雙親(父母同體,惟一的一個)

    • 兄弟(sibling):同一個雙親的孩子之間互稱兄弟

    • 祖先:結點的祖先是從根到該結點所經分支上的全部結點

    • 子孫:以某結點爲根的子樹中的任一結點都稱爲該節點的子孫

  • 樹的其餘相關概念

    • 層次(level):從根開始定義起,根爲第一層,根的孩子爲第二層

      即:若某結點在第L層,則其子樹的根就在第L+1層

    • 堂兄弟:雙親在同一層的結點互爲堂兄弟

    • 深度(depth)或高度:樹中結點的最大層次稱爲樹的深度或高度

  • 有序樹/無序樹:若是將樹中結點的各子樹當作從左至右有次序的,不能互換的,則稱該樹爲有序樹,不然爲無序樹。

  • 森林(forest):m(m>=0)棵互不相交的樹的集合。

    • 對於樹中每一個結點而言,其子樹的集合即爲森林。

  • 線性表與樹的對比

========================================數組

6.3 樹的抽象數據類型

  • 相比線性結構,樹的操做就徹底不一樣了。如下是基本和經常使用操做。

========================================數據結構

6.4 樹的存儲結構

  • 簡單的順序存儲結構沒法直接反映邏輯關係,不能知足樹的實現要求

    故充分利用順序存儲和鏈式存儲結構的特色,介紹三種不一樣的表示法

  • 雙親表示法

    • 引入:除根節點外,其他每一個結點,不必定有孩子,但必定有且僅有一個雙親

    • 定義:設以一組連續空間存儲樹的結點,同時在每一個結點中,附設一個指示器指示其雙親結點到鏈表中的位置。

      • data:數據域,存儲結點的數據信息

      • parent:指針域,存儲該結點的雙親在數組中的下標

      • 約定:根節點的位置域爲-1

  • 代碼實現:

  • 圖示:

  • 弊端:找一個結點的雙親,時間複雜度O(1),可是找一個結點的孩子,須要遍歷整個結構

  • 針對上述找孩子的解決:增設一個結點最左邊孩子的域(長子域),沒有孩子的結點,長子域爲-1

    • 2個孩子:知道長子是誰,另外一個就是次子了

  • 另外一個問題:兄弟之間的關係 -- 增長一個右兄弟域來體現兄弟關係,沒有右兄弟時爲-1

  • 同時關注結點的雙親、孩子、兄弟時:設置雙親域、長子域、右兄弟域

    但對時間遍歷要求較高,有須要時再添加相應的結構

  • 孩子表示法

    • 多重鏈表表示法:

      • 每一個結點有多個指針域,其中每一個指針指向一棵子樹的根節點,這種方法叫作多重鏈表表示法。

    • 方案一:設置指針域的個數爲樹的度

      • 可能存在空間的浪費

  • 方案二:設置每一個結點指針域的個數等於該結點的度,取一個位置來存儲結點指針域的個數

    • 空間利用率提升,可是各個結點的鏈表結構不一樣,要維護結點的度的數值,時間損耗提升

  • 孩子表示法:

    • 把每一個結點的孩子結點排列起來,以單鏈表做存儲結構,則n個結點有n個孩子鏈表,若是是葉子結點,則此單鏈表爲空。而後n個頭指針又組成一個線性表,採用順序存儲結構,存放進一個一維數組中。

  • 孩子表示法的兩種結點結構

    • 孩子鏈表的孩子結點

- ### 表頭數組的表頭結點 學習

  • 孩子表示法的結構定義代碼:

  • 孩子表示法的弊端:找某結點的雙親,仍須要遍歷整個樹

  • 改進:雙親孩子表示法

  • 孩子兄弟表示法

    • 引入:

      任意一棵樹,它的結點的第一個孩子若是存在就是惟一的,它的右兄弟若是存在也是惟一的。

      所以,能夠設置兩個指針,分別指向該結點的第一個孩子和此結點的右兄弟

  • 結構定義代碼:

  • 圖示:

  • 弊端:找雙親仍需遍歷整棵樹,能夠增長parent指針域

  • 好處:把一棵複雜的樹變成了一棵二叉樹

========================================編碼

6.5 二叉樹的定義

  • 定義

  • 一、二叉樹的特色

  • 二、特殊二叉樹

    • 1-斜樹:

      全部結點都只有左子樹的二叉樹叫左斜樹

      全部結點都只有右子樹的二叉樹叫右斜樹

      這二者統稱爲斜樹。

      特色:每層只有一個結點,結點個數與二叉樹的深度相同

      注:線性表結構能夠理解爲是樹的一種極其特殊的表現形式

  • 二、滿二叉樹

    定義:一棵二叉樹中,全部分支結點都存在左右子樹,而且全部葉子都在同一層

#### 特色: spa

  • 三、徹底二叉樹

    • 定義:對一棵具備n個結點的二叉樹按層序編號,若是編號i(1<=i<=n)的結點與一樣深度的滿二叉樹中編號爲i的結點在二叉樹中位置徹底相同,則此二叉樹爲徹底二叉樹

      徹底二叉樹示例:

#### 非徹底二叉樹示例: - #### 徹底二叉樹的特色: - #### 徹底二叉樹的判斷方法:給每一個結點按滿二叉樹的結構逐層排序,若是編號出現空檔,就不是,不然就是。.net

========================================

6.6 二叉樹的性質

  • 推導:

  • 簡單推導:

  • 舉例:

========================================

6.7 二叉樹的存儲結構

  • 二叉樹的順序存儲結構:按徹底二叉樹編號

    • 順序存儲結構通常只用於徹底二叉樹,不然容易形成空間的浪費

    • 徹底二叉樹:

  • 通常二叉樹:

  • 極端狀況的二叉樹:

  • 二叉鏈表

    • 定義:

      二叉樹每一個結點最多有兩個孩子,因此設置一個數據域和兩個指針域,這樣的鏈表稱爲二叉鏈表。

- data:數據域 - lchild和lchild:指針域,分別存放指向左孩子和右孩子的指針。

  • 二叉鏈表的結點結構定義代碼

  • 圖示:

  • 三叉鏈表:

    • 若有須要,可增長一個指向其雙親的指針域,其稱爲三叉鏈表。

========================================

6.8 遍歷二叉樹

  • 二叉樹遍歷原理

  • 關鍵詞:訪問和次序

  • 訪問:根據實際的需求來肯定具體作什麼,算做是一個抽象操做。

  • 遍歷次序:

    • 線性結構最可能是從頭至尾、循環、雙向等。

    • 樹節點不存在惟一前驅後繼,會由於遍歷方式不一樣而產生徹底不一樣的結果。

  • 二叉樹遍歷方法:

    • 四種:前序遍歷、中序遍歷、後序遍歷、層序遍歷。

    • 前序遍歷:根左右

  • 中序遍歷:左根右

  • 後序遍歷:左右根

  • 層序遍歷:

  • 前序遍歷

    • 代碼實現;

  • 圖示:

  • 中序遍歷

    • 代碼實現

  • 圖示:

  • 後序遍歷

    • 代碼實現:

  • 圖示:

  • 遍歷推導

    • 已知前序遍歷和中序遍歷,求後序遍歷

      ###前序:ABCDEF,中序:CBAEDF
      • 前序第一個字母是A,說明A是根節點
      • 中序CBAEDF,說明CB在A的左,EDF在A的右
      • 前序CB:ABCDEF,先B後C,故B是A的左,C是B的孩子,左右不肯定
      • 中序CB:CBAEDF,先C後B,故C是B的左
      • 前序EDF:ABCDEF,說明D是A的右孩子,EF是D的子孫
      • 中序EDF:CBAEDF,E在D左,F在D右,說明E是D的左孩子,F是D的右孩子
      • 根據獲得的二叉樹圖,檢查一下是否符合所給前序和中序
      • 而後可得後序:CBEFDA
    • 已知中序遍歷和後序遍歷,求前序遍歷:

  • 性質小結:

========================================

6.9 二叉樹的創建

  • 二叉樹的擴展二叉樹:

    • 爲了能讓每一個結點確認是否有左右孩子,將每一個結點的空指針引出一個虛結點,其值爲一特定值,好比"#"

    • 稱這種處理後的二叉樹爲原二叉樹的擴展二叉樹

    • 擴展二叉樹就能夠作到一個遍歷序列肯定一棵二叉樹

  • 代碼實現:

  • 其餘:

    • 固然,也能夠用中序或後序遍歷的方式實現二叉樹的創建

      只需對代碼裏生成結點和構造左右子樹的代碼順序交換,而且輸入字符也作相應的更新便可。

========================================

6.10 線索二叉樹

  • 引入:

    • 空指針存在空間的浪費

  • 二叉鏈表中,只能看出左右孩子,而看不出某序遍歷的前驅和後繼

  • 定義:

    • 線索:指向前驅和後繼的指針稱爲線索

    • 線索鏈表:加上線索的二叉鏈表稱爲線索鏈表

    • 線索二叉樹(Threaded Binary Tree):相應的二叉樹稱爲線索二叉樹

  • 線索化:對二叉樹以某種次序遍歷使其變爲線索二叉樹的過程

(此處應該是把非空指針域也變成了線索)

  • 爲區分左右孩子和前驅後繼,每一個結點增設兩個標誌域

(注:此標誌域佔用的內存空間小於rchild類的指針變量)

  • 線索二叉樹的結構實現

  • 前驅和後繼的信息只有在遍歷二叉樹時才能獲得

  • 因此線索化的過程就是在遍歷的過程當中修改空指針的過程。

  • 代碼實現:中序遍歷線索化

  • 類雙向鏈表圖示:

  • 類雙向鏈表代碼實現:

========================================

6.11 樹、森林與二叉樹的轉換

  • 樹轉換爲二叉樹

  • 森林轉換爲二叉樹

  • 二叉樹轉換爲樹

  • 二叉樹轉換爲森林

    • 首先判斷:二叉樹的根結點是否有右孩子:有就是森林,不然不是。

  • 樹和森林的遍歷

========================================

6.12 赫夫曼樹及其應用

  • 定義

  • 路徑:從樹中一個結點到另外一個結點之間的分支構成兩個結點之間的路徑

  • 路徑長度:路徑上的分支數目稱爲路徑長度

  • 樹的路徑長度:從樹根到每一個結點的路徑長度(注意是每一結點,不止是全部葉結點)

    樹a的路徑長度:

    樹b的路徑長度:

  • 結點的帶權路徑長度:從該結點到樹根之間的路徑長度與結點上權值的乘積。

  • 樹的帶權路徑長度:樹中全部葉子結點的帶權路徑長度。(注意是葉子結點,沒有中間的)

  • 赫夫曼樹(Huffman):帶權路徑長度WPL最小的二叉樹稱作赫夫曼樹。也叫最優二叉樹。

    • 注:哈夫曼樹中沒有度爲1的結點。(每個結點都是由它的兩棵子樹合併產生的新結點)

  • 構造最優的赫夫曼樹

  • 構造赫夫曼樹的赫夫曼算法描述:

  • 赫夫曼編碼

========================================

6.13 總結回顧

========================================

6.14 結尾語

END

相關文章
相關標籤/搜索