資料結構自學筆記五 樹(上)

2021-10-09 08:14:25 字數 4344 閱讀 3531

結點間的關係

樹的其他概念

樹的儲存結構

二叉樹寫在結尾的話

樹是n個結點的有限集。n=0時稱為空樹;n>0時為非空樹。

在任意一棵非空樹中:有且只有乙個特定的結點,稱為(root);當樹不只有乙個結點時,其餘節點可分為m個互不相交的有限集,其中每乙個集合本身又是一棵樹,並且稱為的子樹。

乙個結點擁有子樹的數量稱為該結點的

樹的度是樹內各結點的最大值

度為0的結點,也稱終端結點

度不為0的節點稱為非終端結點分支結點,也可稱為內部結點(除根結點)

結點的 子樹的 根稱為該結點的孩子。相應地,該結點稱為孩子的雙親。(這種命名也體現了結點的子樹不相交的特點)

同乙個雙親的孩子間互稱兄弟(某種意義上的常識hhh)

結點的祖先是從根到該結點所經分支上的所有結點。

以某結點為根的子樹中的任意結點都稱為該結點的子孫

這裡要特別注意一點!確實結點間不少關係都可以通過現實中的家族關係來模擬,但是祖先這個概念和長輩是不同的概念。在生活中我們會稱我們的姨父姨母為「長輩」,但是他們不是你的「祖先」,因為你沒有繼承他們的基因。

所以,在樹中,可以通過由層序低到層序高的線連線起來的結點才可以稱祖先和子孫。

從根開始定義,根為第一層,根的孩子為第二層,以此類推

雙親在同一層的結點間互稱堂兄弟

樹中結點的最大層次稱為樹的深度或高度。

如果將樹中結點的各子樹看成從左到右是有次序的,不能互換的,則稱該樹為有序樹,否則稱為無序樹。

若干棵互不相交的樹的集合稱為森林

以上就是樹的基本概念。其實我感覺這個資料結構也是從生活中抽象來的,和生活中很多概念蠻貼切的。如果能模擬這些概念當然有助於記憶,但是也不可完全照搬,要注意樹獨特的地方。

接下來介紹樹的儲存結構。

樹其實也是一種特殊的線…誒,打順手了,這次應該要反過來了:線性表是一種結構特殊的樹!假設每個結點只有乙個孩子,那這不就是乙個線性表麼!

但是在這裡,我們要討論的是一棵平凡的樹的儲存結構,就不能像之前講線性表那樣,簡單粗暴地把儲存結構分為順序儲存和隨機儲存兩種了。

這次,我們按照儲存的思想方法,把儲存結構分為:雙親表示法、孩子表示法、孩子兄弟表示法

這是一種順序儲存結構的儲存方式,通過建立結構體陣列來存放樹。

其想法為:定義乙個結構體node,資料域存每個結點的資料,指標域存乙個整型數,用來記錄雙親的陣列下標。其中根結點的指標域設為-1。

struct node

;int

main()

這也告訴我們乙個道理,資料結構的設計是靈活、需要變通的,而不是死板、固定的。

孩子表示法屬於順序儲存結構和隨機儲存結構共同使用。

其思想方法為:設計乙個結構體node,和乙個結構體ptr。前者用來表示結點,資料域存結點資料,指標域存乙個ptr*型別的指標(如果結點沒有孩子則為null)。ptr表示用來存放孩子的下標的結構體,資料域存放相應孩子的下標,指標域存放指向存放該孩子右兄弟的下標的ptr結構體的指標。

每個節點依然是通過順序儲存結構存在乙個結構體陣列裡。

這個資料結構在設計上非常重視孩子,通過雙親可以知道每個孩子的位置。但是相反,孩子們卻不知道雙親的位置。像極了當今社會的家庭關係,雙親總是牽掛著孩子,而孩子們卻忘記去關心雙親。

我們當然不能做這樣的人!因此,我們把孩子表示法和上面的雙親表示法結合一下,讓node結構體的指標域再多乙個int型變數,存放每個結點雙親的陣列下標。雙親和孩子互相牽掛,多好!改進後這種和諧的表示法被稱為雙親孩子表示法

上述兩種表示法,分別關照了雙親和孩子,但是似乎忽視了兄弟之間的關係。我們接下來要講的這種表示法叫做孩子兄弟表示法。這種表示法有著極為重要的作用!並且形成了一棵極其特殊且重要的樹——二叉樹。

這種表示法採用的是一種隨機儲存結構。思想方法大致是這樣的。

定義結構體node,這個node有乙個資料域、乙個左指標和乙個右指標。左指標命名為firstchild,指向自己的長子(最左邊的孩子);右指標命名為rightbrother,指向自己右邊的兄弟。

這種表示法的好處在於,每個結點只會有至多兩個孩子,或者說,每個結點最多有兩個分叉。像這種結構的樹,我們把它稱為二叉樹。二叉樹有很多好用的性質,之後我們會介紹到它。

當然,如果你想要快速查詢到結點的雙親,也可以再增加乙個指標域專門指向雙親。

二叉樹的名氣是如此之大,以至於我在剛學c語言的時候就聽過它的名字。只不過一直沒有見過它本「樹」,也不清楚它的作用與性質。

不過所幸,我現在知道了。久仰大名了,二叉樹!

我們只需要在樹的定義上做進一步約束,即可得到二叉樹的定義。

