1. 程式人生 > 實用技巧 >資料結構:七 圖

資料結構:七 圖

1. 圖的定義

定義

  • 圖(Graph)是由頂點的有窮非空集合和頂點之間邊的集合組成,通常表示為:G(V,E)

  • G 表示一個圖,V 是圖 G 中頂點的集合,E 是圖 G 中邊的集合

  • 線性表中我們把資料元素叫元素,樹中將資料元素叫結點,在圖中資料元素,我們則稱之為頂點(Vertex)

  • 在圖結構中,不允許沒有頂點。在定義中,若 V 是頂點的集合,則強調了頂點集合 V 有窮非空

    • 線性表中可以沒有資料元素,稱為空表
    • 樹中可以沒有結點,叫做空樹
  • 圖中,任意兩個頂點之間都可能有關係,頂點之間的邏輯關係用邊來表示,邊集可以是空的

    • 線性表中,相鄰的資料元素之間具有線性關係
    • 樹結構中,相鄰兩層的結點具有層次關係

各種圖定義

  • 無向邊:若頂點 vi 到 vj 之間的邊沒有方向,則稱這條邊為無向邊(Edge),用無序偶對(vi,vj)來表示

  • 有向邊:若從頂點 vi 到 vj 的邊有方向,則稱這條邊為有向邊,也稱為弧(Arc)

    • 用有序偶 <vi,vj> 來表示,vi 稱為弧尾(Tail),vj 稱為弧頭(Head)

  • 簡單圖:在圖中,若不存在頂點到其自身的邊,且同一條邊不重複出現

  • 無向完全圖:在無向圖中,如果任意兩個頂點之間都存在邊

  • 有向完全圖:在有向圖中,如果任意兩個頂點之間都存在方向互為相反的兩條弧

  • 有很少條邊或弧的圖稱為稀疏圖,反之稱為稠密圖

  • 權(Weight):與圖的邊或弧相關的數

    • 這些權可以表示從一個頂點到另一個頂點的距離或耗費
    • 這種帶權的圖通常稱為網(Network)

