最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

《漫畫算法: 小灰的算法之旅》第三章 樹

2023-03-23 11:13 作者:方程星  | 我要投稿

樹和二叉樹

樹和圖是典型的非線性數(shù)據(jù)結(jié)構(gòu)

樹:從“根”衍生出許多“枝干”,再從每個“枝干”衍生出許多更小的“枝干”,最后衍生出更多的“葉子”

現(xiàn)實中的樹

樹(tree)是n(n>=0)個節(jié)點的有限集。

當(dāng)n=0時,稱為空樹。

在任意一個非空樹中,有如下特點:

  1. 有且僅有一個特定的,稱為根(root)的節(jié)點

  2. 當(dāng)n>1時,其余節(jié)點可分為m(m>0)個互不相交的有限集,每一個集合本身又是一個樹,并稱為根的子樹

父子、兄弟節(jié)點

樹的最大層級數(shù),稱為樹的高度或深度。上圖樹的高度為4

二叉樹(binary tree): 這種樹的每個節(jié)點最多有2個孩子節(jié)點


二叉樹結(jié)構(gòu)

滿二叉樹:一個二叉樹的所有非葉子節(jié)點都存在左孩子和右孩子,并且所有葉子節(jié)點都在同一層級上

滿二叉樹

完全二叉樹: 對一個有n個節(jié)點的二叉樹,按層級順序編號,則所有節(jié)點的編號為從1到n。如果這個樹所有節(jié)點和同樣深度的滿二叉樹的編號為從1到n的節(jié)點位置相同,則這個二叉樹為完全二叉樹。

滿二叉樹

二叉樹可以用 鏈?zhǔn)酱鎯Y(jié)構(gòu) 或者 數(shù)組 來進行存儲

鏈?zhǔn)酱鎯Y(jié)構(gòu):

鏈?zhǔn)酱鎯?/figcaption>

二叉樹的每一個節(jié)點包含3個部分,一是存儲數(shù)據(jù)的data變量,二是指向左孩子的left指針,三是指向右孩子的right指針,一個節(jié)點最多可以指向左右兩個孩子節(jié)點

數(shù)組存儲結(jié)構(gòu):

數(shù)組存儲結(jié)構(gòu)

使用數(shù)組存儲時,會按照層級順序把二叉樹的節(jié)點放到數(shù)組中對應(yīng)的位置上。如果某一個節(jié)點的左孩子或右孩子空缺,則數(shù)組的相應(yīng)位置也空出來。

假設(shè)一個父節(jié)點的下標(biāo)是parent, 那么它的左孩子節(jié)點的下標(biāo)就是2×parent+1;

右孩子節(jié)點的下標(biāo)就是2×parent +2

假設(shè)一個左孩子節(jié)點的下標(biāo)是leftChild,那么它的父節(jié)點下標(biāo)就是(leftChild-1) / 2;

右孩子節(jié)點的下標(biāo)是rightChild,那么他的父節(jié)點下標(biāo)就是(rightChild-2) / 2


二叉樹主要應(yīng)用在 查找操作維持相對順序 這兩個方面
1.查找

二叉查找樹(binary search tree): 也叫二叉排序樹(binary sort tree)

二叉查找樹在二叉樹的基礎(chǔ)上增加了以下幾個條件:

* 如果左子樹不為空,則左子樹上所有節(jié)點的值均小于根節(jié)點的值

* 如果右子樹不為空,則右子樹上所有節(jié)點的值均大于根節(jié)點的值

* 左子樹、右子樹也都是二叉查找樹

二叉查找樹

例如查找值為4的節(jié)點,步驟如下:

訪問根節(jié)點6,發(fā)現(xiàn)4<6
訪問節(jié)點6的左孩子節(jié)點3,發(fā)現(xiàn)4>3

訪問節(jié)點3的右孩子節(jié)點4,發(fā)現(xiàn)4=4,這正是要查找的節(jié)點

對于一個節(jié)點分布相對均衡的二叉查找樹來說,如果節(jié)點總數(shù)是n,那么搜索節(jié)點的時間復(fù)雜度就是O(logn),和樹的深度是一樣的

