看以前写的文章:
图的BFS:http://www.cnblogs.com/youxin/p/3284016.html
DFS:http://www.cnblogs.com/youxin/archive/2012/07/28/2613362.html
递归:
参考了算法导论
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输出:
v1 v3 v7 v6 v2 v5 v8 v4。
非递归要用到栈。
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
图的深度优先算法的递归版本相当简洁好懂。将递归版本的算法改写成非递归版本的难度并不大,关键是要处理好如何正确的在搜索的过程中存储搜索树中的子结点,并正确的进行访问.一种实现采用了两个栈,而另一种则使用一个结点类型为队列的栈..