圖的頂點與邊間關係

  • 對於無向圖 G=(V,{E}),如果邊(v,v')屬於 E,則稱頂點 v 和 v' 互為鄰接點(Adjacent),即 v 和 v' 相鄰接
  • 邊(v,v')依附(incident)於頂點 v 和 v',或者說(v,v')與頂點 v 和 v' 相關聯
  • 頂點 v 的度(Degree)是和 v 相關聯的邊的數目,記作 TD(v)
  • 路徑的長度是路徑上的邊或弧的數目
  • 第一個頂點到最後一個頂點相同的路徑稱為迴路或環(Cycle)
  • 序列中頂點不重複出現的路徑稱為簡單路徑
  • 除了第一個頂點和最後一個頂點之外,其餘頂點不重複出現的迴路,稱為簡單迴路或簡單環

連通圖相關術語

  • 在無向圖 G 中,如果從頂點 v 到頂點 v' 有路徑,則稱 v 和 v' 是連通的。

  • 如果對於圖中任意兩個頂點 vi vj 屬於 E ,vi 和 vj 都是連通的,則稱 G 是連通圖(Connected Graph)

  • 無向圖中的極大連通子圖稱為連通分量

    • 要是子圖
    • 子圖是連通的
    • 連通子圖含有極大頂點數
    • 具有極大頂點數的連通子圖包含依附於這些頂點的所有邊
  • 在有向圖 G 中,如果對於每一對 vi vj 屬於 V,vi 不等於 vj,從 vi 到 vj 和從 vj 到 vi 都存在路徑,則稱 G 是強連通圖

  • 有向圖中的極大強連通子圖稱做有向圖的強連通分量

  • 連通圖的生成樹定義

    • 一個連通圖的生成樹是一個極小的連通子圖,它含有圖中全部的 n 個頂點,但只有足以構成一棵樹的 n-1 條邊
    • 如果一個有向圖恰有一個頂點的入度為 0,其餘頂點的入度為 1,則是一棵有向樹
    • 一個有向樹的生成森林由若干棵有向樹組成,含有圖中全部頂點,但只有足以構成若干棵不相交的有向樹的弧

2. 圖的抽象資料型別

ADT 圖(Graph)

Data
    頂點的有窮非空集合和邊的集合

Operation
    CreateGraph(*G,V,VR):按照頂點集V和邊弧集VR的定義構造圖G
    DestroyGraph(*G):圖G存在則銷燬
    LocateVex(G,u):若圖G中存在頂點u,則返回圖中位置
    GetVex(G,v):返回圖中頂點v的值
    PutVex(G,v,value):將圖G中頂點v賦值給value
    FirstAdjVex(G,*v):返回頂點v的一個鄰接頂點,若頂點在G中無鄰接頂點則返回空
    NextAdjVex(G,v,*w):返回頂點v相對於頂點w的下一個鄰接頂點,若w是v的最後一個鄰接點則返回空
    InsertVex(*G,v):在圖G中增加新頂點v
    DeleteVex(*G,v):刪除圖G中頂點v及其相關的弧
    InsertArc(*G,v,w):在圖G中新增弧<v,w>,若G是無向圖,還需要新增對稱弧<w,v>
    DeleteArc(*G,v,w):在圖G中刪除弧<v,w>,若G是無向圖,則需要刪除對稱弧<w,v>
    DFSTraverse(G):對圖G中進行深度優先遍歷,在遍歷過程對每個頂點呼叫
    HFSTraverse(G):對圖G中進行廣度優先遍歷,在遍歷過程對每個頂點呼叫
endADT

3. 圖的儲存結構

鄰接矩陣

  • 圖的鄰接矩陣(Adjacency Matrix)儲存方式是用兩個陣列來表示圖

    • 一個一維陣列儲存圖中頂點資訊
    • 一個二位陣列(稱為鄰接矩陣)儲存圖中的邊或弧的資訊
  • 對稱矩陣:n 階矩陣的元滿足 aij = aji(0 <= i, j <= n)

鄰接表

  • 陣列與連結串列相結合的儲存方法稱為鄰接表(Adjacency List)

    • 圖中頂點用一個一維陣列儲存,當然,頂點也可以用單鏈表來儲存,不過陣列可以較容易地讀取頂點資訊,更加方便
    • 另外,對於頂點陣列中,每個資料元素還需要儲存指向第一個鄰接點的指標,以便於查詢該頂點的邊資訊
    • 圖中每個頂點 vi 的所有鄰接點構成一個線性表,由於鄰接點的個數不定,所以用單鏈表儲存,無向圖稱為頂點 vi 的邊表,有向圖則稱為頂點 vi 作為弧尾的出邊表
  • 無向圖的鄰接表結構

    • 頂點表的各個結點由 data 和 firstedge 兩個域表示

      • data 是資料域,儲存頂點的資訊,
      • firstedge 是指標域,指向邊表的第一個結點,即此頂點的第一個鄰接點
    • 邊表結點由 adjvex 和 next 兩個域組成

      • adjvex 是鄰接點域,儲存某頂點的鄰接點在頂點表中的下標
      • next 則儲存指向邊表中下一個結點的指標

  • 有向圖的逆鄰接表

    • 對每個頂點 vi 都建立一個連結為 vi 為弧頭的表
    • 對帶權值得網圖,可在邊表結點定義中再增加一個 weight 的資料域,儲存權值資訊即可

十字連結串列

  • 重新定義頂點表結點結構

    • firstin 表示入邊表頭指標,指向該頂點的入邊表中第一個結點
    • firstout 表示出邊表頭指標,指向該頂點的出邊表中的第一個結點
  • 重新定義邊表結點結構

    • tailvex 是指弧起點在頂點表的下標
    • headvex 是指弧終點在頂點表中的下標
    • headlink 是指入邊表指標域,指向終點相同的下一條邊
    • taillink 是指邊表指標域,指向起點相同的下一條邊
    • 如果是網,還可以增加一個 weight 域來儲存權值

鄰接多重表

  • 重新定義邊表結點結構

    • ivex 和 jvex 是與某條邊依附的兩個頂點在頂點表中下標
    • ilink 指向依附頂點 ivex 的下一條邊
    • jlink 指向依附頂點 jvex 的下一條邊

邊集陣列

  • 邊集陣列是由兩個一維陣列構成

    • 一個是儲存頂點的資訊
    • 另一個是儲存邊的資訊,這個邊陣列每個資料元素由一條邊的起點下標(begin),終點下標(end)和權(weight)組成
  • 定義的邊陣列結構

    • begin 是儲存起點下標,end 是儲存終點下標,weight 是儲存權值

4. 圖的遍歷

從圖中某一頂點出發訪遍圖中其餘頂點,且使每一個頂點僅被訪問一次,這過程叫圖的遍歷

深度優先遍歷(Depth First Search,DFS)

  • 對於連通圖

    • 從圖中某個頂點 v 出發,訪問此頂點,然後從 v 的未被訪問的鄰接點出發深度優先遍歷圖,直至圖中所有和 v 有路徑相通的頂點都被訪問到
  • 對於非連通圖

    • 只需要對它的連通分量分別進行深度優先遍歷,即在先前一個頂點進行一次深度優先遍歷後,若圖中尚有頂點未被訪問,則另選圖中一個未曾被訪問的頂點作起始點,重複上述過程,直至圖中所有頂點都被訪問到為止
  • 圖的深度優先遍歷類似樹的前序遍歷

  • 深度遍歷更適合目標明確,以找到目標為主要目的

廣度優先遍歷(Breadth First Search,BFS)

  • 圖的廣度優先遍歷就類似於樹的層序遍歷
  • 廣度優先更適合在不斷擴大遍歷範圍時找到相對最優解

5. 最小生成樹

定義

  • 構建連通網的最小代價生成樹

普利姆(Prim)演算法

  • 以某頂點為起點,逐步找各頂點上最小權值的邊來構建最小生成樹

克魯斯卡爾(Kruskal)演算法

6. 最短路徑

定義

  • 非網圖

    • 由於非網圖它沒有邊上的權值,所謂的最短路徑,其實就是指兩頂點之間經過的邊數最少的路徑
  • 網圖

    • 對於網圖來說,最短路徑是指兩頂點之間經過的邊上權值之和最少的路徑,並且我們稱路徑上的第一個頂點是源點,最後一個頂點是終點

迪傑斯特拉(Dijkstra)演算法

弗洛伊德(Floyd)演算法

7. 拓撲排序

拓撲排序介紹

  • AOV 網(Activity On Vertex Network)

    • 在一個表示工程的有向圖中,用頂點表示活動,用弧表示活動之間的優先關係,這樣的有向圖為頂點表示活動的網,我們稱為 AOV 網
  • 拓撲序列

    • 設 G=(V, E) 是一個具有 n 個頂點的有向圖,V 中的頂點序列 v1,v2,······,vn,滿足若從頂點 vi 到 vj 有一條路徑,則在頂點序列中頂點 vi 必在頂點 vj 之前。則我們稱這樣的頂點序列為一個拓撲序列
  • 拓撲排序

    • 對一個有向圖構造拓撲序列的過程

    • 構造時會有兩個結果

      • 如果此網的全部頂點都被輸出,則說明它是不存在環(迴路)的 AOV 網
      • 如果輸出頂點數少了,哪怕是少了一個,也說明這個網存在環(迴路),不是 AOV 網

拓撲排序演算法

  • 基本思路

    • 從 AOV 網中選擇一個入度為 0 的頂點輸出,然後刪除此頂點,並刪除以此頂點為尾的弧,繼續重複此步驟,直到輸出全部頂點或者 AOV 網中不存在入度 0 的頂點為止

8. 關鍵路徑

定義

  • AOE 網

    • 在一個表示工程的帶權有向圖中,用頂點表示事件,用有向邊表示活動,用邊上的權值表示活動的持續時間,這種有向圖的邊表示活動的網,我們稱之為 AOE 網(Activity On Edge Network)
    • 沒有入邊的頂點稱為始點或源點
    • 沒有出邊的頂點稱為終點或匯點
    • 由於一個工程,總有一個開始一個結束,所以正常情況下,AOE 網只有一個源點一個匯點
  • 路徑長度:路徑上各個活動所持續的時間之和

  • 關鍵路徑:從源點到匯點具有最大長度的路徑

  • 關鍵活動:在關鍵路徑上的活動

關鍵路徑演算法原理

  • 找到所有活動的最早開始時間和最晚開始時間,並且比較它們,如果相等就意味著此活動是關鍵活動,活動間的路徑為關鍵路徑;如果不等,則就不是

  • 引數定義

    • 事件的最早發生時間 etv(earliest time of vertex)

      • 即頂點 vk 的最早發生時間
    • 事件的最晚發生時間 ltv(latest time of vertex)

      • 即頂點 vk 的最晚發生時間,也就是每個頂點對應的事件最晚需要開始的時間,超出此時間將會延誤整個工期
    • 活動的最早開工時間 ete(earliest time of edge)

      • 即弧 ak 的最早發生時間
    • 活動的最晚開工時間 lte(latest time of edge)

      • 即弧 ak 的最晚發生時間,也就是不推遲工期的最晚開工時間

關鍵路徑演算法