樹和二叉樹之線索二叉樹(包括對前驅後繼的疑惑)

1 樹的概念

樹的結點:包含一個數據元素及若干指向其子樹的分支。

結點的度:結點擁有的子樹數目。(一個分支就是一個樹,二叉樹結點的度最多爲2,最少爲0)

葉子:度爲0的結點稱爲葉子。

樹的度:整個樹內出現的最大結點的度就是樹的度。

孩子:結點的子樹的根稱爲該結點的孩子。(結點的子樹是指這個結點的一個分支,這個分支就是一個子樹)

雙親:子樹的根結點上面的結點就是他的雙親。(雙親是值一個父結點,不要看到雙以爲是兩個結點)

結點的深度:樹中結點的最大層數稱爲樹的深度或高度。

如圖1所示:

                                                                                       圖1 樹的結構

1.1、二叉樹

1.1.1 二叉樹的特點

由二叉樹定義以及圖示分析得出二叉樹有以下特點:
1)每個結點最多有兩顆子樹,所以二叉樹中不存在度大於2的結點。
2)左子樹和右子樹是有順序的,次序不能任意顛倒。
3)即使樹中某結點只有一棵子樹,也要區分它是左子樹還是右子樹。

1.1.2 二叉樹的性質

性質1  在二叉樹的第i層上至多有2^{i-1}個結點。

性質2  深度爲k的二叉樹至多有2^{k}-1個結點。

性質3  任意二叉樹,如果度爲0的結點樹等於度爲2的結點樹+1。

性質4  具有n個結點的完全二叉樹的深度爲\left | \log _{2}n\right |+1,其中\left | \log _{2}n \right |是向下取整(如4.3取整數4)。

性質5  若對含 n 個結點的完全二叉樹從上到下且從左至右進行 1 至 n 的編號,則對完全二叉樹中任意一個編號爲 i 的結點有如下特性:

(1)若 i=1,則該結點是二叉樹的根,無雙親, 否則,編號爲 [i/2] 的結點爲其雙親結點;
(2)若 2i>n,則該結點無左孩子, 否則,編號爲 2i 的結點爲其左孩子結點;
(3)若 2i+1>n,則該結點無右孩子結點, 否則,編號爲2i+1 的結點爲其右孩子結點。

1.2、滿二叉樹

1.2.1 滿二叉樹定義

在一棵二叉樹中。如果所有分支結點都存在左子樹和右子樹,並且所有葉子都在同一層上,這樣的二叉樹稱爲滿二叉樹。

1.2.2 滿二叉樹的特點有:

(1)葉子只能出現在最下一層。出現在其它層就不可能達成平衡。
(2)非葉子結點的度一定是2。
(3)在同樣深度的二叉樹中,滿二叉樹的結點個數最多,葉子數最多

img

                                           圖2 滿二叉樹

1.3、完全二叉樹

1.3.1 完全二叉樹定義

若設二叉樹的深度爲h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第 h 層所有的結點都連續集中在最左邊,這就是完全二叉樹。(國內的定義).

1.3.2 完全二叉樹特點:

(1)葉子結點只能出現在最下層和次下層。

(2)最下層的葉子結點集中在樹的左部。

(3)倒數第二層若存在葉子結點,一定在左部連續位置。

(4)如果結點度爲1,則該結點只有左孩子,即沒有右子樹。

(5)同樣結點數目的二叉樹,完全二叉樹深度最小。

如圖3所示:

img

                                                         圖3 完全二叉樹

具體看該博客:https://blog.csdn.net/xiaojin21cen/article/details/96148829#371__235

1.4 線索二叉樹

這裏只針對本人曾經理解線索二叉樹時存在的誤區做一些筆記,方便自己閱讀。

首先要知道爲什麼需要線索二叉樹,是爲了更容易得到一顆二叉樹任意一個結點的前去後繼結點,對於一般的二叉樹我們想要知道某個結點的前去後繼時,那就是對該二叉樹進行一次遍歷,那麼問題來了?

(1)什麼是結點的前驅後繼

解析:比如一顆二叉樹經過中序遍歷後,得到了一個線性的排序(這裏的線性表示將那些結點按照中序遍歷放入一個線性數組),比如一顆二叉樹中序排列後爲HDIBJEAFCG,J結點的前驅爲B,後繼爲E,所以前驅後繼是按照排序來定義

(2)書上和博客裏面只有中序遍歷二叉樹的前驅和後繼,難道不存在前序、後序遍歷的前驅後繼?還是用的很少,還是不存在?

解析:前序、中序、後序遍歷結點會得到不同的排列,所以前驅後繼都不一樣,一般我們要知道這顆二叉樹在創建時被要求按照什麼方式存儲的,比如前序還是中序或後序方式創建。譬如有個算法題:給出二叉樹的一個結點,返回它中序遍歷順序的下一個結點。所以他也會要求你返回中序順序的下一個,也就是中序結點的後繼。

(3)很多書上說要使用線索二叉樹將結點的前驅後繼信息存放在該結點的空指針域上,因爲普通二叉樹每次想要得到一個結點的前驅後繼時,都要重新遍歷一次二叉樹,而線索二叉樹只需要遍歷一次後就能終身想用。爲什麼普通二叉樹每次都要遍歷,不是遍歷一次後就把排序存起來了嗎?這樣每次都去那個數組裏面找它的前後不就行了?

解析:我的想法,首先我們確實可以遍歷的時候將二叉樹按照順序重新排序放在一個數組裏,這個數組中a[i]的前驅是a[i-1],後繼是a[i+1],可是當一個二叉樹很大時(10000個結點),如果你按照數組存起來,佔用新的內存,工程中可能要不停的尋找前去後繼,所以數組佔用的內存不能釋放,這將是多恐怖的事情,然後我突然想要找到第9998結點的前驅後繼,難道你去對比數組裏面的值,找到後再分別輸出他的前驅和後繼嗎?既然不能那還有一種方式,每次想知道一個結點時,你傳入這個結點地址(一般傳入的參數就是這個結點的指針,有了該節點指針你可以指向自己結構體內的元素),我再去遍歷這個二叉樹,遍歷過程中,結點指針會匹配到我們要找的那個結點,這時再將它遍歷時前一個結點指針與後一個將要遍歷的接口保存起來。下一次我又要樹裏面的一個結點的前去後繼,這時你還是要重新遍歷,對於需要經常訪問某個結點的前驅後繼代碼中,這樣時間不划算。所以出現了線索二叉樹,創建二叉樹時(創建過程也在遍歷)就把空域的指針指向前驅後繼,這樣遍歷一次後,那些結點本身包含了前驅後繼的信息,你需要那裏一個就找這個結點內的包含前去後繼信息的指針。

算法實踐博客:https://blog.csdn.net/u010889616/article/details/49511161

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章