數(shù)據(jù)結(jié)構(gòu) - 圖
目錄:
- 基本概念
- 無向圖
- 有向圖
- 儲存結(jié)構(gòu)
- 鄰接矩陣
- 鄰接表
- 十字鏈表(有向圖)
- 鄰接多重表(無向圖)
- 圖的遍歷
- 深度優(yōu)先搜索
- 廣度優(yōu)先搜索
- 最小生成樹
- 普里姆算法(Prim)
- 克魯斯卡爾算法(Kruskal)
- 最后
基本概念
圖是由結(jié)點和他們之間連線的集合
無向圖
無向圖.png
無向圖解析.png
- 連通圖:當(dāng)任意一個結(jié)點都能直接或間接到其他全部結(jié)點的時候,就稱為連通圖
- 完全圖:邊數(shù) = 頂點數(shù) *( 頂點數(shù) - 1 ) / 2
- 生成樹 : 邊數(shù) = 頂點數(shù) - 1
有向圖
有向圖.png
有向圖解析.png
- 上圖,V1的出度是2,入度是1
- 權(quán)值:一條連線所代表的值
- 當(dāng)兩個結(jié)點互相指向,那么就等于一條直線
儲存結(jié)構(gòu)
儲存結(jié)構(gòu).png
鄰接矩陣
使用數(shù)組的形式來儲存數(shù)據(jù)
- 在有向圖中,當(dāng)一個頂點能夠指向另外一個頂點,則矩陣中的值為1,否則為0
有向圖鄰接矩陣.png
- 在無向圖中,邊是相當(dāng)于兩個頂點相互指向
無向圖鄰接矩陣.png
- 代碼中鄰接矩陣表示 :
int[][] martix ;
鄰接表
使用頂點以及其弧的指向來儲存數(shù)據(jù)
鄰接表存儲.png
- 頂點索引:頂點的唯一標(biāo)識
- 出弧鏈表頭指針: 頂點指向其他頂點的連接
- 頂點數(shù)據(jù):頂點儲存的數(shù)據(jù)
</br> - 在代碼中,鄰接表的結(jié)構(gòu)表示
鄰接表代碼構(gòu)造.png
十字鏈表(有向圖)
使用頂點以及其弧的指向來儲存數(shù)據(jù)
十字鏈表數(shù)據(jù)儲存.png
這里以V1頂點為例說明:
- 頂點索引:0
- 頂點數(shù)據(jù):1(假定的)
- 以該頂點為弧尾的弧的結(jié)點指針: V1 -> V3, V1 -> V2, V1 -> V4
- 以該頂點為弧頭的弧的結(jié)點指針: V4 -> V1
這里以V1 -> V4 的弧為例說明: - 弧尾頂點索引:0
- 弧頭頂點索引:3
- 弧尾相同的下一條弧的指針: V1 -> V2 , V1 -> V3
- 弧頭相同的下一條弧的指針: V3 -> V4
- 弧的數(shù)據(jù):V1V4(假定的)
</br> - 代碼實現(xiàn)的結(jié)構(gòu):
十字鏈表代碼構(gòu)造.png
鄰接多重表(無向圖)
使用頂點以及邊的連接指向來儲存數(shù)據(jù)
鄰接多重表數(shù)據(jù)儲存.png
頂點表示很清晰簡單
這里以V1 ->V4邊為例說明:
- A點索引 : 0(V1)
- B點索引:3 (V4)
- 與A點相連接的下一條邊的指針: V1 -> V2 或者 V1 -> V3, 取決于哪一條更早建立連接
- 與B點相連接的下一條邊的指針 : V3 -> V4
</br> - 代碼實現(xiàn)的結(jié)構(gòu):
鄰接多重表代碼構(gòu)造.png
圖的遍歷
實例-圖.png
深度優(yōu)先搜索
對于上圖
從A頂點開始進(jìn)行深度優(yōu)先搜索的順序為:
A - B - C - E - F - D - G - H
丟棄了 F - B , H -D 這兩條邊,形成了一棵樹
- 規(guī)則:
順著一個頂點不斷向下搜索,當(dāng)搜索到的頂點與前面搜索過的頂點形成環(huán)的時候就停止
有點類似樹的前序遍歷
廣度優(yōu)先搜索
對于上圖
從A頂點開始進(jìn)行廣度優(yōu)先搜索的順序為:
A - B - D - C - F - G - H - E
丟棄了E - F 和 G - H 這兩條邊,形成了一棵樹
- 規(guī)則:
按層來不斷進(jìn)行搜索
最小生成樹
當(dāng)遍歷的時候涉及邊的權(quán)值問題,就要使用最小生成樹來解決
最小生成樹前.png
如圖:上面的數(shù)值是邊的權(quán)值,可以理解為修路的成本,每個頂點可以理解為一個城市,如何最節(jié)約成本完成城市之間的連通就需要使用最小生成樹。
最小生成樹后:
最小生成樹后.png
普里姆算法(Prim)
普里姆算法(Prim).png
過程:
- 選定一個點A,放入點集合
- 關(guān)于A的所有的邊放入 待選邊集合
- 從待選邊集合選取權(quán)值最小的邊 A - F (1),放入邊集合
- 邊集合中提取出未在點集合的點F,放入點集合
- 刷新待選邊集合,列出所有A和F有關(guān)的邊
- 選出權(quán)值最小且不會與當(dāng)前已選邊形成閉環(huán)的邊,然后放入邊集合
- 以此類推,得出所有邊,既是最小生成樹
Prim算法后:
普里姆算法(Prim)后.png
克魯斯卡爾算法(Kruskal)
克魯斯卡爾算法(Kruskal).png
過程:
- 列出所有邊的集合
- 依次選取權(quán)值最小的邊,同時將涉及的點加入點集合
- 選取的邊不能與已選邊構(gòu)成閉合
- 當(dāng)點集合中出現(xiàn)了所有點以后,需要讓所有點能連通,形成生成樹(邊 = 點 - 1)
Kruskal算法后:
克魯斯卡爾算法(Kruskal)后.png
最后
對數(shù)據(jù)結(jié)構(gòu)的基本認(rèn)識和理解到這里就結(jié)束了
關(guān)于圖的代碼實現(xiàn),在有了隊列,棧,線性表的實踐過后,代碼的轉(zhuǎn)換肯定是沒問題的
重點在于對上面所說知識點的深入理解和邏輯轉(zhuǎn)換
再次感謝慕課網(wǎng)的James老師
PS:
后面我會寫一寫,從零開始的Android組件化開發(fā)的記錄博文