主頁 >  其他 > 第8章 圖

第8章 圖

2020-10-04 21:39:20 其他

第8章 圖

目錄
  • 一、圖的基本概念
  • 二、圖的基本運算
  • 三、圖的基本存盤結構
    • 3.1 鄰接矩陣及其實作
      • 3.1.1 鄰接矩陣存盤結構
      • 3.1.2 建立網路的鄰接矩陣演算法(演算法)
    • 3.2 鄰接表及其實作
      • 3.2.1 鄰接表存盤結構
      • 3.2.2 建立無向圖的鄰接表演算法(演算法)
    • 3.3 鄰接多重表
  • 四、圖的遍歷
    • 4.1 深度優先遍歷(DFS)
    • 4.2 廣度優先遍歷 (BFS)
  • 五、生成樹與最小生成樹 (無向網)
    • 5.1 最小生成樹的定義
    • 5.2 最小生成樹的普里姆(Prim)演算法
    • 5.3 最小生成樹的克魯斯卡爾(Kruskal)演算法
  • 六、最短路徑 (有向網)
    • 6.1 單源最短路徑(Dijkstra演算法)
    • 6.2 所有頂點對的最短路徑 (Floyd演算法)
  • 七、拓撲排序 (AOV網)
  • 八、關鍵路徑 (AOE網)
  • 九、演算法設計題
    • 9.1 求一個頂點的度(真題)(演算法)
    • 9.2 往圖中插入一個頂點(演算法)
    • 9.3 往圖中插入一條邊(演算法)
  • 十、錯題集

