日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一文搞定深度优先搜索(DFS)与广度优先搜索(BFS)【含完整源码】

發布時間:2024/10/14 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一文搞定深度优先搜索(DFS)与广度优先搜索(BFS)【含完整源码】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

寫在前面:博主是一位普普通通的19屆雙非軟工在讀生,平時最大的愛好就是聽聽歌,逛逛B站。博主很喜歡的一句話花開堪折直須折,莫待無花空折枝:博主的理解是頭一次為人,就應該做自己想做的事,做自己不后悔的事,做自己以后不會留有遺憾的事,做自己覺得有意義的事,不浪費這大好的青春年華。博主寫博客目的是記錄所學到的知識并方便自己復習,在記錄知識的同時獲得部分瀏覽量,得到更多人的認可,滿足小小的成就感,同時在寫博客的途中結交更多志同道合的朋友,讓自己在技術的路上并不孤單。

目錄:
1.深度優先搜索(DFS)
???? ?? 深度優先搜索簡介
???? ?? 深度優先搜索代碼實現(C語言鄰接矩陣完整代碼)
2.廣度優先搜索(BFS)
???? ?? 廣度優先搜索簡介
???? ?? 廣度優先搜索的代碼實現(C語言鄰接矩陣完整代碼)

1.深度優先搜索

1.深度優先搜索簡介

以下圖為例:

