大話數(shù)據(jù)結(jié)構(gòu)之樹(一)

引子

繼線性表與鏈表的概念篇與源碼剖析篇之后,本來(lái)這篇打算剖析一下HashMap,因?yàn)槊看蚊嬖囍谐霈F(xiàn)率最高的數(shù)據(jù)結(jié)構(gòu)就是HashMap。 但是忽然發(fā)現(xiàn), 1.8之前的JDK的HashMap基于數(shù)組和鏈表組合實(shí)現(xiàn),到了1.8之后完全變了,至于它是怎么實(shí)現(xiàn)的,這里賣個(gè)關(guān)子,透漏一下就是跟樹有關(guān)。因此本篇起開始樹系列。

在數(shù)據(jù)結(jié)構(gòu)中,樹和圖是兩種比較復(fù)雜的結(jié)構(gòu)之一;里面涉及各種概念, 各種類型以及不同的算法實(shí)現(xiàn), 希望想學(xué)習(xí)的小伙伴可以跟著我的節(jié)奏,一起克服這些困難。而且重要的是, 樹在面試中出現(xiàn)的次數(shù)僅次于HashMap, 所以,打起精神來(lái)吧!


先來(lái)說(shuō)說(shuō)普通的樹

樹是由n(n>=1)個(gè)有限節(jié)點(diǎn)組成一個(gè)具有層次關(guān)系的集合。把它叫做“樹”是因?yàn)樗雌饋?lái)像一棵倒掛的樹,也就是說(shuō)它是根朝上,而葉朝下的。它具有以下的特點(diǎn):
1.每個(gè)節(jié)點(diǎn)有零個(gè)或多個(gè)子節(jié)點(diǎn);
2.沒有父節(jié)點(diǎn)的節(jié)點(diǎn)稱為根節(jié)點(diǎn);
3.每一個(gè)非根節(jié)點(diǎn)有且只有一個(gè)父節(jié)點(diǎn);
4.除了根節(jié)點(diǎn)外,每個(gè)子節(jié)點(diǎn)可以分為多個(gè)不相交的子樹;

自然中的樹


image.png

數(shù)據(jù)結(jié)構(gòu)中的樹


image.png

再來(lái)看一下百度的解釋, 我們發(fā)現(xiàn)確實(shí)是一顆倒著的樹,哈哈!重點(diǎn)看圖2,我們總結(jié)一下樹的特點(diǎn):

  1. 有且僅有一個(gè)跟節(jié)點(diǎn)A(理解為樹根),也可以沒有(空樹)
  2. 每個(gè)節(jié)點(diǎn)(根節(jié)點(diǎn)除外)只能有一個(gè)父節(jié)點(diǎn),可以有多個(gè)子節(jié)點(diǎn)
  3. 層次結(jié)構(gòu)A | BC | DE | ####
  4. 從任意節(jié)點(diǎn)來(lái)看, 樹是一對(duì)多的關(guān)系
  5. 樹是節(jié)點(diǎn)的有窮集(節(jié)點(diǎn)數(shù)不是無(wú)限的)

對(duì)照著上圖,來(lái)看一下,是否符合上面說(shuō)的特點(diǎn)!看完上面的描述,大體應(yīng)該對(duì)樹結(jié)構(gòu)有一個(gè)直觀的了解了。 那么來(lái)科普一下關(guān)于樹的概念


1.每個(gè)元素稱為結(jié)點(diǎn)(node)
2.節(jié)點(diǎn)的度:一個(gè)節(jié)點(diǎn)含有的子樹的個(gè)數(shù)稱為該節(jié)點(diǎn)的度;
3.葉節(jié)點(diǎn)或終端節(jié)點(diǎn):度為0的節(jié)點(diǎn)稱為葉節(jié)點(diǎn);
4.非終端節(jié)點(diǎn)或分支節(jié)點(diǎn):度不為0的節(jié)點(diǎn);
5.雙親節(jié)點(diǎn)或父節(jié)點(diǎn):若一個(gè)節(jié)點(diǎn)含有子節(jié)點(diǎn),則這個(gè)節(jié)點(diǎn)稱為其子節(jié)點(diǎn)的父節(jié)點(diǎn);
6.孩子節(jié)點(diǎn)或子節(jié)點(diǎn):一個(gè)節(jié)點(diǎn)含有的子樹的根節(jié)點(diǎn)稱為該節(jié)點(diǎn)的子節(jié)點(diǎn);
7.兄弟節(jié)點(diǎn):具有相同父節(jié)點(diǎn)的節(jié)點(diǎn)互稱為兄弟節(jié)點(diǎn);
8.樹的度:一棵樹中,最大的節(jié)點(diǎn)的度稱為樹的度;
9.節(jié)點(diǎn)的層次:從根開始定義起,根為第1層,根的子節(jié)點(diǎn)為第2層,以此類推;
10.樹的高度或深度:樹中節(jié)點(diǎn)的最大層次;
11.堂兄弟節(jié)點(diǎn):雙親在同一層的節(jié)點(diǎn)互為堂兄弟;
12.節(jié)點(diǎn)的祖先:從根到該節(jié)點(diǎn)所經(jīng)分支上的所有節(jié)點(diǎn);
13.子孫:以某節(jié)點(diǎn)為根的子樹中任一節(jié)點(diǎn)都稱為該節(jié)點(diǎn)的子孫。
14.森林:由m(m>=0)棵互不相交的樹的集合稱為森林;


