1. 程式人生 > >圖論(三)--深度優先搜尋(DFS)

圖論(三)--深度優先搜尋(DFS)

基於演算法導論圖演算法-深度優先搜尋

  • 題目描述
  • 問題分析
  • 原始碼
  • 結果截圖

題目描述

深度優先搜尋(用遞迴和棧分別實現):對圖進行遍歷,得到連通分支數,並求出每個頂點的發現時間和完成時間

問題分析

與廣搜相同,每個頂點白色->灰色->黑色

虛擬碼

這裡寫圖片描述

遞迴實現(棧實現虛擬碼未提供,可參見原始碼)

遞迴實現

原始碼

void DFS(Graph G);//dfs圖
void DFS_VISIT(Graph G, Vertex u);//從某個結點dfs遞迴實現
void DFS_visit_stack(Graph G, Vertex v);//深搜用棧實現
void print_path(Graph G, Vertex v);//列印一個點的深搜路徑,沿著pred向上找
void print_path_everyPoint(Graph G);//列印每個頂點的深搜路徑

圖的頂點資料結構有所變化(添加發現時間和完成時間)

struct VertexRecord {
    Vertex pred;//先驅結點
    int in_degree;//入度 
    int out_degree;//出度 
    int color;//頂點狀態
    int dist;//距離源點的距離
    int discover_time;//深搜發現時間
    int finish_time;//深搜時的結束時間
    List  adjto;//指向第一個鄰接結點的指標
};
#include<stack>
void print_path(Graph G, Vertex v) {//列印一個點的深搜路徑,沿著pred向上找 if (G->vertices[v].pred != -1) { print_path(G, G->vertices[v].pred); } printf(" %d", v); } void print_path_everyPoint(Graph G) {//列印每個頂點的深搜路徑 for (int i = 0; i < G->vexnum; i++) { printf("頂點%d的深搜路徑為:"
,i); print_path(G, i); printf("\n"); } } void print_time_dfs(Graph G) {//列印每個頂點的發現時間和結束時間 for (int i = 0; i < G->vexnum; i++) { printf("頂點%d發現時間:%d,結束時間為:%d", i, G->vertices[i].discover_time, G->vertices[i].finish_time); printf("\n"); } } int Time; //int count_finishTime_descreasing = VertexNum; void DFS_VISIT(Graph G, Vertex u) {//遞迴實現深搜 Time = Time + 1; G->vertices[u].discover_time = Time; //if (G->vertices[u].pred == -1) G->vertices[u].dist = 0; //else G->vertices[u].dist = G->vertices[G->vertices[u].pred].dist + 1;//權為1計算,此處為距離的計算 G->vertices[u].color = 1;//gray PtrToNode ptr = G->vertices[u].adjto; while (ptr != NULL) { Vertex v = ptr->adjvex; if (G->vertices[v].color == 0) { G->vertices[v].pred = u; DFS_VISIT(G, v); } ptr = ptr->next; } G->vertices[u].color = 2;//black Time = Time + 1; G->vertices[u].finish_time = Time; } void DFS_visit_stack(Graph G, Vertex v) {//深搜用棧實現 PtrToNode ptr; stack<int> S; S.push(v); //G->vertices[v].dist = 0; G->vertices[v].color = 1;//灰色 G->vertices[v].discover_time = ++Time; printf("\n%d", v); while (!S.empty()) { Vertex u = S.top(); ptr = G->vertices[u].adjto; while (ptr != NULL) { if (G->vertices[ptr->adjvex].color == 0) { S.push(ptr->adjvex); //G->vertices[ptr->adjvex].dist = G->vertices[u].dist + 1;//權為1計算,此處為距離的計算 G->vertices[ptr->adjvex].color = 1;//灰色 Time++; G->vertices[ptr->adjvex].discover_time = Time; G->vertices[ptr->adjvex].pred = u; printf(" %d", ptr->adjvex); break; } ptr = ptr->next; } if (S.top() == u) { G->vertices[u].color = 2;//黑色 Time++; G->vertices[u].finish_time = Time; //finishTime_descreasing[--count_finishTime_descreasing] = u; S.pop(); } } printf("\n"); } void DFS(Graph G) { int count = 0; for (int i = 0; i < G->vexnum; i++) { G->vertices[i].color = 0;//白色 G->vertices[i].pred = -1; } Time = 0; for (int i = 0; i < G->vexnum; i++) { if (G->vertices[i].color == 0) { //DFS_VISIT(G, i); DFS_visit_stack(G, i); count++; } } printf("共有%d個連通分量\n", count); print_path_everyPoint(G);//列印每個頂點的深搜路徑 print_time_dfs(G);//列印每個頂點距離0的距離 } int main() { //有向圖的隨機生成(20個頂點,100左右的邊,可以進行修改) //CreateRandomDirectGraph(); //Graph G = CreateDirectGraph(); //無向邊的隨機生成(20個頂點,50左右的邊) CreateRandomUndirectGraph(); Graph G = CreateUndirectGraph(); printf("列印圖結構:\n"); print_graph(G);//列印圖 //printf("\n列印各頂點入度和出度:\n"); //print_VertexDegree(G);//列印頂點度數 //printf("\n列印每條邊的權值:\n"); //print_EdgeWeight(G);//列印邊權 //printf("\n下面是bfs:\n"); //BFS(G, 0); printf("\n下面是dfs:"); DFS(G); return 0; }

結果截圖

這裡寫圖片描述