圖論(三)--深度優先搜尋(DFS)
阿新 • • 發佈:2019-01-10
基於演算法導論圖演算法-深度優先搜尋
- 題目描述
- 問題分析
- 原始碼
- 結果截圖
題目描述
深度優先搜尋(用遞迴和棧分別實現):對圖進行遍歷,得到連通分支數,並求出每個頂點的發現時間和完成時間
問題分析
與廣搜相同,每個頂點白色->灰色->黑色
虛擬碼
遞迴實現(棧實現虛擬碼未提供,可參見原始碼)
原始碼
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;
}
結果截圖