以上概念都是根據(jù)社會(huì)中的家譜與自然中的事物命名的,結(jié)合家譜應(yīng)該很好理解。先給一個(gè)簡(jiǎn)單的樹的圖,說(shuō)明一下

image.png
  1. 樹的單位是節(jié)點(diǎn), (線性表的單位是什么? 元素; 鏈表的單位也是節(jié)點(diǎn); 圖的單位是頂點(diǎn))

A-F本身不算節(jié)點(diǎn),A-F所在的小球是節(jié)點(diǎn); 節(jié)點(diǎn)包含兩個(gè)信息: 與其他節(jié)點(diǎn)的關(guān)系, 節(jié)點(diǎn)的值(A, B, C)

  1. 節(jié)點(diǎn)的度

一個(gè)節(jié)點(diǎn)所包含的子樹(子節(jié)點(diǎn))的個(gè)數(shù),比如A,B的度都是2(包含兩個(gè)子節(jié)點(diǎn)); C的度是1(僅包含子節(jié)點(diǎn)F); D, E, F的度是0(無(wú)子節(jié)點(diǎn))

  1. 根節(jié)點(diǎn)與葉節(jié)點(diǎn)

把一顆樹倒過(guò)來(lái)就是樹結(jié)構(gòu), 那么A就是樹根,稱為根節(jié)點(diǎn), 根節(jié)點(diǎn)沒有父節(jié)點(diǎn), 像樹的根。D,E,F就是葉節(jié)點(diǎn), 葉節(jié)點(diǎn)沒有子節(jié)點(diǎn),像樹的葉子。

  1. 父節(jié)點(diǎn), 子節(jié)點(diǎn), 兄弟節(jié)點(diǎn)

關(guān)系都是相對(duì)的。 A的子節(jié)點(diǎn)是B和C, 則B和C的父節(jié)點(diǎn)就是A。如果學(xué)過(guò)DNA,可以根據(jù)DNA的圖進(jìn)行關(guān)系認(rèn)定。B和C具有同一個(gè)父親(父節(jié)點(diǎn)), 那么B和C必然是兄弟(互為兄弟節(jié)點(diǎn))。

  1. 堂兄弟節(jié)點(diǎn), 祖先節(jié)點(diǎn)

現(xiàn)實(shí)中的堂兄弟必然是父輩是親兄弟。 那么B和C具有相同的父節(jié)點(diǎn),是親兄弟。 所以B的孩子和C的孩子就是堂兄弟。也即D,E,F互為堂兄弟節(jié)點(diǎn)。祖先節(jié)點(diǎn), 一個(gè)節(jié)點(diǎn)所有的先輩節(jié)點(diǎn),如F的祖先節(jié)點(diǎn),C(父節(jié)點(diǎn)), A(祖父節(jié)點(diǎn))。

  1. 節(jié)點(diǎn)的層次

從根節(jié)點(diǎn)開始, 每一層的節(jié)點(diǎn)的所有子節(jié)點(diǎn)算一層。如A是第一層, A的子節(jié)點(diǎn)BC是第二層, BC的子節(jié)點(diǎn)DEF是第三層,以此類推。

  1. 樹的高度或深度

節(jié)點(diǎn)的最大層次,上圖樹的高度是3; 如果F節(jié)點(diǎn)還有一個(gè)子節(jié)點(diǎn)G, 那么高度就是4。

8.森林

