圖的深度優先搜索dfs

 圖的深度優先搜索:

1.將最初訪問的頂點壓入棧;ios

2.只要棧中仍有頂點,就循環進行下述操做:數組

(1)訪問棧頂部的頂點u;函數

(2)從當前訪問的頂點u 移動至頂點v 時,將v 壓入棧。若是當前頂點u 不存在未訪問的相鄰矩陣,則將u 從棧中刪除;spa

 

主要的幾個變量:

color[n] 用WHITE、GRAY、BLACK 中的一個來表示頂點i 的訪問狀態
M[n][n] 鄰接矩陣, 若是存在頂點i 到頂點j 的邊,則M[i][j]爲true
Stack S

棧, 暫存訪問過程當中的頂點code

 

 

 

 

 

其中color 數組中, 白色表明「未訪問的頂點」, 灰色表明「訪問過的頂點」(雖然被訪問過了,但仍然可能留有通往未訪問頂點的邊), 黑色表明」訪問結束的頂點」;blog

 

有倆種方法實現深度優先遍歷

(1)用遞歸實現的深度優先搜索

#include<stdio.h>

#define N 100
#define WHITE 0
#define GRAY 1
#define BLACK 2
 
int n, M[N][N];
int color[N], d[N], f[N], tt;//color[n]表示該頂點訪問與否,d[n]表示該頂點的發現時刻 ,f[n]表示該頂點的結束時刻 ,tt表示時間 


//用遞歸函數實現的深度優先搜索 
void dfs_visit(int u) {
    int v;
    color[u] = GRAY;
    d[u] = ++tt;
    for(v = 0; v < n; v++) {
        if(M[u][v] == 0)    continue;
        if(color[v] == WHITE)
            dfs_visit(v);
    }
    color[u] = BLACK;
    f[u] = ++tt;//訪問結束 
}

void dfs() {
    int u;
    //初始化 
    for(u = 0; u < n; u++)    color[u] = WHITE;
    tt = 0; 
    
    //以未訪問的u爲起點進行深度優先搜索
    for(u = 0; u < n; u++) {
        if(color[u] == WHITE)
            dfs_visit(u);
    } 
    
    //輸出 
    for(u = 0; u < n; u++) {
        printf("%d %d %d\n", u+1, d[u], f[u]); 
    }
}

int main() {
    int u, v, k, i, j;
    
    scanf("%d", &n);
    //初始化 
    for(i = 0; i < n; i++) {
        for(j = 0; j < n; j++) {
            M[i][j] = 0;
        }
    }
    //輸入數據,構造鄰接矩陣 
    for(i = 0; i < n; i++) {
        scanf("%d %d", &u, &k);
        u--;
        for(j = 0; j < k; j++) {
            scanf("%d", &v);
            v--;
            M[u][v] = 1;
        }
    }
    
    dfs();
    
    return 0;
}

/*
6
1 2 2 3
2 2 3 4 
3 1 5
4 1 6
5 1 6
6 0
*/

 

 

 

(2)用棧實現的深度優先搜索

 

#include<iostream>
#include<stack> 
using namespace std;

static const int N = 100; 
static const int WHITE = 0;
static const int GRAY = 1;
static const int BLACK = 2;

int n, M[N][N];
int color[N], d[N], f[N], tt;//color[n]表示該頂點訪問與否,d[n]表示該頂點的發現時刻 ,f[n]表示該頂點的結束時刻 
int nt[N];//記錄每一個頂點的鄰接頂點偏移量,eg:頂點0有倆個頂點1,2;現已經訪問過1了,那麼, nt[u] = 1; 下次直接訪問2 

//按編號順序獲取與u相鄰的v
int next(int u) {
    for(int v = nt[u]; v < n; v++) {
        nt[u] = v + 1;
        if(M[u][v])    return v;
    }
    return -1;
}


void dfs_visit(int r) {
    for(int i = 0; i < n; i++)    nt[i] = 0;
    
    stack <int> S;
    S.push(r);
    color[r] = GRAY;
    d[r] = ++tt;
    
    while( !S.empty() ) {
        int u = S.top();
        int v = next(u);
        if(v != -1) {
            if(color[v] == WHITE) {
                color[v] = GRAY;
                d[v] = ++tt;
                S.push(v);
            }
        }
        else {
            S.pop();
            color[u] = BLACK;
            f[u] = ++tt;
        }
    }
}

void dfs() {
    //初始化
    for( int i = 0; i < n; i++) {
        color[i] = WHITE;
        nt[i] = 0;
    } 
    //設置時間 
    tt = 0;
    
    //以未訪問的u爲起點進行深度優先搜索,設置循環的目的應該是防止該圖不是連通圖 
    for(int u = 0; u < n; u++) {
        if(color[u] == WHITE)    dfs_visit(u);
    }
    
    for(int i = 0; i < n; i++) {
        cout << i+1 << " " << d[i] << " " << f[i] << endl;
    }
}

int main() {
    int u, k, v;
    cin >> n; //頂點數 
     
    //鄰接矩陣置零 
    for( int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) 
            M[i][j] = 0;
    }
    
    //建立鄰接矩陣 
    for(int i = 0; i < n; i++) {
        cin >> u >> k;//輸入頂點和頂點的度
        u--;
        for(int j = 0; j < k; j++) {
            cin >> v;
            v--;
            M[u][v] = 1;
        } 
    }
    
    dfs();
    
    return 0;
}

/*
6
1 2 2 3
2 2 3 4 
3 1 5
4 1 6
5 1 6
6 0
*/ 
相關文章
相關標籤/搜索