采用深度優先算法遍歷這個圖的過程為:

  • 首先任意找一個未被遍歷過的頂點,例如從 V1 開始,由于 V1 率先訪問過了,所以,需要標記 V1 的狀態為訪問過;
  • 然后遍歷 V1 的鄰接點,例如訪問 V2 ,并做標記,然后訪問 V2 的鄰接點,例如 V4 (做標記),然后 V8 ,然后 V5 ;
  • 當繼續遍歷 V5 的鄰接點時,根據之前做的標記顯示,所有鄰接點都被訪問過了。此時,從 V5 回退到 V8 ,看 V8 是否有未被訪問過的鄰接點,如果沒有,繼續回退到 V4 , V2 , V1 ;
  • 通過查看 V1 ,找到一個未被訪問過的頂點 V3 ,繼續遍歷,然后訪問 V3 鄰接點 V6 ,然后 V7 ;
  • 由于 V7 沒有未被訪問的鄰接點,所有回退到 V6 ,繼續回退至 V3 ,最后到達 V1 ,發現沒有未被訪問的;
  • 最后一步需要判斷是否所有頂點都被訪問,如果還有沒被訪問的,以未被訪問的頂點為第一個頂點,繼續依照上邊的方式進行遍歷。
  • 根據上邊的過程,可以得到圖 1 通過深度優先搜索獲得的頂點的遍歷次序為:
    V1 -> V2 -> V4 -> V8 -> V5 -> V3 -> V6 -> V7

    所謂深度優先搜索,是從圖中的一個頂點出發,每次遍歷當前訪問頂點的臨界點,一直到訪問的頂點沒有未被訪問過的臨界點為止。然后采用依次回退的方式,查看來的路上每一個頂點是否有其它未被訪問的臨界點。訪問完成后,判斷圖中的頂點是否已經全部遍歷完成,如果沒有,以未訪問的頂點為起始點,重復上述過程。

    深度優先搜索是一個不斷回溯的過程。

    1.2深度優先搜索代碼實現(C語言鄰接矩陣完整代碼)

    #include <stdio.h>#define MAX_VERtEX_NUM 20 //頂點的最大個數 #define VRType int //表示頂點之間的關系的變量類型 #define InfoType char //存儲弧或者邊額外信息的指針變量類型 #define VertexType int //圖中頂點的數據類型typedef enum{false,true}bool; //定義bool型常量 bool visited[MAX_VERtEX_NUM]; //設置全局數組,記錄標記頂點是否被訪問過typedef struct {VRType adj; //對于無權圖,用 1 或 0 表示是否相鄰;對于帶權圖,直接為權值。InfoType * info; //弧或邊額外含有的信息指針 }ArcCell,AdjMatrix[MAX_VERtEX_NUM][MAX_VERtEX_NUM];typedef struct {VertexType vexs[MAX_VERtEX_NUM]; //存儲圖中頂點數據AdjMatrix arcs; //二維數組,記錄頂點之間的關系int vexnum,arcnum; //記錄圖的頂點數和弧(邊)數 }MGraph; //根據頂點本身數據,判斷出頂點在二維數組中的位置 int LocateVex(MGraph * G,VertexType v){int i=0;//遍歷一維數組,找到變量vfor (; i<G->vexnum; i++) {if (G->vexs[i]==v) {break;}}//如果找不到,輸出提示語句,返回-1if (i>G->vexnum) {printf("no such vertex.\n");return -1;}return i; } //構造無向圖 void CreateDN(MGraph *G){scanf("%d,%d",&(G->vexnum),&(G->arcnum));for (int i=0; i<G->vexnum; i++) {scanf("%d",&(G->vexs[i]));}for (int i=0; i<G->vexnum; i++) {for (int j=0; j<G->vexnum; j++) {G->arcs[i][j].adj=0;G->arcs[i][j].info=NULL;}}for (int i=0; i<G->arcnum; i++) {int v1,v2;scanf("%d,%d",&v1,&v2);int n=LocateVex(G, v1);int m=LocateVex(G, v2);if (m==-1 ||n==-1) {printf("no this vertex\n");return;}G->arcs[n][m].adj=1;G->arcs[m][n].adj=1;//無向圖的二階矩陣沿主對角線對稱} }int FirstAdjVex(MGraph G,int v) {//查找與數組下標為v的頂點之間有邊的頂點,返回它在數組中的下標for(int i = 0; i<G.vexnum; i++){if( G.arcs[v][i].adj ){return i;}}return -1; } int NextAdjVex(MGraph G,int v,int w) {//從前一個訪問位置w的下一個位置開始,查找之間有邊的頂點for(int i = w+1; i<G.vexnum; i++){if(G.arcs[v][i].adj){return i;}}return -1; } void visitVex(MGraph G, int v){printf("%d ",G.vexs[v]); } void DFS(MGraph G,int v){visited[v] = true;//標記為truevisitVex( G, v); //訪問第v 個頂點//從該頂點的第一個邊開始,一直到最后一個邊,對處于邊另一端的頂點調用DFS函數for(int w = FirstAdjVex(G,v); w>=0; w = NextAdjVex(G,v,w)){//如果該頂點的標記位false,證明未被訪問,調用深度優先搜索函數if(!visited[w]){DFS(G,w);}} } //深度優先搜索 void DFSTraverse(MGraph G){//int v;//將用做標記的visit數組初始化為falsefor( v = 0; v < G.vexnum; ++v){visited[v] = false;}//對于每個標記為false的頂點調用深度優先搜索函數for( v = 0; v < G.vexnum; v++){//這個可以作為非連通圖的遍歷模式//如果該頂點的標記位為false,則調用深度優先搜索函數if(!visited[v]){DFS( G, v);}} }int main() {MGraph G;//建立一個圖的變量CreateDN(&G);//初始化圖DFSTraverse(G);//深度優先搜索圖return 0; } //輸入 8,9 1 2 3 4 5 6 7 8 1,2 2,4 2,5 4,8 5,8 1,3 3,6 6,7 7,3 //輸出 1 2 4 8 5 3 6 7

    2.廣度優先搜索(BFS)

    2.1廣度優先搜索簡介

    廣度優先搜索類似于樹的層次遍歷。從圖中的某一頂點出發,遍歷每一個頂點時,依次遍歷其所有的鄰接點,然后再從這些鄰接點出發,同樣依次訪問它們的鄰接點。按照此過程,直到圖中所有被訪問過的頂點的鄰接點都被訪問到。
    最后還需要做的操作就是查看圖中是否存在尚未被訪問的頂點,若有,則以該頂點為起始點,重復上述遍歷的過程。

    還拿圖 1 中的無向圖為例,假設 V1 作為起始點,遍歷其所有的鄰接點 V2 和 V3 ,以 V2 為起始點,訪問鄰接點 V4 和 V5 ,以 V3 為起始點,訪問鄰接點 V6 、 V7 ,以 V4 為起始點訪問 V8 ,以 V5 為起始點,由于 V5 所有的起始點已經全部被訪問,所有直接略過, V6 和 V7 也是如此。
    以 V1 為起始點的遍歷過程結束后,判斷圖中是否還有未被訪問的點,由于圖 1 中沒有了,所以整個圖遍歷結束。遍歷頂點的順序為:

    V1 -> V2 -> v3 -> V4 -> V5 -> V6 -> V7 -> V8

    2.2廣度優先搜索的代碼實現(C語言鄰接矩陣完整代碼)

    #include <stdio.h> #include <stdlib.h> #define MAX_VERtEX_NUM 20 //頂點的最大個數 #define VRType int //表示頂點之間的關系的變量類型 #define InfoType char //存儲弧或者邊額外信息的指針變量類型 #define VertexType int //圖中頂點的數據類型 typedef enum{false,true}bool; //定義bool型常量 bool visited[MAX_VERtEX_NUM]; //設置全局數組,記錄標記頂點是否被訪問過 typedef struct Queue{VertexType data;struct Queue * next; }Queue; typedef struct {VRType adj; //對于無權圖,用 1 或 0 表示是否相鄰;對于帶權圖,直接為權值。InfoType * info; //弧或邊額外含有的信息指針 }ArcCell,AdjMatrix[MAX_VERtEX_NUM][MAX_VERtEX_NUM];typedef struct {VertexType vexs[MAX_VERtEX_NUM]; //存儲圖中頂點數據AdjMatrix arcs; //二維數組,記錄頂點之間的關系int vexnum,arcnum; //記錄圖的頂點數和弧(邊)數 }MGraph; //根據頂點本身數據,判斷出頂點在二維數組中的位置 int LocateVex(MGraph * G,VertexType v){int i=0;//遍歷一維數組,找到變量vfor (; i<G->vexnum; i++) {if (G->vexs[i]==v) {break;}}//如果找不到,輸出提示語句,返回-1if (i>G->vexnum) {printf("no such vertex.\n");return -1;}return i; } //構造無向圖 void CreateDN(MGraph *G){scanf("%d,%d",&(G->vexnum),&(G->arcnum));for (int i=0; i<G->vexnum; i++) {scanf("%d",&(G->vexs[i]));}for (int i=0; i<G->vexnum; i++) {for (int j=0; j<G->vexnum; j++) {G->arcs[i][j].adj=0;G->arcs[i][j].info=NULL;}}for (int i=0; i<G->arcnum; i++) {int v1,v2;scanf("%d,%d",&v1,&v2);int n=LocateVex(G, v1);int m=LocateVex(G, v2);if (m==-1 ||n==-1) {printf("no this vertex\n");return;}G->arcs[n][m].adj=1;G->arcs[m][n].adj=1;//無向圖的二階矩陣沿主對角線對稱} }int FirstAdjVex(MGraph G,int v) {//查找與數組下標為v的頂點之間有邊的頂點,返回它在數組中的下標for(int i = 0; i<G.vexnum; i++){if( G.arcs[v][i].adj ){return i;}}return -1; } int NextAdjVex(MGraph G,int v,int w) {//從前一個訪問位置w的下一個位置開始,查找之間有邊的頂點for(int i = w+1; i<G.vexnum; i++){if(G.arcs[v][i].adj){return i;}}return -1; } //操作頂點的函數 void visitVex(MGraph G, int v){printf("%d ",G.vexs[v]); } //初始化隊列 void InitQueue(Queue ** Q){(*Q)=(Queue*)malloc(sizeof(Queue));(*Q)->next=NULL; } //頂點元素v進隊列 void EnQueue(Queue **Q,VertexType v){Queue * element=(Queue*)malloc(sizeof(Queue));element->data=v;element->next=NULL;Queue * temp=(*Q);while (temp->next!=NULL) {temp=temp->next;}temp->next=element; } //隊頭元素出隊列 void DeQueue(Queue **Q,int *u){(*u)=(*Q)->next->data;(*Q)->next=(*Q)->next->next; } //判斷隊列是否為空 bool QueueEmpty(Queue *Q){if (Q->next==NULL) {return true;}return false; } //廣度優先搜索 void BFSTraverse(MGraph G){//int v;//將用做標記的visit數組初始化為falsefor( v = 0; v < G.vexnum; ++v){visited[v] = false;}//對于每個標記為false的頂點調用深度優先搜索函數Queue * Q;InitQueue(&Q);for( v = 0; v < G.vexnum; v++){if(!visited[v]){visited[v]=true;visitVex(G, v);EnQueue(&Q, G.vexs[v]);while (!QueueEmpty(Q)) {int u;DeQueue(&Q, &u);u=LocateVex(&G, u);for (int w=FirstAdjVex(G, u); w>=0; w=NextAdjVex(G, u, w)) {if (!visited[w]) {visited[w]=true;visitVex(G, w);EnQueue(&Q, G.vexs[w]);}}}}} } int main() {MGraph G;//建立一個圖的變量CreateDN(&G);//初始化圖BFSTraverse(G);//廣度優先搜索圖return 0; }

    本篇博客轉載C語言中文網

    總結

    以上是生活随笔為你收集整理的一文搞定深度优先搜索(DFS)与广度优先搜索(BFS)【含完整源码】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。