【圖的遍歷】廣度優先遍歷(DFS)、深度優先遍歷(BFS)及其應用


無向圖滿足約束條件的路徑

•【目的】:掌握深度優先遍歷算法在求解圖路徑搜索問題的應用

  【內容】:編寫一個程序,設計相關算法,從無向圖G中找出滿足如下條件的所有路徑:
  (1)給定起點u和終點v。
  (2)給定一組必經點,即輸出的路徑必須包含這些點。
  (3)給定一組必避點,即輸出的路徑必須不能包含這些點。

  【來源】:《數據結構教程(第五版)》李春葆著,圖實驗11。

代碼:

  1 #include<stdio.h>
  2 #include<malloc.h>
  3 #define MAXV 20
  4 typedef struct ANode
  5 {
  6     int adjvex;
  7     struct ANode *nextarc;
  8 } ArcNode;
  9 
 10 typedef struct
 11 {
 12     ArcNode *adjlist[MAXV];
 13     int n1, e1;
 14 } AdjGraph;
 15 
 16 int visited[MAXV];
 17 int v1[MAXV], v2[MAXV], n, m;  // v1為必過點集合, v2為必避點集合;n為必過點的個數, m為必避點個數
 18 int count = 0; //路徑個數
 19 
 20 void CreateAdj(AdjGraph *&G, int A[MAXV][MAXV], int n1, int e1)
 21 {
 22     int i, j;
 23     ArcNode *p;
 24     G = (AdjGraph*)malloc(sizeof(AdjGraph));
 25     for (i = 0; i < n1; ++i)
 26         G->adjlist[i] = NULL;
 27     for (i = 0; i < n1; ++i)
 28         for (j = n1; j >= 0; --j)
 29             if (A[i][j] == 1)
 30         {
 31             p = (ArcNode*)malloc(sizeof(ArcNode));
 32             p->adjvex = j;
 33             p->nextarc = G->adjlist[i];
 34             G->adjlist[i] = p;
 35         }
 36     G->n1 = n1;
 37     G->e1 = e1;
 38 }
 39 
 40 bool comp(int path[MAXV], int d)
 41 {
 42     int flag1 = 0, f1, flag2 = 0, f2, j;
 43     for (int i = 0; i < n; ++i)
 44     {
 45         f1 = 1;
 46         for (j = 0; j <= d; ++j)
 47             if (path[j] == v1[i])
 48             {
 49                 f1 = 0;
 50                 break;
 51             }
 52         flag1 += f1;
 53     }   
 54         
 55     for (int i = 0; i < m; ++i)
 56     {
 57         f2 = 0;
 58         for (j = 0; j <= d; ++j)
 59             if (path[j] == v2[i])
 60             {
 61                 f2 = 1;
 62                 break;
 63             }    
 64         flag2 += f2;    
 65     }    
 66     
 67     if (flag1 == 0 && flag2 == 0)
 68         return true;
 69     else
 70         return false;
 71 }
 72 
 73 void findpath(AdjGraph *G, int u, int v, int d, int path[MAXV])
 74 {
 75     int i;
 76     ArcNode *p;
 77     visited[u] = 1;
 78     ++d; path[d] = u;
 79     if (u == v && comp(path, d))
 80     {
 81         printf("路徑%d:", ++count);
 82         printf("%d", path[0]);
 83         for (i = 1; i <= d; ++i)
 84             printf("->%d ", path[i]);
 85         printf("\n");
 86     }
 87     p = G->adjlist[u];
 88     while (p != NULL)
 89     {
 90         if (visited[p->adjvex] == 0)
 91             findpath(G, p->adjvex, v, d, path);
 92             p = p->nextarc;
 93     }
 94     visited[u] = 0;
 95 }
 96 
 97 int main()
 98 {
 99     AdjGraph *G;
100     int u, v; // u為起點,v為終點
101     int path[MAXV];
102     int A[MAXV][MAXV] = {
103     {0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
104     {1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 },
105     {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
106     {1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
107     {1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
108     {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
109     {0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
110     {0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0 },
111     {0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0 },
112     {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0 },
113     {0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0 },
114     {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0 },
115     {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1 },
116     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1 },
117     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 } };
118     CreateAdj(G, A, 15, 21);
119     printf("輸入起點和終點:");
120     scanf("%d %d", &u, &v);
121     printf("輸入必過點個數: ");
122     scanf("%d", &n);
123     printf("輸入必過點集合:");
124     for (int i = 0; i < n; ++i)
125         scanf("%d", &v1[i]);
126     printf("輸入必避點個數: ");
127     scanf("%d", &m);
128     printf("輸入必過點集合:");
129     for (int i = 0; i < m; ++i)
130         scanf("%d", &v2[i]);
131         printf("\n\n所有探寶路徑如下:\n");
132     findpath(G, u, v, -1, path);
133     return 0;
134 }

運行結果:

 

 

 

 

用圖搜索方法求解迷宮問題

•【目的】:深入掌握圖遍歷算法在求解實際問題中的運用

 【內容】:編寫一個程序,完成如下功能:
  (1)  建立迷宮對應的鄰接表
  (2)  采用深度優先遍歷算法輸出從入口(1, 1)到出口(M,N)的所有迷宮路徑

 【來源】:《數據結構教程(第五版)》李春葆著,圖實驗14。

代碼:

  1 #include<stdio.h>
  2 #include<malloc.h>
  3 #define MAXV  20
  4 #define N 4
  5 #define M 4
  6 typedef struct ANode
  7 {
  8     int i, j;      // i為橫坐標, j為縱坐標
  9     struct ANode *nextarc;
 10 } ArcNode;
 11 
 12 typedef struct
 13 {
 14     ArcNode *mg[N + 2][M + 2];
 15 } AdjGraph;
 16 
 17 typedef struct
 18 {
 19     int i;
 20     int j;
 21 } Box;
 22 
 23 typedef struct
 24 {
 25     Box data[MAXV];
 26     int length;
 27 } Path;
 28 
 29 int visited[N + 2][M + 2] = { 0 };
 30 
 31 void CreateAdj(AdjGraph *&G, int A[N + 2][M + 2], int n, int m)
 32 {
 33     int i, j, k, i1, j1;
 34     ArcNode *p;
 35     G = (AdjGraph *)malloc(sizeof(AdjGraph));
 36     for (i = 0; i < n + 2; ++i)
 37         for (j = 0; j < m + 2; ++j)
 38             G->mg[i][j] = NULL;
 39     for (i = 1; i <= n; ++i)
 40         for (j = 1; j <= m; ++j)
 41             if (A[i][j] == 1)
 42             {
 43                 k = 1;
 44                 while (k <= 4)
 45                 {
 46                     switch (k)
 47                     {
 48                     case 1: i1 = i - 1; j1 = j; break;
 49                     case 2: i1 = i; j1 = j + 1; break;
 50                     case 3: i1 = i + 1; j1 = j; break;
 51                     case 4: i1 = i; j = j - 1; break;
 52                     }
 53                     ++k;
 54                     if (A[i1][j1] == 1)
 55                     {
 56                         p = (ArcNode*)malloc(sizeof(ArcNode));
 57                         p->i = i1;
 58                         p->j = j1;
 59                         p->nextarc = G->mg[i][j];
 60                         G->mg[i][j] = p;
 61                     }
 62                 }
 63             }
 64 }
 65 
 66 void findpath(AdjGraph *G, int x1, int y1, int xe, int ye, Path pa)
 67 {
 68     ArcNode *p;
 69     ++pa.length;
 70     pa.data[pa.length].i = x1;
 71     pa.data[pa.length].j = y1;
 72     visited[x1][y1] = 1;
 73     if (xe == x1 && ye == y1)
 74     {
 75         for (int u = 0; u <= pa.length; ++u)
 76             printf(" (%d, %d) ", pa.data[u].i, pa.data[u].j);
 77     }
 78 
 79     p = G->mg[x1][y1];
 80     while (p != NULL)
 81     {
 82 
 83         if (visited[p->i][p->j] == 0)
 84             findpath(G, p->i, p->j, N, M, pa);
 85         p = p->nextarc;
 86     }
 87     visited[x1][y1] = 0;
 88 }
 89 
 90 int main()
 91 {
 92     AdjGraph *G;
 93     Path pa;
 94     int A[N + 2][M + 2] = {
 95         { 0, 0, 0, 0, 0, 0 },{ 0, 1, 1, 1, 0, 0 },
 96     { 0, 1, 0, 1, 1, 0 },{ 0, 1, 1, 1, 0, 0 },
 97     { 0, 0, 1, 1, 1, 0 },{ 0, 0, 0, 0, 0, 0 } };
 98     CreateAdj(G, A, N, M);
 99     pa.length = -1;
100     findpath(G, 1, 1, N, M, pa);
101     return 0;
102 }

 

 

 

 求解兩個動物之間通信最少翻譯問題

•【目的】:掌握廣度優先遍歷算法在求解實際問題中的運用

 【內容】:編寫一個程序,完成如下功能:
據美國動物分類學家歐內斯特-邁爾推算,世界上有超過100萬種動物,各種動物有自己的語言。假設動物A只能與動物B通信,所以,動物A、C之間通信需要動物B來當翻譯。問兩個動物之間項目通信至少需要多少個翻譯。
     測試文本文件test.txt中第一行包含兩個整數n(2<= n <= 200)、m(1 <= m <= 300),其中n代表動物的數量,動物編號從0開始,n個動物編號為0 ~ n-1,m表示可以相互通信動物數,接下來的m行中包含兩個數字分別代表兩種動物可以相互通信,在接下來包含一個整數k(k <= 20),代表查詢的數量,每個查詢,輸出這兩個動物彼此同喜至少需要多少個翻譯,若它們之間無法通過翻譯來通信,輸出-1.

輸入樣本      輸出結果
3 2                 0
0 1                 1             
2
0 0
0 2

 【來源】:《數據結構教程(第五版)》李春葆著,圖實驗12。


免責聲明!

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



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