【數據結構複習總結】—— 圖


一、相關名詞解釋

1. 完全圖

  • 無向圖中任意兩個頂點之間都存在邊,稱爲無向完全圖。 n個頂點,n(n-1)/2 條邊
  • 有向圖中任意兩個頂點之間都存在相反的兩條弧,稱爲有向完全圖。 n個頂點, n(n-1)條邊

2. 連通圖/強連通圖

  • 無向圖 中頂點v到頂點w有路徑存在,稱v和w連通。若任意兩個頂點都連通,連通圖
    若一個圖有n個頂點,並且邊數小於n-1,則此圖必是非連通圖
    若一個圖有n個頂點,並且邊數大於n-1,則此圖必有迴路

  • 有向圖 中頂點v到頂點w和頂點w到頂點v之間都有路徑,稱v和w 強連通 。若任意兩個頂點都連通,強連通圖

3. 連通分量/極大連通子圖

  • 無向圖中極大連通子圖稱爲連通分量;
  • 有向圖中極大連通子圖稱爲強連通分量;

極小連通子圖指該連通子圖既保持圖的連通且包含的邊數最少;

4. 生成樹 (對於連通圖而言)

連通圖的生成樹是 包含全部頂點的一個極小連通子圖(即包含全部頂點且邊數最少)
若砍去生成樹的一條邊,則會變成非連通圖
若加上一條邊,則會形成一個迴路

5. 頂點的入度和出度

  • 無向圖 的的全部頂點的度之和等於邊數的2倍
  • 有向圖 的全部頂點的入度之和與出度之和相等,且與邊數相等

6. 簡單路徑

序列中的頂點和路徑不重複出現的路徑。

7. 迴路

路徑中第一個頂點和最後一個頂點相同的路徑

二、圖的存儲

鄰接矩陣法:(稠密圖)

圖的順序存儲結構

一維數組存儲頂點集,二維數組存儲邊集

無向圖的鄰接矩陣第i行(列)非零元素的個數表示該頂點的度
有向圖的鄰接矩陣第i行(列)非零元素的個數表示該頂點的出度(入度)

無向圖的鄰接矩陣是對稱的

鄰接表法:(稀疏圖)

圖的鏈式存儲結構

一個單鏈表表示該頂點的邊表;
各個單鏈表的頭指針和頂點採用順序存儲連接起來表示頂點表

在這裏插入圖片描述

鄰接表可以方便的找出一頂點的所有鄰邊,但確定兩結點之間是否有邊效率低下
在有向圖中,求一個給定結點的出度只需計算鄰接表中結點的個數,但求入度需要遍歷全部頂點的鄰接表

  • 假設有n個頂點,e條邊的有向圖用鄰接表表示,則刪除與某個頂點v相關的所有邊的時間複雜度爲:O(n+e)

    首先刪除下標爲v的頂點表結點的單鏈表,邊數最多n-1,時間複雜度O(n);
    再掃描所有邊表結點,刪除所有的頂點v的入邊,時間複雜度O(e);

十字鏈表

有向圖的另一種鏈式存儲結構。

鄰接多重表

無向圖的鏈式存儲結構。

三、圖的遍歷

廣度優先遍歷BFS(類似於層次遍歷)

基本思想 :利用 隊列 實現。

  • 首先訪問起始頂點 V 並將其入隊
  • V出隊,並遍歷V的所有鄰接點 w1,w2,….,wn並依次入隊
  • w1出隊,並遍歷 w1 的全部鄰接點(不包括已經被訪問的點)
  • w2出隊,並遍歷w2的全部鄰接點(不包括已經被訪問的點)
  • … 以此類推
	void BFS(Graph G, int v){
	    visit(v); //訪問初始結點
	    visited[v] = TRUE; //初始結點置已訪問標識
	    EnQueue(Q,v); //頂點v入隊
	    while(!isEmpty(Q)){
	        DeQueue(Q,v); //頂點v出隊
	        for(w = FirstNeighbor(G,v); w>=0; w = NextNeighbor(G,v,w)){ //循環遍歷v所有鄰接點
	            if(!visited[w]){
	                visit(w); //訪問頂點w
	                visited[w] = TRUE;
	                EnQueue(Q, w);
	            }
	        }
	    } //while
	}
	void BFSTraverse(Graph G){
	    for(i = 0; i<G.vexnum; i++)
	        visited[i] = FALSE;
	    InitQueue(Q); //初始化隊列
	    for(i = 0; i<G.vexnum;i++) //防止一次遍歷無法遍歷到全部結點(非連通圖)
	        if(!visited[i]) //若未被訪問
	            BFS(G,i);
}     

深度優先遍歷DFS(類似於先序遍歷)

基本思想:利用 遞歸/棧 實現。當不能繼續向下訪問時,依次回退到最近的被訪問結點

  • 首先訪問頂點V,並將其標記爲已訪問
  • 然後訪問與頂點V的其中一個未被訪問的鄰接點W,並將其標記爲已訪問
  • 再訪問W的其中一個未被訪問的鄰接點,並將其標記爲已訪問
  • 依次類推… 當一個頂點所有的鄰接頂點都被訪問過時,則依次退回最近被訪問過的頂點
	void DFS(Graph G, int v){
	    visit(v);
	    visited[v] = TRUE;
	    for (w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)){
	        if(!visited[v])
	            DFS(G,w); //遞歸
	    }
	}
	void DFSTraverse(Graph G, int v){
	    for(int i = 0 ; i<G.vexnum; i++)
	        visited[v] = FALSE;
	    for(int i = 0; i<G.vexnum; i++)
	        if(!visited[v])
	            DFS(G,i);
}
}

四、圖的應用

1. 最小生成樹

Prim算法

每次選取相對最小的邊並且互相連通。需保證無環

kruskal算法

每次選取最小的邊,無須保證此過程是否連通。需保證無環

2. 最短路徑

Dijkstra算法

該算法可以求得某一頂點到其餘各頂點的最短路徑。

算法思想:

  • 設有兩個頂點集合 S 和 T,其中集合 S 中存放的是圖中已找到最短路徑的頂點,集合 T 中存放 的是圖中的剩餘頂點。
  • 初始狀態時,集合 S 中只包含源點 V0,然後不斷從集合 T 中選取到頂點 V0 路徑最短的頂點 Vu 並加入集合 S 中,之後的路徑可通過該結點
  • 集合 S 每加入一個新的頂點 Vu,都要修改 V0 到集合 T 中各個頂點的最短路徑的長度值
  • 不斷重 復這個過程,直至集合T中的頂點全部併入到 S 中爲止。

在這裏插入圖片描述

Floyd算法

每次都試圖在路徑上添加新的中間結點
在這裏插入圖片描述

3. 拓撲排序

什麼圖可以進行拓撲排序?
有向無環圖

基本思想 :每次去除一個入度爲0的結點和該與頂結點相連的邊

在這裏插入圖片描述

若圖中存在一條A——>B的路徑,則在拓撲排序中表示B事件在A事件的後面

4. 關鍵路徑

具有最大路徑長度的路徑稱爲關鍵路徑

只提高一條關鍵路徑上的關鍵活動速度並不能縮短整個工程的工期,只有加快所有關鍵路徑上的關鍵活動才能縮短工期



👉 👉 👉 個人博客 小牛肉的個人博客,歡迎來訪~👈 👈 👈

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章