一顆樹,只能有一個(gè)根節(jié)點(diǎn); 如果一個(gè)圖中,有N個(gè)節(jié)點(diǎn)是沒有父節(jié)點(diǎn)的, 那么整個(gè)圖就是森林。

樹的分類

二叉樹
滿二叉樹 與 完全二叉樹
二叉查找樹(二叉搜索樹或二叉排序樹)
平衡二叉樹(AVL樹)
紅黑樹

二叉樹: 每個(gè)節(jié)點(diǎn)最多只能有兩個(gè)子節(jié)點(diǎn)就是二叉樹; 可以沒有子節(jié)點(diǎn)(葉子節(jié)點(diǎn)), 可以只有一個(gè)子節(jié)點(diǎn),也可以有兩個(gè)子節(jié)點(diǎn)。上圖就是一個(gè)二叉樹, 它的每個(gè)節(jié)點(diǎn)最多都只有兩個(gè)子節(jié)點(diǎn)

滿二叉樹: 我們知道二叉樹的每個(gè)節(jié)點(diǎn)最多只有2個(gè)子節(jié)點(diǎn), 那就是它可以允許節(jié)點(diǎn)有一個(gè)或沒有子節(jié)點(diǎn)的。比如上圖的C節(jié)點(diǎn)只有一個(gè)右孩子F。 那么滿二叉樹就是滿的二叉樹,什么是滿的? 除了葉子節(jié)點(diǎn)外,每個(gè)節(jié)點(diǎn)必須都要2個(gè)子節(jié)點(diǎn),不允許一個(gè)子節(jié)點(diǎn)的存在。如果上圖C節(jié)點(diǎn)添加一個(gè)左孩子G , 那么這就是一個(gè)滿二叉樹了。

二叉查找樹,或稱為二叉搜索樹, 二叉排序樹: 首先它是一個(gè)二叉樹,如果不明白二叉樹,看上面。其次它要滿足一定的條件(如果每個(gè)節(jié)點(diǎn)的值是一個(gè)整數(shù)為例):

  1. 如果它的左子樹不為空,那么左孩子的值一定小于根節(jié)點(diǎn)的值
  2. 如果它的右子樹不為空,那么右孩子的值一定大于根節(jié)點(diǎn)的值

看上面兩條其實(shí)很好理解, 我們總結(jié)一下就是:二叉搜索樹的節(jié)點(diǎn)的值是有序的; 它總是符合一個(gè)規(guī)律: 左孩子的值 < 父節(jié)點(diǎn)的值 < 右孩子的值。 還是不好理解? 那么上個(gè)圖看一下

image.png

我們可以看到,每個(gè)節(jié)點(diǎn)的左子樹的值,都小于根節(jié)點(diǎn);每個(gè)節(jié)點(diǎn)的右子樹的值,都大于根節(jié)點(diǎn)。以根節(jié)點(diǎn)12為例, 左子樹是5, 2, 9; 右子樹是18, 15, 19, 17, 16。 拿出任意節(jié)點(diǎn)5, 左孩子節(jié)點(diǎn)是2 < 5, 右孩子節(jié)點(diǎn)是9 > 5。二叉排序樹就是每個(gè)節(jié)點(diǎn)都符合這標(biāo)準(zhǔn)的二叉樹。

在面試或?qū)W習(xí)中, 二分法是極其常用的,它可以在一定程度上大幅度提高查詢效率; 那么對(duì)比一下二叉排序樹, 是不是發(fā)現(xiàn), 二分法和二叉排序樹的思想是一樣的?

平衡二叉樹,又稱AVL樹: 首先,它還是一個(gè)二叉樹。 其次是平衡, 那么平衡的是什么呢? 子樹的高度。 它是一顆二叉樹, 滿足任一節(jié)點(diǎn)的左右子樹高度差不會(huì)大于1。 高度是怎么定義的還有印象嗎?

image.png

紅黑樹: 這是一種自平衡二叉樹, 后文中會(huì)說(shuō)到。

被動(dòng)的接受永遠(yuǎn)是學(xué)習(xí)的障礙, 接下來(lái)布置一個(gè)小練習(xí)

1. 自己嘗試著畫一下樹的結(jié)構(gòu),包括二叉樹, 二叉排序樹, 二叉平衡樹,森林等
2. 參考下圖,用代碼實(shí)現(xiàn)一顆樹(因?yàn)榻酉聛?lái)要將遞歸以及如何遍歷二叉樹)

image.png

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容