数据结构--图(Graph)详解(一)
數據結構–圖(Graph)詳解(一)
文章目錄
- 數據結構--圖(Graph)詳解(一)
- 一、圖的基本概念
- 1.圖的分類
- 2.弧頭和弧尾
- 3.入度和出度
- 4.(V1,V2) 和 < V1,V2 > 的區別
- 5.集合 VR 的含義
- 6.路徑和回路
- 7.權和網的含義
- 8.子圖
- 9.完全圖
- 10.稀疏圖和稠密圖
- 11.連通圖
- 12.強連通圖
- 13.生成樹
- 14.生成森林
- 15.重連通圖及重連通分量
- 16.AOE網
- 17.關鍵路徑
- 二、圖的存儲結構
- 1.圖的順序存儲法
- 2.圖的鄰接表存儲法
- 3.圖的十字鏈表存儲法
- 4.圖的鄰接多重表存儲法
一、圖的基本概念
我們知道,數據之間的關系有 3 種,分別是 “一對一”、“一對多” 和 “多對多”,前兩種關系的數據可分別用線性表和樹結構存儲,接下來學習存儲具有"多對多"邏輯關系數據的結構——圖存儲結構。
1.圖的分類
圖 1 所示為存儲 V1、V2、V3、V4 的圖結構,從圖中可以清楚的看出數據之間具有的"多對多"關系。例如,V1 與 V4 和 V2 建立著聯系,V4 與 V1 和 V3 建立著聯系,以此類推。
與鏈表不同,圖中存儲的各個數據元素被稱為頂點(而不是節點)。拿圖 1 來說,該圖中含有 4 個頂點,分別為頂點 V1、V2、V3 和 V4。
圖存儲結構中,習慣上用 Vi 表示圖中的頂點,且所有頂點構成的集合通常用 V 表示,如圖 1 中頂點的集合為 V={V1,V2,V3,V4}。
注意,圖 1 中的圖僅是圖存儲結構的其中一種,數據之間 “多對多” 的關系還可能用如圖 2 所示的圖結構表示:
可以看到,各個頂點之間的關系并不是"雙向"的。比如,V4 只與 V1 存在聯系(從 V4 可直接找到 V1),而與 V3 沒有直接聯系;同樣,V3 只與 V4 存在聯系(從 V3 可直接找到 V4),而與 V1 沒有直接聯系,以此類推。
因此,圖存儲結構可細分兩種表現類型,分別為無向圖(圖 1)和有向圖(圖 2)。
2.弧頭和弧尾
有向圖中,無箭頭一端的頂點通常被稱為"初始點"或"弧尾",箭頭直線的頂點被稱為"終端點"或"弧頭"。
3.入度和出度
- 對于有向圖中的一個頂點 V 來說,箭頭指向 V 的弧的數量為 V 的入度(InDegree,記為 ID(V));
- 箭頭遠離 V 的弧的數量為 V 的出度(OutDegree,記為OD(V))
拿圖 2 中的頂點 V1來說,該頂點的入度為 1,出度為 2(該頂點的度為 3)。
4.(V1,V2) 和 < V1,V2 > 的區別
- 無向圖中描述兩頂點(V1 和 V2)之間的關系可以用 (V1,V2) 來表示,而有向圖中描述從 V1 到 V2 的"單向"關系用<V1,V2> 來表示。
- 由于圖存儲結構中頂點之間的關系是用線來表示的,因此 (V1,V2) 還可以用來表示無向圖中連接 V1 和 V2 的線,又稱為邊;
- 同樣,<V1,V2> 也可用來表示有向圖中從 V1 到 V2 帶方向的線,又稱為弧。
5.集合 VR 的含義
- 并且,圖中習慣用 VR 表示圖中所有頂點之間關系的集合。
例如,圖 1 中無向圖的集合 VR={(v1,v2),(v1,v4),(v1,v3),(v3,v4)},圖 2 中有向圖的集合 VR={<v1,v2>,<v1,v3>,<v3,v4>,<v4,v1>}。
6.路徑和回路
- 無論是無向圖還是有向圖,從一個頂點到另一頂點途徑的所有頂點組成的序列(包含這兩個頂點),稱為一條路徑。
- 如果路徑中第一個頂點和最后一個頂點相同,則此路徑稱為"回路"(或"環")。
- 并且,若路徑中各頂點都不重復,此路徑又被稱為"簡單路徑";
- 同樣,若回路中的頂點互不重復,此回路被稱為"簡單回路"(或簡單環)。
拿圖 1 來說,從 V1 存在一條路徑還可以回到 V1,此路徑為 {V1,V3,V4,V1},這是一個回路(環),而且還是一個簡單回路(簡單環)。
- 在有向圖中,每條路徑或回路都是有方向的。
7.權和網的含義
- 在某些實際場景中,圖中的每條邊(或弧)會賦予一個實數來表示一定的含義,這種與邊(或弧)相匹配的實數被稱為"權",而帶權的圖通常稱為網。
如圖 3 所示,就是一個網結構:
8.子圖
- 指的是由圖中一部分頂點和邊構成的圖,稱為原圖的子圖。
根據不同的特征,圖又可分為完全圖,連通圖、稀疏圖和稠密圖:
9.完全圖
- 若圖中各個頂點都與除自身外的其他頂點有關系,這樣的無向圖稱為完全圖(如圖 4a))。
- 同時,滿足此條件的有向圖則稱為有向完全圖(圖 4b))。
具有 n 個頂點的完全圖,圖中邊的數量為 n(n-1)/2;而對于具有 n 個頂點的有向完全圖,圖中弧的數量為 n(n-1)。
10.稀疏圖和稠密圖
- 這兩種圖是相對存在的,即如果圖中具有很少的邊(或弧),此圖就稱為"稀疏圖";反之,則稱此圖為"稠密圖"。
稀疏和稠密的判斷條件是:e < nlogn,其中 e 表示圖中邊(或弧)的數量,n 表示圖中頂點的數量。如果式子成立,則為稀疏圖;反之為稠密圖。
11.連通圖
- 前面講過,圖中從一個頂點到達另一頂點,若存在至少一條路徑,則稱這兩個頂點是連通著的。
例如圖 1 中,雖然 V1 和 V3 沒有直接關聯,但從 V1 到 V3 存在兩條路徑,分別是 V1-V2-V3 和 V1-V4-V3,因此稱 V1 和 V3 之間是連通的。
- 無向圖中,如果任意兩個頂點之間都能夠連通,則稱此無向圖為連通圖。
例如,圖 2 中的無向圖就是一個連通圖,因為此圖中任意兩頂點之間都是連通的。
- 若無向圖不是連通圖,但圖中存儲某個子圖符合連通圖的性質,則稱該子圖為連通分量。
- 前面講過,由圖中部分頂點和邊構成的圖為該圖的一個子圖,但這里的子圖指的是圖中"最大"的連通子圖(也稱"極大連通子圖")。
如圖 3 所示,雖然圖 3a) 中的無向圖不是連通圖,但可以將其分解為 3 個"最大子圖"(圖 3b)),它們都滿足連通圖的性質,因此都是連通分量。
提示,圖 3a) 中的無向圖只能分解為 3 部分各自連通的"最大子圖"。
需要注意的是,連通分量的提出是以"整個無向圖不是連通圖"為前提的,因為如果無向圖是連通圖,則其無法分解出多個最大連通子圖,因為圖中所有的頂點之間都是連通的。
12.強連通圖
- 有向圖中,若任意兩個頂點 Vi 和 Vj,滿足從 Vi 到 Vj 以及從 Vj 到 Vi都連通,也就是都含有至少一條通路,則稱此有向圖為強連通圖。
如圖 4 所示就是一個強連通圖。
- 與此同時,若有向圖本身不是強連通圖,但其包含的最大連通子圖具有強連通圖的性質,則稱該子圖為強連通分量。
如圖 5 所示,整個有向圖雖不是強連通圖,但其含有兩個強連通分量。
13.生成樹
對連通圖進行遍歷,過程中所經過的邊和頂點的組合可看做是一棵普通樹,通常稱為生成樹。
如圖 1 所示,圖 1a) 是一張連通圖,圖 1b) 是其對應的 2 種生成樹。
連通圖中,由于任意兩頂點之間可能含有多條通路,遍歷連通圖的方式有多種,往往一張連通圖可能有多種不同的生成樹與之對應。
- 連通圖中的生成樹必須滿足以下 2 個條件:
- 包含連通圖中所有的頂點;
- 任意兩頂點之間有且僅有一條通路;
因此,連通圖的生成樹具有這樣的特征,即生成樹中邊的數量 = 頂點數 - 1。
14.生成森林
生成樹是對應連通圖來說,而生成森林是對應非連通圖來說的。
我們知道,非連通圖可分解為多個連通分量,而每個連通分量又各自對應多個生成樹(至少是 1 棵),因此與整個非連通圖相對應的,是由多棵生成樹組成的生成森林。
如圖 2 所示,這是一張非連通圖,可分解為 3 個連通分量,其中各個連通分量對應的生成樹如圖 3 所示:
15.重連通圖及重連通分量
- 在無向圖中,如果任意兩個頂點之間含有不止一條通路,這個圖就被稱為重連通圖。
- 在重連通圖中,在刪除某個頂點及該頂點相關的邊后,圖中各頂點之間的連通性也不會被破壞。
- 在一個無向圖中,如果刪除某個頂點及其相關聯的邊后,原來的圖被分割為兩個及以上的連通分量,則稱該頂點為無向圖中的一個關節點(或者“割點”)。
圖 1 是連通圖但不是重連通圖,圖中有4個關節點,分別是:A、B、D 和 G。比如刪除頂點 B 及相關聯的邊后,原圖就變為:
可以看到,圖被分割為各自獨立的 3 部分,頂點集合分別為:{A、C、F、L、M、J}、{G、H、I、K} 和 {D、E}。
-
了解了什么是關節點后,重連通圖其實就是沒有關節點的連通圖。
-
在重連通圖中,只刪除一個頂點及其相關聯的邊,肯定不會破壞其連通性。
-
如果一味地做刪除頂點的操作,直到刪除 K 個頂點及其關聯的邊后,圖的連通性才遭到破壞,則稱此重連通圖的連通度為 K 。
-
重連通圖的實際應用
如今的通信網絡對人們的生活有著重要的影響,如果將通信網絡比做一個巨大的連通圖的話,它的連通度 K
值越高,證明其穩定性越好,即使某一個站點發生故障無法工作也不會影響整個系統的正常工作。
同樣,小到城市之間,大到國家之間的航空網也可以看作是一個連通圖,但如果此圖建設成為重連通圖,當某條航線因為天氣等因素關閉時,飛機仍可以從別的航線到達目的地。
在戰爭中,有“兵馬未動,糧草先行”的說法,可見后勤補給對軍隊的重要性。如果補給線是一個重連通圖,就不用過于擔心補給線被破壞的問題,因為即使破壞一條,還有其它的,只要連通度足夠大。
判斷重連通圖的方法
了解了什么是重連通圖之后,如何編寫程序直接判斷一個圖是否是重連通圖呢?
對于任意一個連通圖來說,都可以通過深度優先搜索算法獲得一棵深度優先生成樹,例如,圖 1 通過深度優先搜索獲得的深度優先生成樹為:
虛線表示遍歷生成樹時未用到的邊,簡稱“回邊”。也就是圖中有,但是遍歷時沒有用到,生成樹中用虛線表示出來。
- 在深度優先生成樹中,圖中的關節點有兩種特性:
- 首先判斷整棵樹的樹根結點,如果樹根有兩條或者兩條以上的子樹,則該頂點肯定是關節點。因為一旦樹根丟失,生成樹就會變成森林。
- 然后判斷生成樹中的每個非葉子結點,以該結點為根結點的每棵子樹中如果有結點的回邊與此非葉子結點的祖宗結點相關聯,那么此非葉子結點就不是關節點;反之,就是關節點。
注意:必須是和該非葉子結點的祖宗結點(不包括結點本身)相關聯,才說明此結點不是關節點。
- 所以,判斷一個圖是否是重連通圖,也可以轉變為:判斷圖中是否有關節點,如果沒有關節點,證明此圖為重連通圖;反之則不是。
- 拿圖 3 的生成樹來說,利用兩個特性判斷每個頂點是否為關節點:
- 首先,判斷樹根結點 A ,由于有兩個孩子,也就是有兩棵子樹,所以 A 是關節點。
- 然后判斷樹中所有的非葉子結點,也就是: L 、 M 、 B 、 D 、 H 、 K 、 G ;
- L 結點為根結點的子樹中 B 結點有回邊直接關聯 A ,所以, L 不是關節點;
- 在以 M 結點為樹根的子樹中,J 結點和 B 結點都有回邊關聯 M 結點的祖宗結點,所以,M 不是關節點;
- 以 B 結點為根結點的 3 棵子樹中,只有一棵子樹(只包含結點 C )與 B 結點的祖宗結點 A 有關聯,其他兩棵子樹沒有,所以結點 B 是關節點;
- 以 D 結點為根結點的子樹中只有結點 E,且沒有回邊與祖宗結點關聯,所以,D 是關節點;
- 以 H 結點為根結點的子樹中, G 結點與 B 結點關聯,所以, H 結點不是關節點;
- K 結點和 H 結點相同,由于 G 結點與祖宗結點 B 關聯,所以 K 結點不是關節點;
- 以 G 結點為根結點的子樹中只有一個結點 I,沒有回邊,所以結點 G 是關節點;
綜上所述,圖 3 中的關節點有 4 個,分別是: A 、 B 、 D 、 G 。
16.AOE網
AOE 網是在 AOV 網的基礎上,其中每一個邊都具有各自的權值,是一個有向無環網。其中權值表示活動持續的時間。
如圖 1 所示就是一個 AOE 網,例如 a1=6 表示完成 a1 活動完成需要 6 天;
AOE 網中每個頂點表示在它之前的活動已經完成,可以開始后邊的活動,
例如 V5 表示 a4 和 a5 活動已經完成,a7 和 a8 可以開始。
使用 AOE 網可以幫助解決這樣的問題:如果將 AOE 網看做整個項目,那么完成整個項目至少需要多少時間?
解決這個問題的關鍵在于從 AOE 網中找到一條從起始點到結束點長度最長的路徑,這樣就能保證所有的活動在結束之前都能完成。
起始點是入度為 0 的點,稱為“源點”;結束點是出度為 0 的點,稱為“匯點”。這條最長的路徑,被稱為”關鍵路徑“。
17.關鍵路徑
- 為了求出一個給定 AOE 網的關鍵路徑,需要知道以下 4 個統計數據:
- 對于 AOE 網中的頂點有兩個時間:最早發生時間(用 Ve(j) 表示)和最晚發生時間(用 Vl(j) 表示);
- 對于邊來說,也有兩個時間:最早開始時間(用 e(i) 表示)和最晚開始時間( l(i) 表示)。
- Ve(j): 對于 AOE 網中的任意一個頂點來說,從源點到該點的最長路徑代表著該頂點的最早發生時間,通常用 Ve(j) 表示。
例如,圖 1 中從 V1 到 V5 有兩條路徑,V1 作為源點開始后,a1 和 a2 同時開始活動,但由于 a1 和 a2活動的時間長度不同,最終 V1-V3-V5 的這條路徑率先完成。
但是并不是說 V5 之后的活動就可以開始,而是需要等待 V1-V2-V5
這條路徑也完成之后才能開始。所以對于 V5 來講,Ve(5) = 7。
- Vl(j):表示在不推遲整個工期的前提下,事件 Vk 允許的最晚發生時間。
例如,圖 1 中,在得知整個工期完成的時間是 18 天的前提下,V7 最晚要在第 16 天的時候開始,因為 a10 活動至少需要 2天時間才能完成,如果在 V7 事件在推遲,就會拖延整個工期。
所以,對于 V7 來說,它的 Vl(7)=16。
- e(i):表示活動 ai 的最早開始時間,如果活動 ai 是由弧 <Vk,Vj> 表示的,那么活動 ai 的最早開始的時間就等于時間 Vk 的最早發生時間,也就是說:e[i] = ve[k]。
e(i)很好理解,拿圖 1 中 a4 來說,如果 a4 想要開始活動,那么首先前提就是 V2 事件開始。所以 e[4]=ve[2]。
-
l(i):表示活動 ai 的最晚開始時間,如果活動 ai 是由弧 <Vk,Vj> 表示,ai 的最晚開始時間的設定要保證 Vj的最晚發生時間不拖后。所以,l[i]=Vl[j]-len<Vk,Vj>。
-
在得知以上四種統計數據后,就可以直接求得 AOE網中關鍵路徑上的所有的關鍵活動,方法是:對于所有的邊來說,如果它的最早開始時間等于最晚開始時間,稱這條邊所代表的活動為關鍵活動。由關鍵活動構成的路徑為關鍵路徑。
-
求關鍵路徑的具體過程
對圖 1 中的 AOE 圖求關鍵路徑,首先完成 Ve(j)、Vl(j)、e(i)、l(i) 4 種統計信息的準備工作。
- Ve(j),求出從源點到各頂點的最長路徑長度為(長度最大的):
-
Vl(j),求出各頂點的最晚發生時間(從后往前推,多種情況下選擇最小的):
-
e(i),求出各邊中ai活動的最早開始時間:
-
l(i),求各邊中ai活動的最晚開始時間(多種情況下,選擇最小的):
通過對比 l(i) 和 e(i) ,其中 a1 、 a4 、 a7 、 a8 、 a10 、 a11 的值都各自相同,所以,在圖 1 中的 AOE 網中有兩條關鍵路徑:
-
關鍵路徑的代碼實現
二、圖的存儲結構
1.圖的順序存儲法
2.圖的鄰接表存儲法
3.圖的十字鏈表存儲法
4.圖的鄰接多重表存儲法
詳情請點擊:https://blog.csdn.net/wolfGuiDao/article/details/107587464
總結
以上是生活随笔為你收集整理的数据结构--图(Graph)详解(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库支持锁的种类
- 下一篇: 数据结构--图(Graph)详解(二)