圖的DFS遞歸和非遞歸

看之前寫的文章:html

圖的BFS:http://www.cnblogs.com/youxin/p/3284016.htmlnode

DFS:http://www.cnblogs.com/youxin/archive/2012/07/28/2613362.html算法

遞歸:ide

參考了算法導論spa

int parent[50];
int
color[50];//0表明white,1 gray 2 black static int time=0; int d[50];//頂點v第一次被發現(並置v爲gray色) int f[50];//結束檢測v的鄰接表(並置v爲黑色) void DFS(Graph G,int u); void DFSTraverse(Graph G,void (*Visit)(VextexType v)) { visitFunc=Visit; for(int i=0;i<G.vexnum;i++) { color[i]=0; parent[i]=-1; } time=0; for(int i=0;i<G.vexnum;i++) { if(color[i]==0) //未訪問 DFS(G,i); } } void DFS(Graph G,int u) { color[u]=1;//white vextex has just been discovered visitFunc(G.vertices[u].data); time=time+1; d[u]=time; ArcNode *p=G.vertices[u].firstarc; while(p) { int v=p->adjvex; if(color[v]==0) { parent[v]=u; DFS(G,v); } p=p->nextarc; } color[u]=2;//black,it's finished f[u]=time=time+1; }
   DFSTraverse(G,visit);
     cout<<endl;
         
     for(int i=0;i<G.vexnum;i++)
         cout<<i<<ends<<parent[i]<<endl;
     cout<<endl;
              
     for(int i=0;i<G.vexnum;i++)
         cout<<i<<ends<<d[i]<<"----"<<f[i]<<endl;

能夠看到DFS輸出:code

v1 v3 v7 v6 v2 v5 v8 v4。htm

 

非遞歸要用到棧。blog

void DFS2(Graph G,int u)
{
     
    stack<int> s;
    visited[u]=true;
    s.push(u);
    
    while(!s.empty())
    {
        int v=s.top();s.pop();
         
        
        visitFunc(G.vertices[v].data);

        ArcNode *p=G.vertices[v].firstarc;
        while(p)
        {
            if(!visited[p->adjvex])
            {
                s.push(p->adjvex);
                visited[p->adjvex]=true;
                
            }
            p=p->nextarc;
        }
        
    }
}

寫非遞歸時千萬要記住的是,進棧時必定要設置visited[i]=true(包括原頂點);否則有些節點會重複進棧DFS和遞歸

二叉樹的先序遍歷是同樣的,只不過二叉樹只有2個分支,要要進右分支,在進左分支,而圖只要是鄰接點都進去,不分前後隊列

 

下面的代碼寫的比較爛:(不要用,用上面的)

void DFS2(Graph G,int u)
{
    color[u]=1;//white vextex has just been discovered
    visitFunc(G.vertices[u].data);
    time=time+1;
    d[u]=time;
    stack<int> s;
    ArcNode *p=G.vertices[u].firstarc;
    while(p)
    {
        color[p->adjvex]=1;
        s.push(p->adjvex);
        p=p->nextarc;
    }
    while(!s.empty())
    {
        int v=s.top();s.pop();
        //color[v]=1;//white vextex has just been discovered,這句話能夠不要,由於在進棧時已經設置了
        visitFunc(G.vertices[v].data);

        ArcNode *p2=G.vertices[v].firstarc;
        while(p2)
        {
            if(color[p2->adjvex]==0)
            {
                s.push(p2->adjvex);
                color[p2->adjvex]=1;//每次進棧都要設置1
                 
            }
            p2=p2->nextarc;
        }
         
    }
}

這裏的d[ ]和f【】很差寫。

輸出:

v1 v2 v4v8 v5 v3 v6 v7

 

鄰接矩陣的非遞歸代碼:

#include
#include
#define max_node 20
#define max 20000
using namespace std;

int map[max_node][max_node];

void dfs(int start,int n)
{
    stack s;
    int i,vis[max_node],ctop;
    memset(vis,0,sizeof(vis));
    vis[start] = 1;
    printf("%d ",start);
    for (i = 1;i <= n;i++)
        if(!vis[i] && map[i][start] == 1)
        {
            vis[i] = 1;
            s.push(i);
        }
    while(!s.empty())
    {
        ctop = s.top();
        vis[ctop] = 1;
        printf("%d ",s.top());
        s.pop();
        for (i = 1;i <= n;i++)
            if(!vis[i] && map[i][ctop] == 1)
            {
                vis[i] = 1;
                s.push(i);
            }
    }
}

int main()
{
    int s,t,n;
    scanf("%d",&n);
    memset(map,max,sizeof(map));
    while(1)
    {
        scanf("%d %d",&s,&t);
        if(s == 0) break;
        map[s][t] = map[t][s] = 1;
    }
    dfs(1,n);
    return 0;
}
輸入:

8
1 2
1 3
2 4
2 5
4 8
5 8
3 6
3 7
0 0

輸出:
1 3 7 6 2 5 8 4
View Code

圖的深度優先算法的遞歸版本至關簡潔好懂。將遞歸版本的算法改寫成非遞歸版本的難度並不大,關鍵是要處理好如何正確的在搜索的過程當中存儲搜索樹中的子結點,並正確的進行訪問.一種實現採用了兩個棧,而另外一種則使用一個結點類型爲隊列的棧..

相關文章
相關標籤/搜索