2. 維持相對順序

新插入的節(jié)點,同樣要遵循二叉排序樹的原則。例如插入新元素5,由于5<6、5>3、5>4,所以5最終會插到節(jié)點4的右孩子位置
如插入新元素10,由于10>6、10>8、10>9,所以10最終會插到節(jié)點9的右孩子位置

在二叉查找樹中依次插入9、8、7、6、5、4,查詢節(jié)點的時間復(fù)雜度也退化成了O(n)

如何解決這個問題呢?這就涉及二叉樹的自平衡了;

二叉樹自平衡的方式有多種,如紅黑樹、AVL樹、樹堆等;

除二叉查找樹以外,二叉堆也維持著相對的順序;

不過二叉堆的條件要寬松一些,只要求父節(jié)點的值比它的左右孩子的值都大

二叉樹的遍歷

遍歷是一個線性操作。


數(shù)組遍歷與鏈表遍歷

二叉樹,是典型的非線性數(shù)據(jù)結(jié)構(gòu),遍歷時需要把非線性關(guān)聯(lián)的節(jié)點轉(zhuǎn)化成一個線性的序列


從節(jié)點之間位置關(guān)系的角度來看,二叉樹的遍歷方式有4種:

  1. 前序遍歷

  2. 中序遍歷

  3. 后序遍歷

  4. 層序遍歷

從更宏觀的角度來看,二叉樹的遍歷歸結(jié)為兩大類:

  1. 深度優(yōu)先遍歷(前序遍歷、中序遍歷、后序遍歷)

  2. 廣度優(yōu)先遍歷(層序遍歷)

深度優(yōu)先遍歷:

1. 前序遍歷

二叉樹的前序遍歷,輸出順序是根節(jié)點、左子樹、右子樹

前序遍歷

2. 中序遍歷

輸出順序是左子樹、根節(jié)點、右子樹

中序遍歷

3. 后序遍歷

輸出順序是左子樹、右子樹、根節(jié)點

后序遍歷
實參列表創(chuàng)建的二叉樹

絕大多數(shù)可以用遞歸解決的問題,其實都可以用另一種數(shù)據(jù)結(jié)構(gòu)來解決,這種數(shù)據(jù)結(jié)構(gòu)就是棧

。因為遞歸和棧都有回溯的特性。

使用棧來完成二叉樹的前序遍歷:

遍歷二叉樹的根節(jié)點1,放入棧中
遍歷節(jié)點1的左孩子節(jié)點2,放入棧中
遍歷節(jié)點2的左孩子節(jié)點4,放入棧中

節(jié)點4既沒有左孩子,也沒有右孩子,我們需要回溯到上一個節(jié)點2;

讓舊的棧頂元素4出棧,就可以重新訪問節(jié)點2,得到節(jié)點2的右孩子節(jié)點5;

此時節(jié)點2已經(jīng)沒有利用價值(已經(jīng)訪問過左孩子和右孩子),節(jié)點2出棧,節(jié)點5入棧;

節(jié)點2出棧,節(jié)點5入棧

節(jié)點5既沒有左孩子,也沒有右孩子,我們需要再次回溯,一直回溯到節(jié)點1,所以讓節(jié)點5出棧;

根節(jié)點1的右孩子是節(jié)點3,節(jié)點1出棧,節(jié)點3入棧;

節(jié)點1出棧,節(jié)點3入棧

節(jié)點3的右孩子是節(jié)點6,節(jié)點3出棧,節(jié)點6入棧;

節(jié)點3出棧,節(jié)點6入棧

節(jié)點6既沒有左孩子,也沒有右孩子,所以節(jié)點6出棧,此時棧為空,遍歷結(jié)束

節(jié)點6出棧

廣度優(yōu)先遍歷

層序遍歷: 二叉樹按照從根節(jié)點到葉子節(jié)點的層次關(guān)系,一層一層橫向遍歷各個節(jié)點。

