30分鐘看完數據結構和算法原理(包括二叉樹,圖,各種排序算法)

1.樹與二叉樹

結點的度:一個結點的有幾個孩子(孫子不算)

樹的度:所有結點中,其中一個結點最大的度

葉子結點:沒有孩子的結點

分支結點:左右分支的結點

內部結點:夾在中間的結點,既不是葉子和根結點

父結點:作爲父親的結點

子結點:作爲孩子的結點

兄弟結點:同一個父親的結點

層次:樹的層次

 

2.二叉樹的性質

2.1 分類

滿二叉樹:結點都是滿的的二叉樹

完全二叉樹:結點按順序分佈的,但是沒有滿的二叉樹

非完全二叉樹:結點沒有按順序分佈的二叉樹

 

3.二叉樹的遍歷

前序遍歷:根節點最先訪問,即根-左-右

中序遍歷:根結點中間訪問,即左-根-右

後序遍歷:根結點最後訪問,即左-右-根

層次遍歷:一層一層訪問

圖上結果:

前:1 ,2 ,4 ,5,7 ,8 ,3, 6

中:4 ,2 ,7 ,8, 5,1 , 3, 6

後:4 ,8, 7, 5 ,2, 6 ,3 ,1

層次:1, 2, 3 ,4 ,5 ,6 ,7 ,8

3.2二叉樹的反向構造

反向構造:就是知道其中兩種遍歷,來構建二叉樹(必須有中序遍歷,否則不能推出)

下圖:先看前序遍歷的A爲根結點,所以中序遍歷中,A的左邊爲左子樹,右邊爲右子樹,依次推下面的

 

結果:

4.普通樹轉成二叉樹

樹轉二叉樹的兩個個原則:

1.普通樹的孩子結點變成新二叉樹的左子樹結點

2.普通樹的兄弟結點變成新二叉樹的右子樹結點

看起來很抽象,下面用例子分析

如下圖:

普通樹的根結點是1,孩子結點有2, 3 , 4

那麼(根據原則1)先把2拿出來,作爲新二叉樹左子樹結點,而在普通樹中3作爲2的兄弟,所以在新二叉樹中3(根據原則2)只能做2的右子樹,

接下來3有5, 6 ,7三個孩子結點,同理,5作爲新二叉樹的左子樹,而在普通樹中6作爲5的兄弟,所以在新二叉樹中6(根據原則2)只能做5的右子樹,依次類推,得出新的二叉樹的結構

 

5.查找二叉樹(又稱排序二叉樹)

查找二叉樹:根結點要大於左子樹,小於右子樹

6.最優二叉樹(哈夫曼樹)

樹的路徑長度:結點與結點的路徑距離

權:結點的值

帶權路徑長度:樹的路徑長度*結點的值

樹的帶權路徑長度:葉子結點的帶權路徑長度累加

如下圖(假設結點與結點的路徑距離爲1):

左邊第一棵樹的帶權路徑長度:2*2+4*3+8*3+1*1=41

左邊第二棵樹的帶權路徑長度:4*2+1*3+2*3+8*1=25

怎麼構造哈夫曼樹?

如下圖右邊:

在5,29,7,8,14,23,3,11中找出兩個最小的值即5,3

5,3組成小樹,和爲8,所以8放到原先的數列中,但是8重複了,只能取一個

29,7,8,14,23,11中找出兩個最小的值即7,8,依次類推,得出哈夫曼樹

7.線索二叉樹

線索二叉樹:由於二叉樹的葉子結點或分支結點,有時左右子樹的指針地址是空的,爲了利用資源和快速資源尋找,產生了線索二叉樹

分類:

前序線索二叉樹:先讓二叉樹進行前序遍歷,其中有空指針地址的結點(即結點沒有2個孩子),然後讓該結點的左指針地址指向前一個結點,右指針地址指向後一個結點

中序線索二叉樹:先讓二叉樹進行中序遍歷,其中有空指針地址的結點(即結點沒有2個孩子),然後讓該結點的左指針地址指向前一個結點,右指針地址指向後一個結點

後序線索二叉樹:先讓二叉樹進行後序遍歷,其中有空指針地址的結點(即結點沒有2個孩子),然後讓該結點的左指針地址指向前一個結點,右指針地址指向後一個結點

這麼說,太抽象了,用一個例子分析

如下圖:

左下角的樹(構造前序線索二叉樹)的前序遍歷:A B D E H C F G I,

