1. 程式人生 > 其它 >資料結構 ———— 樹

資料結構 ———— 樹

資料結構 ———— 樹

目錄

  摘要:在資料結構中,樹是一種非常重要的存在,樹有著眾多的變體,其中二叉樹就是最為重要的一種變體,我們在學習初期,遇到的最多的樹便是二叉樹,在各種方面應用的最多的也是二叉樹,因此我們今天著重分析二叉樹

1.樹的基本構成

  在資料結構中,樹的構造和我們現實生活中的樹非常相似,只不過外形更加抽象罷了,在資料結構中的樹中,同樣存在根以及枝葉和分叉,接下來,我們先通過圖形來看一看樹的基本構成,以此來方便二叉樹的學習,因為作為樹中的特殊品種,二叉樹自然也具備樹一切的基本構成。

1.1.父節點

  在樹結構中,存在著像連結串列中一樣的指向,在一個節點中,內部存在一個指向其他節點的指標,在連結串列中,如果A節點指向B節點,那麼A節點被稱為B節點的前驅,而B節點稱之為A節點的後繼,在樹中情況發生了變化,如果A節點指向B節點,那麼A節點稱之為B節點的父節點或者雙親節點,B節點稱之為A節點的孩子節點,如圖所示:

  在圖中,A節點指向了B和C節點,因此B和C節點是A節點的孩子節點,A是B、C節點的父節點。

1.2.孩子節點

  同樣如上圖所示,B節點是被A指向的,因此B節點是A節點的孩子節點,而D節點被B指向,則D節點是B節點的孩子節點,孩子節點和父節點之間的關係是相互的,二者是一個對立關係。

1.3.兄弟節點

  同樣如上圖所示,我們可以發現B節點和C節點的父節點是同一個,都是A節點,具備這種父節點是同一個節點關係的節點,相互之間互稱兄弟節點,B和C之間就是兄弟節點,這一點非常類似人類之間的血統關係,一對父母所生的不同孩子,互稱兄弟,而樹中也沿用了這個定義。

1.4.堂兄弟節點

  這個概念不是很重要,但是也是存在這個定義的,和人類之間的血統關係一樣,如果兩個男人互為兄弟,組成的不同家庭所生出的孩子之間互稱堂兄弟姐妹,樹中也沿用了這個定義,如圖所示:

  D和E,D和F之間,便是堂兄弟關係,但是E和F是親兄弟,簡而言之:兩節點的父節點如果是親兄弟,那麼二者互為堂兄弟的關係

1.5.根節點

  具備了上面所講的定義,那我們現在也可以講解一下什麼是根節點了,所謂根節點,就是一棵樹中,位於最頂端的,是所有的節點之祖的節點,根節點沒有雙親節點或者說是父節點,沒有節點指向根節點,只有它指向了別人,如圖所示:

  紅框中的節點,便是這棵樹的根節點,該節點位於該樹的最頂端,沒有其他的節點指向它,它是這棵樹的祖宗,如果沒有它,那這棵樹中的其他節點都無法被找到,根節點正好比每個家族中的祖宗,有了祖宗,才可能有現在的我們,而如果我們觀察家譜的話也會發現,家譜實際上就是一個樹狀結構,而位於這棵樹的上層的人,通常是我們的祖輩,而我們的家譜越往上,人數便會越少,如果有可能的話,最上方可能只有一對夫婦,而這一對夫婦正有可能是某一個家族的創始人。有理論提到,現在地球上的所有生物,都來源於一個細胞,該理論與根節點也有相似之處。總之,一棵樹中位於最上方的,沒有雙親節點的節點,我們稱之為根節點

1.6.葉子節點

  和一棵真正的樹一樣,資料結構中的樹也是有著葉子的,我們在生活中觀察便可發現,一棵樹有著很多的樹幹,樹枝,這些樹枝有著複雜的分叉,但是這些分叉都不約而同的在葉子部分結束掉了,也就是說葉子是一棵樹中的最末端,在葉子之後,不會生出其他的分支了。這個概念被資料結構沿用,位於一棵樹的最低端,沒有孩子節點的節點,我們稱之為葉子節點,如圖所示:

  在改圖中,藍色方框框起來的節點們就是葉子節點,這些節點位於樹的最下一層,他們之後便沒有其他節點了,這就是葉子節點,沒有孩子節點的節點便是葉子節點。這好比我們的血統關係中,一個家族中的最小輩分,還沒有孩子的人,就是這個家族中的葉子節點部分。需要注意的是位於最下層並不是葉子節點的必要條件,葉子節點不一定位於最下層,成為葉子節點的必要條件是沒有孩子節點