層序遍歷
根節(jié)點1進入隊列
節(jié)點1出隊,輸出節(jié)點1,并得到節(jié)點1的左孩子節(jié)點2、右孩子節(jié)點3。讓節(jié)點2和節(jié)點3入隊
節(jié)點2出隊,輸出節(jié)點2,并得到節(jié)點2的左孩子節(jié)點4、右孩子節(jié)點5。讓節(jié)點4和節(jié)點5入隊
節(jié)點3出隊,輸出節(jié)點3,并得到節(jié)點3的右孩子節(jié)點6。讓節(jié)點6入隊
節(jié)點4出隊,輸出節(jié)點4,由于節(jié)點4沒有孩子節(jié)點,所以沒有新節(jié)點入隊
節(jié)點5出隊,輸出節(jié)點5,由于節(jié)點5同樣沒有孩子節(jié)點,所以沒有新節(jié)點入隊
節(jié)點6出隊,輸出節(jié)點6,節(jié)點6沒有孩子節(jié)點,沒有新節(jié)點入隊

什么是二叉堆

二叉堆本質(zhì)上是一種完全二叉樹,分為最大堆和最小堆。

最大堆的任何一個父節(jié)點的值,都大于或等于它左孩子或右孩子節(jié)點的值。

最大堆

最小堆的任何一個父節(jié)點的值,都小于或等于它左孩子或右孩子節(jié)點的值。

最小堆


二叉堆的根節(jié)點叫作堆頂;

最大堆的堆頂是整個堆中的最大元素;

最小堆的堆頂是整個堆中的最小元素

二叉堆有:1.插入節(jié)點 2.刪除節(jié)點 3.構(gòu)建二叉堆

堆的自我調(diào)整: 把一個不符合堆性質(zhì)的完全二叉樹,調(diào)整成一個堆

1. 插入節(jié)點


目前的是最小堆;

當(dāng)在二叉堆中插入節(jié)點時,插入位置是完全二叉樹的最后一個位置。


插入新節(jié)點,值為0
新節(jié)點的父節(jié)點5比0大,顯然不符合最小堆的性質(zhì)。于是讓新節(jié)點“上浮”,和父節(jié)點交換位置
用節(jié)點0和父節(jié)點3做比較,因為0小于3,則讓新節(jié)點繼續(xù)“上浮”
0和1比較
新節(jié)點0“上浮”到了堆頂位置

2. 刪除節(jié)點

從二叉堆刪除節(jié)點的過程和插入節(jié)點的過程正好相反,所刪除的是處于堆頂?shù)墓?jié)點;

刪除最小堆的堆頂節(jié)點1

最小堆
為了繼續(xù)維持完全二叉樹的結(jié)構(gòu),我們把堆的最后一個節(jié)點10臨時補到原本堆頂?shù)奈恢?br>
讓暫處堆頂位置的節(jié)點10和它的左孩子、右孩子進行比較,如果左孩子、右孩子節(jié)點中最小的一個(顯然是節(jié)點2)比節(jié)點10小,那么讓節(jié)點10“下沉”到最小值節(jié)點位置
讓節(jié)點10和它的左孩子、右孩子做比較,左孩子、右孩子中最小的是節(jié)點7,由于10大于7,讓節(jié)點10繼續(xù)“下沉”

3. 構(gòu)建二叉堆

把一個無序的完全二叉樹調(diào)整為二叉堆,本質(zhì)就是讓所有非葉子節(jié)點依次“下沉”。

無序完全二叉樹(要轉(zhuǎn)換為最小堆)
從最后一個非葉子節(jié)點開始,也就是從節(jié)點10開始。如果節(jié)點10大于它的左孩子、右孩子節(jié)點中最小的一個,則節(jié)點10“下沉”
接下來輪到節(jié)點3,如果節(jié)點3大于它的左孩子、右孩子節(jié)點中最小的一個,則節(jié)點3“下沉”

然后輪到節(jié)點1,如果節(jié)點1大于它的左孩子、右孩子節(jié)點中最小的一個,則節(jié)點1“下沉”。事實上,節(jié)點1小于它的左孩子、右孩子,所以不用改變。