那麼有空地址的結點有:D E H F G I

依照定義,D的左指針地址指向B,D的右邊指針地址指向E,然後依次類推,得出前序線索二叉樹

 

8.平衡二叉樹

之前有排序二叉樹,但是不夠平衡,爲了達到更加優化,提出了平衡二叉樹

 

 

9.圖

分類:無向圖(沒有方向),有向圖(有方向)

圖與樹的本質區別:圖是有環的,而樹沒有環

 

9.1圖的存儲

兩種形式:鄰階矩陣,鄰階表

(1)鄰階矩陣:採用一個二維數組存儲,用0和1代表該結點有沒有連線

太抽象了,例子分析

如下圖:

左邊的圖共有5個結點,所以矩陣需要5*5個

看圖的右邊的矩陣分析,

第一行第一列是0,因爲左邊的“圖”中,“1”這個結點沒有與自己連線,

第一行第二列是1,因爲左邊的“圖”中,“1”這個結點沒有與“2”結點連線,

第一行第三列是1,因爲左邊的“圖”中,“1”這個結點沒有與“3”結點連線,

依次類推,得出鄰階矩陣

 

 

(2)鄰階表:先用一個數組存儲每個結點,然後其中的每個結點的相鄰結點用鏈表連接起來

太抽象了,例子分析

如下圖:

v1 到 v8 總共8個結點,先用數組存儲起來,圖中紅色方框表示

看左邊的圖,

v1一共有3個相鄰的結點,v2 ,v4, v6,用鏈表連接起來(連接順序無要求)在v1的後面

v2一共有3個相鄰的結點,v3,v5, v4,用鏈表連接起來(連接順序無要求)在v2的後面

依次類推,得出鄰階表

9.2圖的遍歷

廣度優先:一層一層遍歷(類似層次遍歷)

深度優先:一個結點接一個結點訪問,直到不能訪問(類似前序遍歷)

廣度優先(鄰接表存儲)如下圖分析:

首先v0有三個相鄰的結點v4 ,v3 ,v1,所以先訪問v4 ,v3, v1

繼續走,看v4,有三個相鄰的結點v6,v1 ,v0,所以先訪問v6 ,v1(已經訪問過了,不用管), v0(已經訪問過了,不用管)

繼續走,看v3,有兩個相鄰的結點v6,v0,所以先訪問v6 (已經訪問過了,不用管), v0(已經訪問過了,不用管)

繼續走,看v1,有三個相鄰的結點v4,v2 ,v0,所以先訪問v4 (已經訪問過了,不用管),v2, v0(已經訪問過了,不用管)

第一層遍歷完了,繼續第二層

繼續走,看v6,有三個相鄰的結點v3,v4,v7,所以以先訪問v3 (已經訪問過了,不用管), v4(已經訪問過了,不用管),v7

繼續走,看v2,有兩個相鄰的結點v1,v5,所以以先訪問v1 (已經訪問過了,不用管), v5

最後結果:v0, v4 ,v3, v1,v2,v0,v7,v5(其中一種結果)

遍歷完成 

 

深度優先(鄰接表存儲)如下圖分析:

先訪問v0,v4,v6,v7,發現v7後面沒有了,回退一步,

看v6的其他相鄰的結點,所以以先訪問v3,v4(已經訪問過了,不用管),v3後面也沒有了,回退一步,

看v6的其他相鄰的結點,發現全部訪問完了,繼續回退一步,

看v4的其他相鄰的結點,所以以先訪問v0(已經訪問過了,不用管),v1,v6(已經訪問過了,不用管)

v1後面還有,繼續訪問 v2 ,v5,後面沒有了,回退一步,v2其他相鄰的結點已經訪問,繼續回退,v1其他相鄰的結點已經訪問,

繼續回退 ,v4其他相鄰的結點已經訪問,繼續回退 ,v0其他相鄰的結點已經訪問

最後結果:v0, v4 ,v6, v7,v3,v1,v2,v5(其中一種結果)

到此遍歷完成

圖的拓撲排序:

拓撲排序:執行的先後順序,比如,完成某件事,必須要完成前面的事才行

太抽象了,實例分析

如下圖:

0可以開始執行,把兩條線劃掉

接下來,2和3都可以執行,把線劃掉,

接下來執行4(但是4必須等2和3執行完),把線劃掉,

接下來執行3或6,把線劃掉,

接下來執行5或者6

最後執行7

 

 

10.圖的最小生成樹

