圖的遍歷遞歸和非遞歸實現

引自:html

http://www.cnblogs.com/dolphin0520/archive/2011/07/13/2105236.htmlios

 圖的遍歷有兩種遍歷方式:深度優先遍歷(depth-first search)和廣度優先遍歷(breadth-first search)。ui

由於深度優先須要無路可走時按照來路往回退,正好是後進先出
廣度優先則須要保證先訪問頂點的未訪問鄰接點先訪問,剛好就是先進先出

1.深度優先遍歷spa

   基本思想:首先從圖中某個頂點v0出發,訪問此頂點,而後依次從v0相鄰的頂點出發深度優先遍歷,直至圖中全部與v0路徑相通的頂點都被訪問了;若此時尚有頂點未被訪問,則從中選一個頂點做爲起始點,重複上述過程,直到全部的頂點都被訪問。能夠看出深度優先遍歷是一個遞歸的過程。3d

   以下圖中的一個無向圖code

   

  其深度優先遍歷獲得的序列爲:htm

  0->1->3->7->4->2->5->6blog

2.廣度優先遍歷遞歸

   基本思想:首先,從圖的某個頂點v0出發,訪問了v0以後,依次訪問與v0相鄰的未被訪問的頂點,而後分別從這些頂點出發,廣度優先遍歷,直至全部的頂點都被訪問完。it

   如上面圖中

   其廣度優先遍歷獲得的序列爲:

   0->1->2->3->4->5->6->7

 

#include<iostream>
#include<queue>
#include<stack>
#include<stdlib.h>
#define MAX 100
using namespace std;

typedef struct 
{
    int edges[MAX][MAX];    //鄰接矩陣
    int n;                  //頂點數
    int e;                  //邊數
}MGraph;

bool visited[MAX];          //標記頂點是否被訪問過

void creatMGraph(MGraph &G)    //用引用做參數
{
    int i,j;
    int s,t;                 //存儲頂點編號
    int v;                   //存儲邊的權值
    for(i=0;i<G.n;i++)       //初始化
    {
        for(j=0;j<G.n;j++)
        {
            G.edges[i][j]=0;
        }
        visited[i]=false;
    }
    for(i=0;i<G.e;i++)      //對矩陣相鄰的邊賦權值
    {
        scanf("%d %d %d",&s,&t,&v);   
//兩個頂點肯定一條邊
//輸入邊的頂點編號以及權值 G.edges[s][t]=v; } } void DFS(MGraph G,int v) //深度優先搜索 { int i; printf("%d ",v); //訪問結點v visited[v]=true; for(i=0;i<G.n;i++) //訪問與v相鄰的未被訪問過的結點 { if(G.edges[v][i]!=0&&visited[i]==false) { DFS(G,i);//若沒訪問則繼續,並且根據頂點的序號按數序訪問 } } } //stack彈出順序有問題 void DFS1(MGraph G,int v) //非遞歸實現 { stack<int> s; printf("%d ",v); //訪問初始結點 visited[v]=true; s.push(v); //入棧 while(!s.empty()) { int i,j; i=s.top(); //取棧頂頂點 for(j=0;j<G.n;j++) //訪問與頂點i相鄰的頂點 { if(G.edges[i][j]!=0&&visited[j]==false) { printf("%d ",j); //訪問 visited[j]=true; s.push(j); //訪問完後入棧 break; //找到一個相鄰未訪問的頂點,訪問以後則跳出循環 } }
//對於節點4,找完全部節點發現都已訪問過或者沒有臨邊,因此j此時=節點總數,而後把這個4給彈出來
直到彈出1,以前的深度搜索的值都已彈出,有半部分尚未遍歷,開始遍歷有半部分
if(j==G.n) //若是與i相鄰的頂點都被訪問過,則將頂點i出棧 s.pop(); } } void BFS(MGraph G,int v) //廣度優先搜索 { queue<int> Q; //STL模板中的queue printf("%d ",v); visited[v]=true; Q.push(v); while(!Q.empty()) { int i,j; i=Q.front(); //取隊首頂點 Q.pop();//彈出一個,而後遍歷這個節點的子節點,而後遍歷完再彈出下一個 for(j=0;j<G.n;j++) //廣度遍歷 { if(G.edges[i][j]!=0&&visited[j]==false) { printf("%d ",j); visited[j]=true; Q.push(j); } } } } int main(void) { int n,e; //創建的圖的頂點數和邊數 while(scanf("%d %d",&n,&e)==2&&n>0) { MGraph G; G.n=n; G.e=e; creatMGraph(G); DFS(G,0); printf("\n"); // DFS1(G,0); // printf("\n"); // BFS(G,0); // printf("\n"); } return 0; }

 參考:

http://hi.baidu.com/huifeng00/item/f06ec624935577869c63d196

暫時沒想通

while(!s.empty())
{int i,j;
i=s.top();
s.pop();
for(j=0;j<G.n;j++)
{
if(g.edges[i][j]!=0&&visited[j]==false)
{
printf("%d",j);
visited[j]=true;
s.push(j);
break;
}
}
}
相關文章
相關標籤/搜索