1.7.非葉子節點

  與葉子節點相反的便是非葉子節點,如上圖所示,藍色方框以外的所有節點都是非葉子節點,根節點也是非葉子節點,只不過根節點是非葉子節點中比較特殊的一個罷了。

2.樹節點的構成

  瞭解了樹的邏輯結構之後,我們來從物理儲存的角度瞭解一下樹中的每個節點到底是什麼樣子的,是什麼樣的資料構造使得資料結構中可以存在樹這樣的特殊結構呢?首先我們先來複習一下連結串列節點的構造:

  在連結串列中,每個節點都是一個單元,擁有自己的地址。而每一個節點中,都有一個指標,名為next,這個指標是一個引用型別變數,它會指向另外一個單元的地址,這樣就能夠把資料串聯起來了,因而我們僅需要一個頭指標,就可以根據它逐步獲取到所有單元的資訊,上圖中就是連結串列的內部物理儲存結構示意圖。而樹呢?實際上,樹結構是一種邏輯儲存結構,其物理結構的實現存在兩種——鏈式結構、順序結構,這兩種結構在之後我們都會說明,但是在順序結構儲存的樹中的節點沒有鏈式結構中的節點那麼複雜,因此在這裡我們僅介紹鏈式結構的樹節點,鏈式結構的樹節點和連結串列節點有著相似之處,如下圖所示:

  這就是樹的節點示意圖了,在樹的非連續性儲存或者說是鏈式儲存中,其單個節點的結構就是這樣的:每個節點中具備兩個以上的指標指向其他節點。而我們經常研究的二叉樹的節點,就是被嚴格限制的樹節點,二叉樹的節點被限制為每個節點中必須有兩個指標欄位,指向其他的節點

3.二叉樹

  二叉樹是一種非常重要的資料結構,在上文中也提到了二叉樹的節點構成是被限制的,即必須有兩個指標指向其他的節點,簡而言之,就是在二叉樹中,每個節點最多有兩個分叉,如下圖所示的就是一個典型的二叉樹:

  在這個樹中,每個節點最多有兩個孩子,在二叉樹的真實實現中,即使一個節點沒有孩子,其內部也是需要有指標欄位的定義的,關於這點大部分人認為是理所當然的常識,實際上這是為了便於節點的統一管理,以及樹的擴充套件。

4.重要的樹結構

4.1.滿二叉樹

  可以說是要求最為嚴格的樹結構,首先滿二叉樹必須是二叉樹,其次滿二叉樹要求在整棵樹中:第1層進有根節點,之後第i層節點數必須為第(i-1)行的二倍,可以僅有一層,如果我們按照這個規則隨便畫一棵樹的話,那麼滿二叉樹通常是如下圖所示的:

  在滿二叉樹中,只有一個孩子的節點是不允許存在的,同時我們可以發現,在滿二叉樹中,其節點個數永遠是奇數。同時我們可以感性的理解為,滿二叉樹畫出來的形狀是一個完整的等腰三角形。滿二叉樹因此具備一些數學上的特殊性質,這些特殊性質,和其中的被限制的分叉規則相關,如下圖所示:

  如果我們在一棵滿二叉樹中按照從上到下,從左到右的順序依次為每個節點編號,就會發現一個規律,那就是父節點的二倍,就是左孩子節點的編號,而父節點的二倍加一,就是右孩子節點的編號,也就是說:如果我們為一棵滿二叉樹進行從上到下,從左到右的依次編號時,左孩子的編號 = 根節點編號 * 2;右孩子的編號 = 根節點編號 * 2 + 1。這本質上是一個數學規律,來源於二叉樹的特殊分叉規則。

  需要注意的是,以上的滿二叉樹是國內滿二叉樹的定義,國外的滿二叉樹定義並不是這樣,國外的滿二叉樹定義為:二叉樹中節點要麼有兩個孩子節點,要麼沒有孩子節點,關於這個定義的強度,實際上是弱於國內的二叉樹定義強度的,如果按照國外的二叉樹定義法則,下圖中的樹也是滿二叉樹:

  但是這種樹並不具備上面所提到的數學規律,因此在之後的學習中我們還是要以國內的滿二叉樹定義為準,國外的定義使用需要視具體情況而定。

