大話數據結構-圖


文章知識點來至於大話數據結構里邊章節知識, 這篇主要介紹圖在計算機中存儲形式, 以及在某些算法領域中對圖的相關應用。本篇涉及到的知識點也比較多在圖的遍歷中介紹了深度優先遍歷、廣度優先遍歷;在最小生成樹節介紹了普利姆算法和克魯斯卡爾算法;最短路徑中介紹了迪傑斯特拉算法、佛洛依德算法;本篇后邊還介紹了拓撲排序以及關鍵路徑等知識點。 本篇對算法進行了描述和實現, 在實現代碼的同時添加了流程圖。相關代碼源碼請查看文章最后。本篇最后的算法描述和流程圖以及代碼實現是重點,如果對本篇感興趣一定要通過該部分來鞏固數據機構。

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM