文章知識點來至於大話數據結構里邊章節知識, 這篇主要介紹圖在計算機中存儲形式, 以及在某些算法領域中對圖的相關應用。本篇涉及到的知識點也比較多在圖的遍歷中介紹了深度優先遍歷、廣度優先遍歷;在最小生成樹節介紹了普利姆算法和克魯斯卡爾算法;最短路徑中介紹了迪傑斯特拉算法、佛洛依德算法;本篇后邊還介紹了拓撲排序以及關鍵路徑等知識點。 本篇對算法進行了描述和實現, 在實現代碼的同時添加了流程圖。相關代碼源碼請查看文章最后。本篇最后的算法描述和流程圖以及代碼實現是重點,如果對本篇感興趣一定要通過該部分來鞏固數據機構。
圖
1 圖的定義
圖是由頂點的有窮非空集合和頂點之間邊的集合組成,通過表示為G(V,E),其中,G標示一個圖,V是圖G中頂點的集合,E是圖G中邊的集合。
無邊圖:若頂點Vi到Vj之間的邊沒有方向,則稱這條邊為無項邊(Edge),用序偶對(Vi,Vj)標示。
對於下圖無向圖G1來說,G1=(V1, {E1}),其中頂點集合V1={A,B,C,D};邊集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}:
有向圖:若從頂點Vi到Vj的邊是有方向的,則成這條邊為有向邊,也稱為弧(Arc)。用有序對(Vi,Vj)標示,Vi稱為弧尾,Vj稱為弧頭。如果任意兩條邊之間都是有向的,則稱該圖為有向圖。
有向圖G2中,G2=(V2,{E2}),頂點集合(A,B,C,D),弧集合E2={<A,D>,{B,A},<C,A>,<B,C>}.
權(Weight):有些圖的邊和弧有相關的數,這個數叫做權(Weight)。這些帶權的圖通常稱為網(Network)。
圖的定義和術語總結:
2 圖的抽象數據類型
基本操作抽象:
1、 圖的存儲結構
鄰接矩陣:圖的鄰接矩陣存儲方式是用兩個數組來標示圖。一個一位數組存儲圖頂點的信息,一個二維數組(稱為鄰接矩陣)存儲圖中邊或者弧的信息。
設圖G有n個頂點,則鄰接矩陣是一個n*n的方陣,定義為:
實例如下,左圖是一個無向圖。右圖是鄰接矩陣表示:
鄰接矩陣代碼存儲結構:
無向網圖的創建代碼,時間復雜度為O{n + n2 + e}。
鄰接表
用數組和鏈表結合的存儲方式來標示圖的方法稱為鄰接表。
鄰接表處理思路
鄰接表存儲結構
鄰接表存儲代碼結構
鄰接表創建代碼
十字鏈表(OrthogonalList)
十字鏈表把鄰接表與逆鄰接表結合起來,解決了出度和入度的問題。
3 圖的遍歷
定義:從圖中某個頂點出發訪遍圖中其余頂點,且使每個頂點僅被訪問依次,這一過程叫做圖的遍歷.
遍歷方法: 深度優先遍歷和廣度優先遍歷
深度優先遍歷
從圖中某個頂點出發v出發,訪問此頂點,然后從v的未被訪問的鄰接點出發深度優先便利圖,知道圖中所有和v有相同路徑的頂點都被訪問。
深度優先遍歷采用鄰接矩陣遍歷:
深度優先遍歷采用鄰接表遍歷:
廣度優先遍歷
廣度優先遍歷(Breadth_First_Search)又稱為廣度優先搜索,簡稱BFS。
鄰接矩陣廣度算法實現:
鄰接表廣度優先算法實現:
4 最小生成樹
定義:我們把構造連通圖的最小代價生成樹稱為最小生成樹。
最小生成樹實現算法:普利姆算法和克魯斯卡爾算法
魯斯卡爾算法
定義:
數據初始化:我們將下圖的鄰接矩陣通過程序轉化為右圖的邊集數組,並且對他們按權值從小到大排序。
算法流程圖:
算法代碼實現:
5 最短路徑
定義:對於網圖來說,最短路徑是指兩個頂點之間經過的邊上權值之和最少的路徑,並且我們稱路徑上的第一個頂點式源點,最后一個頂點是終點。
兩種計算最短路徑算法:迪傑斯特拉(Djikstra)算法和佛洛伊德算法
迪傑斯特拉(Djikstra)算法
算法描述:迪傑斯特拉算法並不是一下子求出開始節點到尾節點的最短路徑,而是一步步求出它們之間頂點的最短路徑,過程中都是基於已經求出的最短路徑的基礎上,求得更遠頂點的最短路徑,最終得到你要的結果。
流程圖:
迪傑斯特拉代碼實現:
5 拓撲排序
定義
在一個表示工程的有向圖中,用頂點表示活動,用弧表示活動之間的優先關系,這樣的有向圖為頂點表示活動的網,我們稱為AOV網(Activity On Vertex)。
設G=(V,E)是一個具有n個頂點的有向圖,V中的頂點序列V1,V2…..,Vn滿足若從頂點Vi到頂點Vj有一條路徑,則在頂點序列中Vi必在Vj頂點之前。則我們稱這樣的頂點序列為拓撲序列。
所謂拓撲序列,其實就是對一個有向圖構造拓撲序列的過程。
數據結構
頂點結構:
參考拓撲圖:
算法實現:
6 關鍵路徑
定義
在一個表示工程的帶權有向圖中,用頂點表示事件,用有向圖表示活動,用邊上的權值表示活動的持續事件,這種這種有向圖的邊表示活動圖,我們稱之為AOE網(Activity On Edge Network)。
我們把路徑上各
個活動所持續的時間之和稱為路徑的長度,從原點到匯點具有最大長度的路徑叫做關鍵路徑,在關鍵路徑上的活動叫關鍵活動。
7 迪傑斯特拉算法求最短路徑(C#版算法實現):

public class DjikstraAlgorithm { public const int INFINITY = 65535; public static void CaculateFinalWay(int[][] matrix, int maxVex, out int[] prevMatrix, out int[] weightTable) { var minWeightKey = 0; var finals = new bool[maxVex]; prevMatrix = new int[maxVex]; weightTable = new int[maxVex]; for (var i = 0; i < maxVex; i++) { finals[i] = false; prevMatrix[i] = 0; weightTable[i] = matrix[0][i]; } weightTable[0] = 0; finals[0] = true; for (var v = 1; v < maxVex; v++) { var minWeightValue = INFINITY; for (var w = 0; w < maxVex; w++) { if (!finals[w] && weightTable[w] < minWeightValue) { minWeightKey = w; minWeightValue = weightTable[w]; } } finals[minWeightKey] = true; for (var w = 0; w < maxVex; w++) { if (!finals[w] && minWeightValue + matrix[minWeightKey][w] < weightTable[w]) { weightTable[w] = minWeightValue + matrix[minWeightKey][w]; prevMatrix[w] = minWeightKey; } } } } }
8 迪傑斯特拉算法單元測試

1 private static void TestDjikstraAlgorithm() 2 { 3 const int max = DjikstraAlgorithm.INFINITY; 4 var matrix = new int[][] 5 { 6 new int[] { 0, 1, 5, max, max, max, max, max, max}, 7 8 new int[] { 1, 0, 3, 7, 5, max, max, max, max}, 9 10 new int[] { 5, 3, 0, max, 1, 7, max, max, max}, 11 12 new int[] {max, 7, max, 0, 2, max, 3, max, max}, 13 14 new int[] {max, 5, 1, 2, 0, 3, 6, 9, max}, 15 16 new int[] {max, max, 7, max, 3, 0, max, 5, max}, 17 18 new int[] {max, max, max, 3, 6, max, 0, 2, 7}, 19 20 new int[] {max, max, max,max, 9, 5, 2, 0, 4}, 21 22 new int[] {max, max, max,max, max, max, 7, 4, 0} 23 }; 24 25 int[] preMatrix; 26 int[] weightTable; 27 DjikstraAlgorithm.CaculateFinalWay(matrix, 9, out preMatrix, out weightTable); 28 //驗證V8的權值 29 Assert.IsEqual(weightTable[8], 16); 30 //驗證V0到V8的最短路徑 31 Assert.IsEqual("V0->V1->V2->V4->V3->V6->V7->V8", GetFinalWay(preMatrix)); 32 } 33 34 private static string GetFinalWay(int[] preMatrix) 35 { 36 var index = 8; 37 var finalWay = "V" + index; 38 39 while (index != 0) 40 { 41 finalWay = string.Format("V{0}->", preMatrix[index]) + finalWay; 42 index = preMatrix[index]; 43 } 44 45 return finalWay; 46 }
最后附上源代碼下載地址:
http://download.csdn.net/detail/w_wanglei/5689883