一、圖的基本概念

  1. \(G\) 的頂點集:記作 \(V(G)\)
  2. \(G\) 的邊集:記作 \(E(G)\)
  3. 無向圖的邊:頂點 \(v\) 到 頂點 \(u\) 的邊記作 \((u,v)\)
  4. 有向圖的邊:頂點 \(v\) 到 頂點 \(u\) 的邊記作 \(<u,v>\)
  5. 鄰接點:若 \((v,u)\) 是一條無向邊,則稱 \(u\)\(v\) 互為鄰接點
  6. 頂點和邊數的關系:
    1. \(n\) 個頂點的無向圖,其邊數 \(e\) 小于等于 \(n(n-1)/2\)邊數恰好為 \(n(n-1)/2\) 的無向圖稱為無向完全圖
    2. \(n\) 個頂點的有向圖,其邊數 \(e\) 小于等于 \(n(n-1)\)邊數恰好為 \(n(n-1\) 的有向圖稱為有向完全圖
  7. 無向圖頂點的度:頂點相關聯的邊的數目,頂點 \(v\) 的度記為 \(D(v)\)
  8. 有向圖頂點的度:
    1. 入度:以頂點 \(v\) 作為終點的邊的數目,記為 \(ID(v)\)
    2. 出度:以頂點 \(v\) 作為始點的邊的數目,記為 \(OD(v)\)
    3. 注:有向圖頂點的度等于頂點的入度和出度之和
  9. 頂點數 \(n\)、邊數 \(e\) 和度數的關系:\(e=\frac{1}{2}\sum_{i=1}^n{D(v_i)}\)
  10. 有向圖路徑:存在一個頂點序列 \(v,v_1,v_2,\cdots,v_m,u\),且 \((v,v_1),(v_1,v_2),\cdots,(v_m,u)\) 都屬于 \(E(G)\),則該頂點序列為 \(v\)\(u\) 的一條路徑
  11. 無向圖路徑:有向圖路徑:存在一個頂點序列 \(v,v_1,v_2,\cdots,v_m,u\),且 \(<v,v_1>,<v_1,v_2>,\cdots,<v_m,u>\) 都屬于 \(E(G)\),則該頂點序列為 \(v\)\(u\) 的一條路徑
  12. 簡單路徑:一條路徑除了起點 \(v\) 和終點 \(u\) 之外,其余頂點均不相同,該路徑稱之為一條簡單路徑
  13. 簡單回路(簡單環):起點和終點相同\(v=u\))的簡單路徑
  14. 無向圖連通的概念:
    1. 無向圖的連通:頂點 \(v\)\(u\) 之間有路徑,則稱 \(v\)\(u\) 是連通的
    2. 連通圖(無向圖):\(V(G)\) 中任意兩個不同的頂點 \(v\)\(u\) 都連通(即有路徑),則 \(G\) 為連通圖
    3. 連通分量:無向圖 \(G\)極大連通子圖(任何連通圖的連通分量都是其本身,非連通的無向圖有多個連通分量
  15. 有向圖連通的概念:
    1. 強連通圖:\(V(G)\) 中任意兩個不同的頂點 \(v\)\(u\)都存在從 \(v\)\(u\) 和從 \(u\)\(v\) 的路徑
    2. 強連通分量:有向圖的極大強連通子圖(任何強連通圖的唯一強連通分量是其自身,非強連通的有向圖有多個強連通分量
  16. 連通分量和強連通分量注意事項:單個頂點可以屬于一個單獨的連通分量或強連通分量
  17. 權:圖的每條邊上附上相關的數值
  18. 網路(帶權圖):圖的每條邊都賦上一個權

二、圖的基本運算

三、圖的基本存盤結構

  1. 注:對于以下圖的存盤結構,都假定頂點序號從 \(0\) 開始,圖 \(G\) 的頂點集一般形式為 \(V(G)=\{v_0,\cdots,v_i,\cdots,v_{n-1}\}\)

3.1 鄰接矩陣及其實作

  1. 圖的鄰接矩陣表示法:用兩個表格分別存盤資料元素(頂點)的資訊和資料之間的關聯(邊)資訊

    1. 一維陣列(順序表):存盤資料元素的資訊
    2. 二維陣列(鄰接矩陣):存盤資料元素之間的關系
  2. 鄰接矩陣的性質:若 \((v_i,v_j)或<v_i,v_j>\in{E(G)}\)\(A[i,j]=1\);若 \((v_i,v_j)or<v_i,v_j>\notin{E(G)}\)\(A[i,j]=0\)

  3. 無向圖的鄰接矩陣:該鄰接矩陣一定是對稱的,可以采用上(下)三角矩陣進行壓縮存盤,存盤空間為 \(n(n+1)/2\)

  4. 有向圖的鄰接矩陣:該鄰接矩陣不一定是對稱的,存盤空間為 \(n^2\)

  5. 無向圖頂點 \(v_i\) 的度數:\(D(v_i) = \sum_{j=0}^{n-1}A[i,j]=\sum_{j=0}^{n-1}A[j,i]\) (對稱矩陣\(A=A^T\)

  6. 有向圖頂點 \(v_i\) 的度數:

    1. 出度:\(OD(v_i)=\sum_{j=0}^{n-1}A[i,j]\)
    2. 入度:\(ID(v_i) = \sum_{j=0}^{n-1}A[j,i]\)
  7. 圖鄰接矩陣圖:

  8. 網路的鄰接矩陣性質:

\[A[i,j]= \begin{cases} W_{ij} &\qquad \text{當$(v_i,v_j)$或$<v_i,v_j>$$\in$E(G)} \\ 0 &\qquad \text{當$(v_i,v_j)$或$<v_i,v_j>$$\notin$E(G)且i=j} \\ \infin &\qquad \text{當$(v_i,v_j)$或$<v_i,v_j>$$\notin$E(G)且i$\neq$j} \end{cases} \]

  1. 圖網路鄰接矩陣圖:

3.1.1 鄰接矩陣存盤結構

#define FINITY 5000 // 用5000表示無窮大
#define M 20 // 最大頂點數
typedef char vertextype; // 頂點值型別
typedef int edgetype; // 權值型別
typedef struct {
    vertextype vexs[M]; // 頂點資訊域
    edgetype edges[M][M]; // 鄰接矩陣
    int n, e; // 圖中頂點總數和邊數
} Mgraph;

3.1.2 建立網路的鄰接矩陣演算法(演算法)

  1. 演算法步驟:
    1. 打開檔案
    2. 讀入圖中的頂點數和邊數
    3. 讀入圖中的頂點值
    4. 初始化鄰接矩陣
    5. 讀入網路中的邊
    6. 建立無向圖鄰接矩陣
    7. 關閉檔案

3.2 鄰接表及其實作

  1. 鄰接表與鄰接矩陣的區別:
    1. 頂點個數為 \(n\) 的圖,鄰接矩陣的存盤空間為 \(n^2\) ,而使用鄰接表則可節省很多空間
    2. 鄰接矩陣表示法唯一,而鄰接表的表示法不唯一
  2. 鄰接表中的兩個結點:
    1. 表頭結點:存盤頂點的資料域(\(vertex\))和頭指標域(\(firstedge\)
    2. 邊表結點:鄰接點域(\(adjvex\))和鏈域(\(next\)
  3. 鄰接表的隨機訪問任意頂點的構造:讓所有頭結點順序存盤在一個向量中
  4. 圖無向圖鄰接表:
  5. 有向圖
    1. 出邊表(鄰接表):表結點存盤以頂點 \(v\) 為始點射出的一條邊
    2. 入邊表(逆鄰接表):表結點存盤以頂點 \(v\) 為終點射出的一條邊
  6. 圖有向圖的鄰接表:
  7. 鄰接表存盤空間:無向圖(\(n\) 個頂點和 \(e\) 條邊)用鄰接表存盤需要 \(n\) 個頭結點和 \(2e\) 個邊結點
  8. 注:\(e\) 遠小于 \(n(n-1)/2\),鄰接表存盤圖比鄰接矩陣存盤圖節省空間
  9. 無向圖的度(鄰接表):頂點 \(v_i\) 的度為第 \(i\) 個鏈表中結點的個數
  10. 有向圖的度(鄰接表-出邊表):
    1. 出度:第 \(i\) 個鏈表中的結點的個數
    2. 入度:所有鏈表中其鄰接點域的值為 \(i\) 的結點的個數

3.2.1 鄰接表存盤結構

#define M 20 // 預定義圖的最大頂點數
typedef char datatype; // 定點資訊資料域
// 邊表結點型別
typedef struct node {
    int adjvex; // 鄰接點
    struct node *next;
} edgenode;
// 頭結點型別
typedef struct vnode {
    datatype vertex; // 頂點資訊
    edgenode *firstedge; // 鄰接鏈表頭指標
} vertexnode;
// 鄰接表型別
typedef struct {
    vertexnode adjlist[M]; // 存放頭結點的順序表
    int n, e; // 圖的頂點數與邊數
} linkedgraph;

3.2.2 建立無向圖的鄰接表演算法(演算法)

  1. 演算法步驟:
    1. 打開檔案
    2. 讀入頂點數和邊數
    3. 讀入頂點資訊
    4. 邊表置為空
    5. 回圈 e(邊數) 次建立邊表
      1. 輸入無序對 \((i,j)\)
      2. 鄰接點序號為 \(j\)
      3. 將新結點 \(*s\) 插入頂點 \(v_i\) 的邊表頭部
    6. 關閉檔案

3.3 鄰接多重表

  1. 鄰接多重表由兩個表組成:

    1. 表頭結點:\(vertex\) 域存盤頂點的相關資訊;\(firstedge\) 存盤第一條關聯于 \(vertex\) 頂點的邊

    2. 邊表結點:\(mark\) 域標志圖的遍歷演算法中是否被搜索過;\(vex_i\)\(vex_j\) 表示邊的兩個頂點在圖中的位序;\(link_i\)\(link_j\) 表示兩個邊表結點指標,

      1. \(link_i\) 指向關聯于頂點 \(vex_i\)的下一條邊;\(link_j\) 指向關聯于頂點 \(vex_j\) 的下一條邊
    3. 邊表結點的順序如下表所示:

      1. \(mark\) \(vex_i\) \(link_i\) \(vex_j\) \(link_j\)

四、圖的遍歷

4.1 深度優先遍歷(DFS)

  1. 深度優先遍歷步驟:

    1. 選取一個源點 \(v\in{V}\),把 \(v\) 標記為已被訪問
    2. 使用深度優先搜索方法依次搜索 \(v\) 的所有鄰接點 \(w\)
    3. 如果 \(w\) 未被訪問,以 \(w\) 為新的出發點繼續進行深度優先遍歷
    4. 如果從 \(v\) 出發,有路的頂點都被訪問過,則從 \(v\) 的搜索程序結束
    5. 如果圖中還有未被訪問過的頂點(該圖有多個連通分量或者強連通分量),則再任選一個未被訪問的頂點開始新的搜索
  2. 注:深度優先遍歷的順序是不一定的,但是,當采用鄰接表存盤結構并且存盤結構已確定的情況下,遍歷的結果將是確定的

  3. 圖深度優先遍歷:

4.2 廣度優先遍歷 (BFS)

  1. 廣度優先遍歷步驟:
    1. 從圖中某個源點 \(v\) 出發
    2. 訪問頂點 \(v\) 后,盡可能先橫向搜索 \(v\) 的所有鄰接點
    3. 在訪問 \(v\) 的各個鄰接點 \(w_k,\cdots,w_k\) 后,從這些鄰接點出發依次訪問與 \(w_1,\cdots,w_k\) 鄰接的所有未曾訪問過的頂點
    4. 如果 \(G\) 是連通圖,訪問完成;否則另選一個尚未訪問的頂點作為新源點繼續上述搜索程序,知道圖 \(G\) 的所有頂點均被訪問
  2. 注:廣度優先遍歷無向圖的程序中,呼叫 \(bfs(函式:從頂點\,i\,出發廣度優先遍歷圖\,g\,的連通分量)\) 的次數就是該圖連通分量的個數
  3. 圖廣度優先遍歷:

五、生成樹與最小生成樹 (無向網)

  1. 生成樹:對于一個無向的連通圖 \(G\),設 \(G'\) 是它的一個子圖,如果 \(G'\) 中包含了 \(G\) 中所有的頂點,且 \(G'\) 是無回路的連通圖,則稱 \(G'\)\(G\) 的一顆生成樹
  2. 圖生成樹:
  3. 生成森林:如果 \(G\) 是非連通的無向圖,需要若干次從外部呼叫 \(DFS(或BFS)\) 演算法才能完成對 \(G\) 的遍歷,每一次外部呼叫,只能訪問 \(G\) 的一個連通分量,經過該連通分量的頂點和邊構造出一顆生成樹,\(G\) 的各個連通分量的生成樹組成了 \(G\) 的生成森林
  4. 圖生成森林:

5.1 最小生成樹的定義

  1. 生成樹的權:生成樹 \(T\) 的各邊的權值總和,記作 \(W(T)=\sum_{(u,v)\in{E}}w_{uv}\),其中 \(E\) 表示 \(T\) 的邊集,\(w_{uv}\) 表示邊 \((u,v)\) 的權
  2. 最小生成樹的權:總權值 \(W(T)\) 最小的生成樹稱為最小生成樹
  3. 構造最小生成樹的準則:
    1. 必須只使用該網路中的邊來構造最小生成樹
    2. 必須使用且僅使用 \(n-1\) 條邊來連接網路中的 \(n\) 個頂點
    3. 不能使用產生回路的邊

5.2 最小生成樹的普里姆(Prim)演算法

  1. 兩棲邊:假設 \(G=(V,E)\) 是一個連通圖,\(U\) 是頂點集 \(V\) 的一個非空真子集,\((u,v)\) 是滿足 \(u\in{U},v\in{V-U}\) 的邊(稱這個邊為兩棲邊),且 \((u,v)\)所有的兩棲邊中具有最小的權值(此時,稱 \((u,v)\) 為最小兩棲邊)
  2. Prim演算法步驟:
    1. 初始化 \(U=\{u_0\},TREE=\{\}\)
    2. 如果 \(U=V(G)\),則輸出最小生成樹 \(T\),并結束演算法
    3. 在所有兩棲邊中找一條權最小的邊 \((u,v)\)(若候選兩棲邊中的最小邊不止一條,可任選其中的一條),將邊 \((u,v)\) 加入到邊集 \(TREE\) 中,并將頂點 \(v\) 并入集合 \(U\)
    4. 由于新頂點的加入,\(U\) 的狀態發生變化,需要對 \(U\)\(V-U\) 之間的兩棲邊進行調整
    5. 轉步驟 \(2\)
  3. 下圖步驟順序(\(V=\{A,B,C,D,E,F\}\)):
    1. \(U = \{A\}\)\(V-U=\{B,C,D,E,F\}\)\(TREE=\{\}\),兩棲邊 \((A,B),(A,C),(A,D),(A,E),(A,F)\),最小兩棲邊 \((A,B)\)
    2. \(U = \{A,B\}\)\(V-U=\{C,D,E,F\}\)\(TREE=\{(A,B)\}\),兩棲邊 \((B,C),(B,D),(B,F),(A,E)\)\((B,C)\) 比 (\(A,C)\) 小,因此做一個替換),最小兩棲邊 \((B,D)\)
    3. \(U = \{A,B,D\}\)\(V-U=\{C,E,F\}\)\(TREE=\{(A,B),(B,D)\}\),兩棲邊 \((B,C),(B,F),(A,E)\),最小兩棲邊 \((B,F)\)
    4. \(U = \{A,B,D,F\}\)\(V-U=\{C,E\}\)\(TREE=\{(A,B),(B,D),(B,F)\}\),兩棲邊 \((B,C),((F,E)\),最小兩棲邊 \((B,C)\)
    5. \(U = \{A,B,D,F,C\}\)\(V-U=\{E\}\)\(TREE=\{(A,B),(B,D),(B,F),(B,C)\}\),兩棲邊 \((F,E)\),最小兩棲邊 \((F,E)\)
    6. \(U = \{A,B,D,F,C,E\}\)\(V-U=\{\}\)\(TREE=\{(A,B),(B,D),(B,F),(B,C),(F,E)\}\),兩棲邊 \(\{\}\),最小兩棲邊 \(\{\}\)
  4. 圖prim演算法:

5.3 最小生成樹的克魯斯卡爾(Kruskal)演算法

  1. 演算法步驟:
    1. 將圖 \(G\) 看做一個森林,每個頂點為一棵獨立的樹
    2. 將所有的邊加入集合 \(S\),即一開始 \(S = E\)
    3. \(S\) 中拿出一條最短的邊 \((u,v)\),如果 \((u,v)\) 不在同一棵樹內,則連接 \(u,v\) 合并這兩棵樹,同時將 \((u,v)\) 加入生成樹的邊集 \(E'\)
    4. 重復步驟 \(3\) 直到所有點屬于同一棵樹,邊集 \(E'\) 就是一棵最小生成樹
  2. 圖kruskal演算法:

六、最短路徑 (有向網)

6.1 單源最短路徑(Dijkstra演算法)

  1. 距離向量 \(d\):表示源點可以途徑 \(S\) 中的頂點到達 \(V-S\) 中頂點的距離

  2. 路徑向量 \(p\):保存路徑上第 \(i\) 個頂點的前驅頂點序號(沒有的話,默認為 \(-1\)

  3. 演算法步驟:

    1. 找到與源點 \(v\) 最近的頂點,并將該頂點并入最終集合 \(S\)

    2. 根據找到的最近的頂點更新從源點 \(v\) 出發到集合 \(V-S\) 上可達頂點的最短路徑

    3. 重復以上操作

  4. 圖Dijkstra演算法:

  5. 上圖求單源最短路徑步驟:

    1. 初始化:從源點 \(v1\) 出發得到矩陣,到達個點的最小路徑是 \(D_{12}=10\)\(D_{0}=\left[\begin{array}{cccc} v1 &v2 &v3 &v4 &v5\\ 0 &10 &\infty &30 &100\\ \end{array}\right ]\)
    2. 第一次:\(v2\)出發,\(v1\)\(v2\) 保持不變,迭代剩下點 \((v3,v4,v5)\) 的距離后,剩余點的最短路徑是 \(v4\)\(D_{1}=\left[\begin{array}{cccc} v1 &v2 &v3 &v4 &v5\\ 0 &10 &60(10+50) &30 &100\\ \end{array}\right ]\)
    3. 第二次:\(v4\) 出發,\(v1,v2,v4\) 保持不變,優化剩余點 \((v3,v5)\) 的最短距離,剩余點的最短路徑是 \(v3\)\(D_{2}=\left[\begin{array}{cccc} v1 &v2 &v3 &v4 &v5\\ 0 &10 &50(20+30) &30 &90(30+60)\\ \end{array}\right ]\)
    4. 第三次:\(v3\)出發,\(v1,v2,v4,v3\) 保持不變,優化剩余點 $v5 \(的最短路徑,\)D_{3}=\left[\begin{array}{cccc} v1 &v2 &v3 &v4 &v5\ 0 &10 &50 &30 &60(20+30+10)\ \end{array}\right ]$
  6. 源點 \(v1\)\(Dijkstra演算法\) 的最短路徑(如下表):

    1. 中間頂點 終點 路徑長度
      2 10
      4 3 50
      4 30
      4;3 5 60
  7. 距離向量 \(d\) 和路徑向量 \(p\)

  8. 圖Dijkstra演算法的輔助陣列:

6.2 所有頂點對的最短路徑 (Floyd演算法)

  1. 演算法步驟:略

七、拓撲排序 (AOV網)

  1. \(AOV網\) 邊的作用:表示活動間(一個頂點表示一個活動)的優先關系
  2. 注:(真題)拓撲排序可以判斷圖中有沒有回路(深度遍歷優先演算法也可以)
  3. 演算法步驟
    1. 在有向圖中找一個沒有前驅(入度為 \(0\))的頂點并輸出
    2. 在圖中洗掉該頂點以及所有從該頂點發出的有向邊
    3. 反復執行步驟 \(1\)\(2\),知道所有頂點均被輸出,或者 \(AOV\) 網中再也沒有入度為 \(0\) 的頂點存在為止
  4. 圖拓撲排序:

八、關鍵路徑 (AOE網)

  1. \(AOE網\) 邊的作用:表示活動(一個頂點表示一個活動)持續的時間
  2. 事件可能的最早開始時間 \(v_e(i)\):對于某一事件 \(v_i\),它可能的最早發生時間 \(v_e(i)\) 是從源點到頂點 \(v_i\) 的最大路徑長度
    1. \[\begin{cases}v_e(0) = 0\\v_e(i) = max\{v_e(j)+活動<v_j,v_i>持續的時間\}(1\leq{i}\leq{n-1)}\end{cases} \]

  3. 事件允許的最晚發生時間 \(v_l(i)\):對于某一事件 \(v_i\),它允許的最晚發生時間是在保證按時完成整個工程的前提下,該事件最晚必須發生的時間
    1. \[\begin{cases}v_l(n-1)=v_e(n-1)\\v_l=min\{v_l(j)-len(<v_i,v_j>)\}(0\leq{i}\leq{n-2})\end{cases} \]

  4. 最早可能開始時間 \(e(i)\) 和 允許的最晚發生時間 \(l(i)\)
    1. \[\begin{cases}e(k)=v_e(i)\\l(k)=v_l(j)-len(<v_i,v_j>)\end{cases} \]

    2. 注:\(k\) 為某條邊,即 \(<v_i,v_j>\)\(a_k\)
  5. 關鍵活動:\(e(i) = l(i)\) 的頂點為關鍵活動
  6. 演算法步驟:
    1. 求出各個事件的 \(v_e\)\(v_l\) 值后
      1. 計算原則:\(v_e\) 的值越大越好;\(v_l\) 的值越小越好
    2. 求出活動的最早可能開始時間 \(e(i)\) 和 允許的最晚發生時間 \(l(i)\)
    3. 其中滿足 \(e(i)=l(i)\) 的活動就是 \(AOE網\) 中的關鍵活動
  7. 圖關鍵路徑圖:
拓撲序列(v0、v1、v2、v4、v3、v6、v7、v5、v8、v9)每個事件的最早開始時間:
ve(0)=0
ve(1)= 8,ve(2)=6,ve(4)=7;
ve(3)=max{ve(1)+len(a3),ve(2)+len(a4)}=16;
ve(6)=max{ve(2)+len(a5),ve(4)+len(a6)}=16;
ve(7)=max{ve(6)+len(a11),ve(4)+len(a7)}=20;
ve(5)= ve(3)+len(a8)=20;
ve(8)=max{ve(3)+len(a9),ve(6)+len(a10),ve(7)+len(a12)}=35;
ve(9)=max{ve(5)+len(a13),ve(8)+len(a14)}=45;

每個事件允許的最晚發生時間如下:
vl(9)=ve(9)=45
vl(8)=vl(9)-len(<v8,v9>)=45-10=35
vl(5)=vl(9)-len(<v5,v9>)=45-14=31
vl(7)=vl(8)-len(<v7,v8>)=35-6=29
vl(6)=min{vl(7)-len(<v6,v7>),vl(8)-len(<v6,v8>)}=min{27,27}=27
vl(3)=min{vl(5)-len(<v3,v5>),vl(8)-len(<v3,v8>)}=min{27,16}=16
vl(4)=min{vl(6)-len(<v4,v6>),vl(7)-len(<v4,v7>)}=min{18,16}=16
vl(2)=min{vl(3)-len(<v2,v3>),vl(6)-len(<v2,v6>)}=min{6,18}=6
vl(1)=vl(3)-len(<v1,v3>)=13
vl(0)=min{vl(1)-8,vl(2)-6,vl(4)-7}=min{5,0,9}=0
  1. 圖關鍵路徑

  2. 圖AOE網計算:

九、演算法設計題

9.1 求一個頂點的度(真題)(演算法)

無向圖采用鄰接表作為存盤結構,求一個頂點的度

  1. 演算法步驟:
    1. 獲取頂點的第一個結點 \(firstedge\)
    2. 如果第一個結點存在,回圈獲取后續結點
#define M 20 // 預定義圖的最大頂點數
typedef char datatype; // 頂點資訊資料域
// 邊表結點型別
typedef struct node {
    int adjvex; // 鄰接點
    struct node *next;
} edgenode;
// 頭結點型別
typedef struct vnode {
    datatype vertex; // 頂點資訊
    edgenode *firstedge; // 鄰接鏈表頭指標
} vertexnode;
// 鄰接表型別
typedef struct {
    vertexnode adjlist[M]; // 存放頭結點的順序表
    int n, e; // 圖的頂點數與邊數
} adjgraph;

int d(adjgraph g, int i) {
    int k = 0;
    edgenode *p;
    p = g.adjlist[i].firstedge;

    while (p) {
        k++;
        p = p->next;
    }
    return k;
}

9.2 往圖中插入一個頂點(演算法)

無向圖采用鄰接表作為存盤結構,往圖中插入一個頂點

  1. 演算法步驟:
    1. 查找并判斷待插入的結點是否存在
    2. 判斷鄰接表是否已滿
    3. 上述判斷都通過,則插入新頂點
#define M 20 // 預定義圖的最大頂點數
typedef char datatype; // 頂點資訊資料域
// 邊表結點型別
typedef struct node {
    int adjvex; // 鄰接點
    struct node *next;
} edgenode;
// 頭結點型別
typedef struct vnode {
    datatype vertex; // 頂點資訊
    edgenode *firstedge; // 鄰接鏈表頭指標
} vertexnode;
// 鄰接表型別
typedef struct {
    vertexnode adjlist[M]; // 存放頭結點的順序表
    int n, e; // 圖的頂點數與邊數
} adjgraph;

void insertvex(adjgraph *g, datatype x) {
    int i = 0, flag = 0;
    // 查找待插入的結點是否存在
    while (!flag && i < g->n) {
        if (g->adjlist[i].vertex == x) flag = 1;
        i++;
    }
    // 判斷結點是否存在
    if (flag) {
        printf("結點已存在!");
        getch();
        exit(0);
    }
    // 判斷鄰接表是否已滿
    if (g->n > M) {
        printf("鄰接表已滿!");
        exit(0);
    }
    // 插入結點
    g->adjlist[g->n].vertex = x;
    g->adjlist[g->n].firstedge = NULL;
    g->n++;
}

9.3 往圖中插入一條邊(演算法)

無向圖采用鄰接表作為存盤結構,往圖中插入一條邊(本題采用前插法)

  1. 演算法步驟:
    1. 判斷邊是否已經存在
    2. 在頂點 \(i\) 的鏈表中插入鄰接點 \(j\);在頂點 \(j\) 的鏈表中插入鄰接點 \(i\)(使用前插法)
#define M 20 // 預定義圖的最大頂點數
typedef char datatype; // 頂點資訊資料域
// 邊表結點型別
typedef struct node {
    int adjvex; // 鄰接點
    struct node *next;
} edgenode;
// 頭結點型別
typedef struct vnode {
    datatype vertex; // 頂點資訊
    edgenode *firstedge; // 鄰接鏈表頭指標
} vertexnode;
// 鄰接表型別
typedef struct {
    vertexnode adjlist[M]; // 存放頭結點的順序表
    int n, e; // 圖的頂點數與邊數
} adjgraph;

void insertedge(adjgraph *g, int i, int j) {
    edgenode *p, *s;
    int flag = 0;

    // 判斷邊是否存在
    if (i < g->n && j < g->n) {
        p = g->adjlist[i].firstedge;
        while (!flag && p) {
            if (p->adjvex == j) flag = 1;
            p = p->next;
        }
        if (flag) {
            printf("邊已存在!");
            getch();
            exit(0);
        }
        // 插入無向邊(i,j)
        s = (edgenode *) malloc(sizeof(edgenode));
        s->adjvex = j; // 鄰接點序號為 j
        s->next = g->adjlist[i].firstedge;
        g->adjlist[i].firstedge = s; // 將新結點*s 插入頂點 vi 的邊表頭部
        s = (edgenode *) malloc(sizeof(edgenode));
        s->adjvex = i; // 鄰接點序號為 i
        s->next = g->adjlist[j].firstedge;
        g->adjlist[j].firstedge = s; // 將新結點*s 插入頂點 vj 的邊表頭部
    } else
        printf("插入邊不合法!");
}

十、錯題集

  1. (真題)判斷一個有向圖是否存在回路可以利用拓撲排序法和深度優先遍歷演算法
  2. 在一個帶權連通圖 \(G\) 中,權值最小的邊一定包含在 \(G\) 的最小生成樹中

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/155596.html

標籤:其他

上一篇:第7章 二叉樹

下一篇:第9章 檢索

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more