DFS搜索算法--(1)基礎圖遍歷 絕對看!的!懂!


內容總結 自《啊哈!算法!》

作為一個都大二的了一個菜雞,做題的時候DFS怎么可以不會呢!!!

作為一個都大二了的(!!!)菜雞....《啊哈算法》這本書第四章的搜索,開始那里我就沒看懂,就跑來看第五章了。結果這個理解起來方便一些....總結摘抄一下給遠方的不知名網友and for myself。

以下語言有不嚴謹之處請多包涵,先理解重要。

深度搜索算法,就是對於一個圖(圖自己瞎畫的  太丑)  如下圖所示,給這些圓圈標號。

 

 

 

然后我們遍歷的時候,是“優先深度” ,先從一條路走到黑走不動了再換條道繼續一條路走到黑。即先從1開始,走到2,走到5. 然后走不動了就先回去,先回到2,發現還有6可以走,然后又走到6了。然后又走不動了。便回到2,但是2的所有支路已經都被訪問過了,那就再往回走一個,走到1。 回到1以后,2這條道已經走完了,就走到3,再走到7,走不動了再回到3,3沒有別的支路可以走了就再回到1,然后再走4

 

那么上圖的訪問順序是(不算重復的頂點):1  2  5  6  3  7  4

如果一條道走完了,比如說從2走到5,走完了,就要回到上一個路口頂點2。從5到2的過程稱為回溯。

那么如何存儲一個圖呢?我們用一個二維數組arr來存儲:

 

如上兩個圖所示,二維數組中第i行第j列表示的就是頂點i到頂點j是否有邊。1表示有邊,空着的就是沒有邊(在編程時可以將其賦值為9999,畫圖太麻煩我就省去了) ,二維數組行和列相等的我賦值為0.

能看到,上面的這個圖是關於主對角線對稱的,這是因為這個圖是個‘無向圖’。也就是這個圖的邊沒有方向,從1到2和從2到1是一樣的,所以 arr[ 2 ] [ 1 ] = arr[ 1 ][ 2 ] = 1。

 

以下是代碼實現:

其中,book[  ]  這個數組一開始全部賦初值為0,表示未被訪問過。被訪問賦值為1。

還有一個需要知道的小知識點,就是我的代碼內又兩個return,第一個return表示函數結束,第二個return表示返回上一個dfs()函數,這是遞歸函數的特殊用法。比如:現在是dfs(5),執行代碼時遇到了代碼中第二個return,然后就會返回上一個執行的dfs()函數,這就變成了dfs(2),這個過程就是回溯。

 1 void dfs(int cur)//cur是當前在的頂點的編號
 2 {
 3     printf("%d ",cur);//按順序打印出遍歷過的點
 4     sum++;//sum是全局變量,初值為0。每訪問一個點,sum++。
 5     if(sum==n)
 6         return ;//n為全局變量,是總共點的數量。若sum==n,便是點都訪問完了,就退出函數。
 7     
 8     for(int i=1;i<=n;i++)//從1號點到n號點依次嘗試,看看誰與cur點相連着
 9     {
10         if(arr[cur][i]==1&&book[i]==0)//若這個點沒有被訪問過並且與cur相連
11         {
12             book[i]=1;//把這個點標記為已訪問
13             dfs(i);//遞歸,繼續從這個點再繼續深入遍歷
14         }
15     }
16     return ;//當與cur相連的所有點都已被訪問過了,就返回到上一個dfs()
17 }

 

 

完整代碼如下:

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 
 5 int book[101],sum,n,arr[101][101];
 6 
 7 void dfs(int cur)//cur是當前在的頂點的編號
 8 {
 9     printf("%d ",cur);//按順序打印出遍歷過的點
10     sum++;//sum是全局變量,初值為0。每訪問一個點,sum++。
11     if(sum==n)
12         return ;//n為全局變量,是總共點的數量。若sum==n,便是點都訪問完了,就退出函數。
13 
14     for(int i=1;i<=n;i++)//從1號點到n號點依次嘗試,看看誰與cur點相連着
15     {
16         if(arr[cur][i]==1&&book[i]==0)//若這個點沒有被訪問過並且與cur相連
17         {
18             book[i]=1;//把這個點標記為已訪問
19             dfs(i);//遞歸,繼續從這個點再繼續深入遍歷
20         }
21     }
22     return ;//當與cur相連的所有點都已被訪問過了,就返回到上一個dfs()
23 }
24 
25 
26 
27 int main()
28 {
29     sum=0;
30     int m,a,b;
31     cin>>n>>m;//m表示有幾條邊  n表示有幾個點
32     for(int i=1;i<=n;i++){
33         for(int j=1;j<=n;j++){
34             if(i==j)
35                 arr[i][j]=0;
36             else
37                 arr[i][j]=9999999;//把沒有邊相連的標記為999999
38         }
39     }
40 
41     //讀入頂點之間的那些邊
42     for(int i=0;i<m;i++)
43     {
44         cin>>a>>b;
45         arr[a][b]=1;
46         arr[b][a]=1;//由於時無向圖,所以兩個都要標記。在前面我說過了
47     }
48     book[1]=1;//從1號頂點出發。標記1號頂點已經被訪問
49     dfs(1);
50 
51     getchar();getchar();
52 
53 
54     return 0;
55 }

 

ok fine 那么簡單圖遍歷就說完了  下次繼續寫

 


免責聲明!

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



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