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