4.2.完全二叉樹

  完全二叉樹的定義為:將節點從上到下,從左到右依次平鋪的樹。在這個定義中,重點要求了從上到下從左到右依次鋪滿,而沒有要求整棵樹必須完全鋪滿,因此規則限定比完全二叉樹弱一些,在完全二叉樹中,允許最後一層的節點數不滿足滿二叉樹法則,如果將上面的n-1層看做一顆子樹,那麼這棵子樹必須是一個滿二叉樹,我們看圖說話:

  如圖所示是一棵典型的完全二叉樹,其節點滿足所有節點從上到下,從左到右依次平鋪,但是我們可以注意到其最後一層的最後一個元素缺失了,也就是三角形缺了一角,在該樹中,其節點的排列規則是按照滿二叉樹的排列規則排列的,因此其仍然具備滿二叉樹的數學特質,這個數學特質在二叉樹的順序儲存中經常被使用到。我們可以發現在完全二叉樹中,僅允許有一個非葉子節點擁有一個孩子,其餘非葉子節點必須擁有兩個孩子或者沒有孩子,實際上,在這一點上完全二叉樹的定義就把上面的國外滿二叉樹否決了。在國內的定義中,滿二叉樹必定是完全二叉樹,而完全二叉樹是滿二叉樹從最右下角,依次摘取節點而產生的樹,此規律對國外定義不生效。

4.3.二叉排序樹

  二叉排序樹又稱二叉搜尋樹,其外形並沒有被嚴格定義,也就是說二叉排序樹可以不是滿二叉樹或者完全二叉樹,二叉排序樹的定義主要偏重於節點中的權重,或者說是值,二叉排序樹嚴格定義在整棵樹的任意一棵子樹中,其根節點的值必須大於其左子樹中的所有值,小於其右子樹中的所有值(有時也可以反過來定義,定義為小於左子樹中的所有值,並大於右子樹中的所有值,視情況而定)。如下圖,是一棵典型的二叉排序樹:

4.4.平衡二叉樹

  平衡二叉樹是一種專注於子樹深度定義的樹,在平衡二叉樹中,要求整棵樹中沒一顆子樹的根節點的左子樹和右子樹的深度之差不超過1,如下圖所示:

  上面就是典型的非平衡二叉樹和平衡二叉樹,平衡二叉樹通常是一種對二叉排序樹的優化結構,由於深度差過大是會影響其搜尋效率,因此提出了平衡化概念,並將這種深度差不大的樹定義為平衡二叉樹,在一棵二叉排序樹最為平衡的時候,其作為搜尋結構的效率最高。

4.5.堆

  我們大家都知道堆排序是一種很重要的排序,而其中用到的堆結構,也是一種重要的樹結構,需要注意的是堆結構並沒有那麼複雜,其結構定義也比較簡單:堆通常是一個完全二叉樹,並且在排序中我們經常使用順序儲存的方式儲存堆。在堆中,要求每一棵子樹的根節點都要大於或小於其左右子樹中的任意節點,其中每一棵子樹根節點都大於左右子樹的節點的堆被稱為大頂堆,反之稱為小頂堆。堆結構在之前我已在堆排序中進行了詳細的解釋,同時目前我本人對於堆這個結構的高階運用並不瞭解,也沒有深入研究過堆,在此不深入描述,在之後我會更新筆記,寫一些對於堆結構更深入的研究。

4.6.B樹與B+樹

  二者均是基於二叉排序樹的索引樹,通常用於儲存資料,提升搜尋效率之用,其結構並不是太難理解,我們可以理解為多叉排序樹與多叉排序樹plus。二者均是多叉的,其中B樹的資料是儲存在每個節點之中的,而B+樹的資料僅儲存在葉子節點中,這個概念在很多大學中老師並不會特別深入的教,因為其雖然結構容易理解,但是實現卻十分複雜且自由,也就是說在實現時其每個節點很可能相互不同,這就使得其複雜性陡然上升,況且我學的早已還給老師了,因此在這裡不詳細解讀,我找到了一篇比較簡明移動的文章,先附在此處,供我也是供大家學習。

4.7.紅黑樹

  可以說是最為難懂的樹,但是其應用也非常廣泛,在一些非關係型資料庫的儲存結構中,就經常使用到紅黑樹,基於紅黑樹的思想,可以讓查詢時間變得非常短,但是其思想也比較晦澀難懂,在此我也不深入描述,只是做一個標記,提醒我也是大家以後一定要深入學習紅黑樹這一重要的知識點。