二叉樹是n個節點的有限集合。當n=0時,該集合為空集,稱為空二叉樹;當n大於0時,該二叉樹由根結點和兩棵不相交的二叉樹(稱為左子樹和右子樹)組成。(子二叉樹也可為空樹)

樹和二叉樹的定義都採用的是遞迴定義的方式定義的。如果你已經理解了什麼是樹,那麼通俗的來講,二叉樹就是每個結點至多有兩個分叉(孩子)的樹,所以叫二叉樹。

1.最多有二個子樹

2.左子樹和右子樹是有順序的,不能顛倒。即使樹中某個結點只有一棵子樹,也要區分它是左子樹還是右子樹。(這或許與結點的指標域有關,畢竟乙個左指標乙個右指標,不能亂指呀)

1.斜樹

所有結點都只有左子樹的二叉樹叫左斜樹,反之叫右斜樹。斜樹可以看做線性表,實際上線性表就是一種特殊結構的樹。

2.滿二叉樹

所有分支結點都存在左子樹和右子樹,且所有葉結點都在同一層上的樹叫做滿二叉樹。

3.完全二叉樹

對一棵具有n個節點的二叉樹按層序編號,如果其結點的編號與滿二叉樹中結點的編號完全一致,則稱之為完全二叉樹。

或者換一種理解,二叉樹中所有的結點嚴格按照從左到右、從上到下的順序排布,則稱之為完全二叉樹。

滿二叉樹一定是完全二叉樹,但反之不成立。

之前提到了,二叉樹有一些非常好的性質,讓我們可以使用它完成一些事情。我們現在來介紹二叉樹的性質。

1.在二叉樹的第i層上至多有2^(i-1)個結點

考慮滿二叉樹的情況,相當於每一層的結點數構成了等比數列。公比為2

2.深度為k的二叉樹至多有2^k -1個結點

理由同上,等比數列求和

3.對於任何一棵二叉樹,如果其終端結點(度為0)數為n0,度為2的結點數為n2,則n0=n2+1

我們暫且把連線兩個結點之間的東西稱為連線線,算一算一棵樹有多少根連線線

如果從接收的角度思考,除了根結點外,每個結點都有一根連線線連線它,所以連線線的數量為n1+n2+n0-1

如果從發出的角度思考,發出的總連線線數為2*n2+n1。兩個式子取等號,移項,得證n0=n2+1

4.具有n個結點的完全二叉樹的深度為(int)log 2 n+1

對於乙個深度為k的完全二叉樹,它的結點數肯定要大於深度為k-1的滿二叉樹,即n≥2^(k-1);它的結點數肯定要小於等於深度為k的滿二叉樹,即n≤2^k - 1。取證即可得證。

5.如果對一棵有n個結點的完全二叉樹的結點按層序編號,對任意結點i,有:

(1)如果i=1,則結點i是二叉樹的根,無雙親;如果i>1,則其雙親是結點(int)i/2

(2)如果2i>n,則結點i無左孩子;否則其左孩子是結點2i

(3)如果2i+1>n,則結點i無右孩子;否則其右孩子是結點2i+1

我們想想,對於一棵完全二叉樹而言,其按層序編號,編號是不是連續的?

答案是肯定的,這也就意味著,如果採用順序儲存結構,完全二叉樹的這種非常好的特性使得空間完全不會被浪費!

但如果是一棵普通的樹呢?我們同樣可以用類似的方法先將其補全為完全二叉樹,然後建立順序儲存結構,不過之前補上的地方在這裡應當設為null。

不過,如果這是一棵右斜樹,那麼就會造成極大的空間浪費。因此,只有完全二叉樹才比較適合使用順序儲存結構。

其實在講孩子兄弟表示法時,我們就提到了這個方法。構建節點結構體,設定左指標和右指標,分別指向左孩子和右孩子。這種方法非常形象的表示了二叉樹的結構。這樣的鍊錶我們稱為二叉鍊錶。

當然,我們也可以在指標域加上第三個指標,指向雙親。這樣的鍊錶稱為三叉鍊錶。

關於樹的內容已經學了一半了,明天我們會學二叉樹的功能的**實現,有些小期待。

今天是教師節,祝願我的恩師們,以及所有的善良的老師們節日快樂~

資料結構自學筆記六 樹(下)

前三種遍歷演算法的 實現 由遍歷結果推導二叉樹結構 二叉樹的建立 樹 森林 二叉樹的轉換 樹與森林的遍歷 赫夫曼樹及其應用 寫在後面的廢話 不同於線性表,二叉樹的結構是非線性的,其遍歷方式也有所不同。我們先給二叉樹的遍歷乙個定義 指從根結點出發,按照某種次序依次訪問二叉樹中所有結點,使得每個結點被訪...

資料結構 並查集 自學筆記

為了能夠動態維護若干個不重疊的集合,並支援合併於查詢,我們使用乙個樹形結構儲存每個集合,樹上的每個節點都是乙個元素,根節點是集合的代表元素。並查集的操作包括兩個 get 查詢元素屬於哪乙個集合 返回根節點 merge 將兩個元素 或集合 合併。路徑壓縮 按秩合併 路徑壓縮 可以在每次get操作時,將...

資料結構 樹上莫隊

題意 給定一棵 n 2 leq n leq 10 5 個結點的樹,根結點為 1 號結點,每個結點有顏色 c leq c leq 10 5 然後 m 1 leq m leq 10 5 次詢問,每次詢問給兩個引數 v,k 詢問 v 子樹內,頻次至少有 k 次的顏色有多少種。題解 經典計數顏色的數量,使用...