之前我們有講解過基礎的數據結構算法:線性表、棧和隊列、串的相關概念,以及八大排序算法及其代碼實現。
從本篇博文開始,我們將講解高級數據結構算法,使用C++語言實現,包括BST樹、AVL樹、紅黑樹、跳躍表、字典樹、倒排索引以及分治法、貪心算法、回溯算法、動態規劃、分支限界算法等高級數據結構算法。
樹的基本概念
之前我們講解的都是一對一的線性結構,可現實中,還有很多一對多的情況需要處理,所以我們需要研究這種一對多的數據結構——“樹”,考慮它的各種特性,來解決我們在編程中遇到的相關問題。
下面是引用百科詞條的解釋:
樹狀圖是一種數據結構,它是由 個有限結點組成一個具有層次關係的集合。把它叫做“樹”是因爲它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。它具有以下的特點:
- 每個結點有零個或多個子結點;
- 沒有父結點的結點稱爲根結點;
- 每一個非根結點有且只有一個父結點;
- 除了根結點外,每個子結點可以分爲多個不相交的子樹;
樹的定義:
樹(Tree)是 個結點的有限集。 時稱爲空樹。在任意一顆非空樹中:
- 有且只有一個特定的稱爲根(root)的結點
- 當 時,其餘結點可分爲 個互不相交的有限集 ,其中每一個集合本身又是一棵樹,並且稱爲根的子樹(SubTree)。如下圖所示:
樹的定義其實就是一種典型的遞歸的方法,也就是說在樹的定義的中也用到了樹的概念。下圖中子樹 和子樹 就是根結點A的子樹,D、G、H、I組成的樹又是以B爲根節點的子樹,E、J組成的樹是以C爲根節點的子樹。
對於樹的定義還要強調兩點:
- 時根節點是唯一的,既不可能存在多個根節點。
- 時,子樹的個數沒有限制,但它們一定是互不相交的。
結點分類
樹的結點包含一個數據元素及若干指向其子樹的分支。結點擁有的子樹數稱爲結點的度(Degree)。度爲0的結點稱爲葉子節點(Leaf)或終端結點;度不爲0的結點稱爲非終端結點或分支結點。除根節點外,分支結點也稱爲內部結點。樹的度是樹內各結點度的最大值。
如下圖,這棵樹結點的度的最大值是結點D的度,度爲3,因此樹的度也是3。
結點間關係
結點的子樹的根稱爲該結點的孩子(child),通常我們稱其爲子結點,相應的,該結點稱爲孩子的雙親(parent),通常我們稱爲父節點。
同一個雙親的孩子之間互稱爲兄弟(Sibling)。結點的祖先是從根到該結點所經分支上的所有結點。 反之,以某結點爲根的子樹中的任一結點都統稱爲該結點的子孫。
在下圖中,對於H來說,D、B、A都是它的祖先。B的子孫有D、G、H、I。
樹的其他相關概念
結點的層次(Level)是從根開始定義的,根爲第一層,根的孩子爲第二層。若某結點在第 層,那麼其子樹的根就在第 層。其雙親在同一層的結點互爲堂兄弟。樹中結點的最大層次稱爲樹的深度(Depth)或高度。
在下圖中,G、H、I 與 J 是堂兄弟,當前樹的深度爲4。
如果將樹中結點的各子樹看成從左至右是有次序的,不能互換的,則稱該樹是有序樹,否則稱爲無序樹。
森林(Forest)是 棵互不相交的樹的集合。對樹中每個結點而言,其子樹的集合即爲森林。
有關樹的基本概念整理
- 節點的度:一個節點含有的子樹的個數稱爲該節點的度。
- 葉節點或終端節點:度爲0的節點稱爲葉節點;
- 非終端節點或分支節點:度不爲0的節點;
- 雙親節點或父節點:若一個節點含有子節點,則這個節點稱爲其子節點的父節點;
- 孩子節點或子節點:一個節點含有的子樹的根節點稱爲該節點的子節點;
- 兄弟節點:具有相同父節點的節點互稱爲兄弟節點;
- 樹的度:一棵樹中,最大的節點的度稱爲樹的度;
- 節點的層次:從根開始定義起,根爲第1層,根的子節點爲第2層,以此類推;
- 樹的高度或深度:樹中節點的最大層次;
- 堂兄弟節點:雙親在同一層的節點互爲堂兄弟;
- 節點的祖先:從根到該節點所經分支上的所有節點;
- 子孫:以某節點爲根的子樹中任一節點都稱爲該節點的子孫。
- 森林:由 棵互不相交的樹的集合稱爲森林。
樹的存儲結構
樹中的某個結點的孩子可以有多個,所以僅僅使用簡單的順序結構或者鏈式結構是不能完全表示一整棵樹的。
充分利用順序存儲結構和鏈式存儲結構的特點,完全可以實現對樹的存儲結構的表示。
我們表示一棵樹的方法有:雙親表示法,孩子表示法,孩子兄弟表示法。
有關樹的存儲結構的詳細講解,可以參考博文:《樹的存儲結構》
二叉樹的定義
二叉樹(Binary Tree)是 個結點的有限集合,該集合或者爲空集(稱爲空二叉樹),或者由一個根結點以及兩棵互不相交的、分別稱爲根節點的左子樹和右子樹的二叉樹組成。每個根節點只有兩個子節點的就叫做二叉樹。
下圖便是一棵二叉樹:
二叉樹的特點
二叉樹的特點有:
- 每個結點最多有兩棵子樹,所以二叉樹中不存在度大於 2 的結點。注意不是隻有兩棵子樹,而是最多有。沒有子樹或者有一棵子樹都是可以的。
- 左子樹和右子樹是有順序的,次序不能任意顛倒。
- 即使樹中某結點只有一棵子樹,也要區分它是左子樹還是右子樹。
二叉樹具有五種基本形態:
- 空二叉樹
- 只有一個根結點
- 根結點只有左子樹
- 根結點只有右子樹
- 根結點既有左子樹又有右子樹
特殊的二叉樹
1、斜樹
所有的節點都只有左子樹的二叉樹叫左斜樹;所有節點都只有右子樹的二叉樹叫右斜樹。這兩者統稱爲斜樹。
斜樹的特點很明顯就是每一層只有一個節點,節點的個數與二叉樹的深度相同。其實線性表可以理解爲樹的一種極其特殊的形式。
2、滿二叉樹
在一棵二叉樹中,如果所有分支節點都存在左子樹和右子樹,並且所有的葉子節點都在同一層上,這樣的二叉樹稱爲 " 滿二叉樹 "。如下圖:
單是每個結點都存在左右子樹,不能算是滿二叉樹,還必須要所有的葉子結點都在同一層上,這就做到了整棵樹的平衡。因此,滿二叉樹的特點有:
- 葉子只能出現在最下一層。 出現在其它層就不可能達成平衡。
- 非葉子節點的度一定是2。
- 在同樣深度的二叉樹中,滿二叉樹的節點個數最多,葉子數最多。
3、完全二叉樹
對於一棵具有 個節點的二叉樹按照層序編號,如果編號爲 ()的節點與同樣深度的滿二叉樹中編號爲 的節點在二叉樹中位置完全相同,則這棵二叉樹稱爲”完全二叉樹“。如下圖:
把完全二叉樹的節點與同樣深度的滿二叉樹各個節點進行編號比較,所有節點出現的位置相同,則是完全二叉樹。所以,滿二叉樹一定是一棵完全二叉樹,而完全二叉樹不一定是滿二叉樹。
完全二叉樹的特點:
- 葉子節點只能出現在最下兩層。
- 最下層的葉子一定集中左部連續位置。
- 倒數第二層,若有葉子節點,一定都在右部連續位置。
- 如果節點度爲1,則該節點只有左孩子,即不存在右子樹的情況。
- 同樣節點的二叉樹,完全二叉樹的深度最小。
二叉樹的性質
性質1:在二叉樹的第 層上至多有 個結點(i ≥ 1)
性質2:深度爲 的二叉樹至多有 個結點(k ≥ 1)
性質3:對任何一棵二叉樹 T,如果其終端結點數爲 ,度爲2的節點數爲 ,則 。
性質4:具有 個結點的完全二叉樹的深度爲 (其中表示向下取整,即表示不大於 的最大整數)
性質5:如果對一棵有 個結點的完全二叉樹(其深度爲)的結點按層序編號(從第 層到第 層,每層從左到右),對任一結點 有:
- 如果 ,則結點 是二叉樹的根,無雙親;如果 ,則其雙親是結點
- 如果 ,則結點 無左孩子(結點 爲葉子結點);否則其左孩子是結點 。
- 如果 ,則結點 無右孩子;否則其右孩子是結點 。