最小生成樹:各個結點的連線,總長度最小,但是不能成環了

10.1 普里姆算法(prime)

核心思想:找出結點,並作爲一個集合(有的稱藍點集或紅點集,意思一樣的)去處理

如下圖分析:

首先在樹中去任意一個結點A(也可以其他結點),然後找出其他結點與A最近的連線,發現A 到B是最近的,距離100

繼續,把A與B看成一個“整體”,看看這個“整體”與那個結點最近,發現A 到E是最近的,距離200

繼續,把A與B,E看成一個“整體”,看看這個“整體”與那個結點最近,發現A 到F是最近的,距離250

依次類推,得出圖的最小生成樹

10.1 克魯斯卡爾算法

核心思想:找出最短的邊(比較簡單)

下圖分析:

首先找出最短的邊:100,所以連接A B

繼續找出最短的邊:200,所以連接A E,所以連接F D

繼續找出最短的邊:250,所以連接A F

繼續找出最短的邊:300,所以連接C D,不能連接B F導致成環,

依次類推,得出圖的最小生成樹

,

11.算法的複雜度

 

11.1排序

分類:

交換類:冒泡排序,快速排序

插入類:直接插入排序,希爾排序

選擇類:簡單選擇排序,堆排序

歸併排序

基數排序

 

(1)直接插入排序

核心:在一個已知的序列中,進行比較插入

例子分析:57 ,68 ,59 , 52(要求從小到大排序)

先取第一個57,

然後第二個68,68>57,不處理

然後第三個59,59<68,再繼續比較57,發現59>57,這時可以插入

 

(2)希爾排序

核心思想:取一個間隔增量進行分組,然後組內用直接插入排序,然後縮小間隔增量,直到爲1,最後用直接插入排序完成

好處:經過組內分組排序之後,整個序列變得有序,大大提高了排序的速度

例子分析:

如下圖:

先取增量(這個增量任意的,只要不大於n就行)爲5,每隔5個爲一組,57和28,68和96,59和33,52和24,72和19,然後每個組進行單獨的直接插入排序,變成

28 ,68,33,24,19,57,96,59,52,72

再取增量爲3,每隔3個爲一組,28,24,96爲一組,68,19,59爲一組,33,57,52爲一組然後每個組進行單獨的直接插入排序,依次類推

最後增量爲1,然後再進行直接插入排序,完成。

 

(3)簡單選擇排序

核心思想:首先選出最小與第一個交換位置,然後剩餘選出最小與第二個交換位置。。。

(4)堆排序

堆:要滿足完全二叉樹

分類:

小頂堆:父結點比左右子結點小

大頂堆:父結點比左右子結點大

核心思想:從堆頂取出的結點最大(或最小),然後調整堆,再從堆頂取出的結點最大(或最小),從而排序。

非常適合海量數據排名前幾的排序

怎麼構建大頂堆?如下圖分析

比如構建大頂堆

先數列排成完全二叉樹形式

然後非葉子結點(5,3,1,4,這裏有4個非葉子結點)進行比較,

首先5與8調換,然後8與3調換,然後發現下面的3也要與5調換

按照這種方式,依次類推,得出大頂堆

接下來,例子分析

如下圖分析:

假設已經構建好大頂堆,從大頂堆取出80後,需要調整

從最後一個結點取出來放到根結點,然後進行調整,比較左右子樹,直到合適

(5)冒泡排序

核心思想:從最後兩兩交換,得到最小(或最大)的元素放到前面

(6)快速排序

首先選一個基準,任意的,

比如選第一個57爲基準,然後指針最後一個19與基準比較,如果小於基準,交換位置

然後指針跑到第二位68,與基準比較,如果大於基準,交換位置

依次類推,最後基準會跑到中間,然後基準的左邊都是小於基準,右邊都是大於基準的

然後基準的左邊繼續剛剛的排序,直到完成

然後基準的右邊繼續剛剛的排序,直到完成

(7)歸併排序

分析兩個小組合並(其他也一樣):

57和52比較,52小,52複製到新的數組去,然後右邊的指針加1,

然後57和59比較,57小,57複製到新的數組去,然後左邊的指針加1,

然後68和59比較,59小,59複製到新的數組去,然後右邊的指針加1,後面沒有,排序完成

最後:52,57,59,68

(8)基數排序

核心思想:先按個位排序,然後十位排序,最後百位排序(有更多位的,依次類推),最後得出結果

總結:

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