接下來輪到節(jié)點7,如果節(jié)點7大于它的左孩子、右孩子節(jié)點中最小的一個,則節(jié)點7“下沉”
繼續(xù)比較節(jié)點7,繼續(xù)“下沉”,一個無序的完全二叉樹已被構(gòu)建成了一個最小堆

堆的插入和刪除操作,時間復(fù)雜度為O(logn);

構(gòu)建堆的時間復(fù)雜度,時間復(fù)雜度為O(n)

二叉堆的代碼實現(xiàn)

二叉堆的所有節(jié)點都存儲在數(shù)組中

假設(shè)父節(jié)點的下標(biāo)是parent,那么它的左孩子的下標(biāo)就是2×parent+1;

右孩子的下標(biāo)就是2×parent+2

什么是優(yōu)先隊列

優(yōu)先隊列

最大優(yōu)先隊列,無論入隊順序如何,都是當(dāng)前最大的元素優(yōu)先出隊。

最小優(yōu)先隊列,無論入隊順序如何,都是當(dāng)前最小的元素優(yōu)先出隊

優(yōu)先隊列的實現(xiàn)

可以用最大堆來實現(xiàn)最大優(yōu)先隊列

每一次入隊操作就是堆的插入操作,每一次出隊操作就是刪除堆頂節(jié)點

入隊操作:

插入新節(jié)點5
新節(jié)點5“上浮”到合適位置

出隊操作:

讓原堆頂節(jié)點10出隊
把最后一個節(jié)點1替換到堆頂位置
節(jié)點1“下沉”,節(jié)點9成為新堆頂

二叉堆節(jié)點“上浮”和“下沉”的時間復(fù)雜度都是O(logn),所以優(yōu)先隊列入隊和出隊時間復(fù)雜度也是O(logn)

小結(jié)

什么是樹?

樹是n個節(jié)點的有限集,有且僅有一個特定的稱為根的節(jié)點。當(dāng)n>1時,其余節(jié)點可分為m個互不相交的有限集,每一個集合本身又是一個樹,稱為根的子樹。

什么是二叉樹?

二叉樹是樹的一種特殊形式,每一個節(jié)點最多有兩個孩子節(jié)點。

二叉樹包含完全二叉樹和滿二叉樹兩種特殊形式。

二叉樹的遍歷方式有幾種?

根據(jù)節(jié)點之間的位置關(guān)系,可以分為前序遍歷、中序遍歷、后序遍歷、層序遍歷這4種方式;從更宏觀的角度劃分,可以劃分為深度優(yōu)先遍歷和廣度優(yōu)先遍歷兩大類。

什么是二叉堆?

二叉堆是一種特殊的完全二叉樹,分為最大堆和最小堆。

在最大堆中,任何一個父節(jié)點的值,都大于或等于它的左孩子、右孩子節(jié)點的值。

在最小堆中,任何一個父節(jié)點的值,都小于或等于它的左孩子、右孩子節(jié)點的值。

什么是優(yōu)先隊列?

優(yōu)先隊列分為最大優(yōu)先隊列和最小優(yōu)先隊列。

在最大優(yōu)先隊列中,無論入隊順序如何,當(dāng)前最大的元素都會優(yōu)先出隊,這是基于最大堆實現(xiàn)的。

在最小優(yōu)先隊列中,無論入隊順序如何,當(dāng)前最小的元素都會優(yōu)先出隊,這是基于最小堆實現(xiàn)的。


《漫畫算法: 小灰的算法之旅》第三章 樹的評論 (共 條)

分享到微博請遵守國家法律
普宁市| 全南县| 尤溪县| 永福县| 铁力市| 八宿县| 崇州市| 黎川县| 旅游| 综艺| 松潘县| 盐边县| 石景山区| 龙井市| 巴林左旗| 梨树县| 诏安县| 信丰县| 嘉兴市| 固阳县| 宜昌市| 大同市| 和龙市| 祁阳县| 敦化市| 科尔| 青冈县| 龙游县| 鄯善县| 库尔勒市| 安吉县| 云梦县| 商丘市| 苍溪县| 思茅市| 调兵山市| 甘肃省| 洪洞县| 大同市| 西青区| 邵阳市|