关于深度优先遍历图的非递归算法的一个讨论
2018-03-24 16:17
369 查看
参考:
http://www.cnblogs.com/kubixuesheng/p/4399705.html
http://www.cnblogs.com/dolphin0520/archive/2011/07/13/2105236.html
图的深度优先遍历递归算法大概如下:
1 #include<iostream> 2 #include<queue> 3 #include<stack> 4 #include<stdlib.h> 5 #define MAX 100 6 using namespace std; 7 8 typedef struct 9 { 10 int edges[MAX][MAX]; //邻接矩阵 11 int n; //顶点数 12 int e; //边数 13 }MGraph; 14 15 bool visited[MAX]; //标记顶点是否被访问过 16 17 void creatMGraph(MGraph &G) //用引用作参数 18 { 19 int i,j; 20 int s,t; //存储顶点编号 21 int v; //存储边的权值 22 for(i=0;i<G.n;i++) //初始化 23 { 24 for(j=0;j<G.n;j++) 25 { 26 G.edges[i][j]=0; 27 } 28 visited[i]=false; 29 } 30 for(i=0;i<G.e;i++) //对矩阵相邻的边赋权值 31 { 32 scanf("%d %d %d",&s,&t,&v); 33 //两个顶点确定一条边 34 //输入边的顶点编号以及权值 35 G.edges[s][t]=v; 36 } 37 } 38 39 void DFS(MGraph G,int v) //深度优先搜索 40 { 41 int i; 42 printf("%d ",v); //访问结点v 43 visited[v]=true; 44 for(i=0;i<G.n;i++) //访问与v相邻的未被访问过的结点 45 { 46 if(G.edges[v][i]!=0&&visited[i]==false) 47 { 48 DFS(G,i);//若没访问则继续,而且根据顶点的序号按数序访问 49 } 50 } 51 } 52 //stack弹出顺序有问题 53 void DFS1(MGraph G,int v) //非递归实现 54 { 55 stack<int> s; 56 printf("%d ",v); //访问初始结点 57 visited[v]=true; 58 s.push(v); //入栈 59 while(!s.empty()) 60 { 61 int i,j; 62 i=s.top(); //取栈顶顶点 63 for(j=0;j<G.n;j++) //访问与顶点i相邻的顶点 64 { 65 if(G.edges[i][j]!=0&&visited[j]==false) 66 { 67 printf("%d ",j); //访问 68 visited[j]=true; 69 s.push(j); //访问完后入栈 70 break; //找到一个相邻未访问的顶点,访问之后则跳出循环 71 } 72 } 73 //对于节点4,找完所有节点发现都已访问过或者没有临边,所以j此时=节点总数,然后把这个4给弹出来 74 直到弹出1,之前的深度搜索的值都已弹出,有半部分还没有遍历,开始遍历有半部分 75 if(j==G.n) //如果与i相邻的顶点都被访问过,则将顶点i出栈 76 s.pop(); 77 } 78 } 79 80 void BFS(MGraph G,int v) //广度优先搜索 81 { 82 queue<int> Q; //STL模板中的queue 83 printf("%d ",v); 84 visited[v]=true; 85 Q.push(v); 86 while(!Q.empty()) 87 { 88 int i,j; 89 i=Q.front(); //取队首顶点 90 Q.pop();//弹出一个,然后遍历这个节点的子节点,然后遍历完再弹出下一个 91 for(j=0;j<G.n;j++) //广度遍历 92 { 93 if(G.edges[i][j]!=0&&visited[j]==false) 94 { 95 printf("%d ",j); 96 visited[j]=true; 97 Q.push(j); 98 } 99 } 100 } 101 } 102 103 int main(void) 104 { 105 int n,e; //建立的图的顶点数和边数 106 while(scanf("%d %d",&n,&e)==2&&n>0) 107 { 108 MGraph G; 109 G.n=n; 110 G.e=e; 111 creatMGraph(G); 112 DFS(G,0); 113 printf("\n"); 114 // DFS1(G,0); 115 // printf("\n"); 116 // BFS(G,0); 117 // printf("\n"); 118 } 119 return 0; 120 }View Code
在网络上查了很多资料,又去看了好几本教材,发现这些地方对图的深度优先遍历算法的讲解,基本都是用递归算法实现的。对非递归算法实现描述不是很多。上面第三段代码实现了非递归深搜算法。
在寻找资料过程中,也在思考如何实现,大概设计了如下两种算法:
算法一:(这个是一个错误的思路)
1 st.push(v1)//出发点入栈 2 while(!st.empty()) 3 { 4 temp=st.top(); st.pop();//临时备份栈顶节点到temp,删除栈顶节点 5 printf(temp);//访问temp(原先的栈顶节点) 6 根据temp寻找所有未曾访问的相邻节点,并把这些节点入栈 7 }
算法二:
1 printf(v1);//访问出发节点 2 st.push(v1);//出发点入栈 3 while(!st.empty()) 4 { 5 temp=st.top();//读取栈顶节点到temp 6 循环遍历temp的所有相邻节点: 7 { 8 如果(发现一个未曾访问的相邻节点w): 9 { 10 printf(w);//访问节点w 11 st.push(w);//把w入栈 12 退出循环 13 } 14 } 15 if(temp没有未曾访问的相邻节点) 16 st.pop();//删除栈顶节点 17 }
这两种算法,假如仅仅是对树进行深搜,应该是没有错的。但是对图进行深搜,算法一确实不正确的。看下面这个例子:
对这个图从V0出发做深搜,假如按照算法一操作,假设节点入栈顺序为:V0,V1,V3,……
其中v1和V3入栈时,V0已经出栈。但是取出栈顶V3做访问操作,然后再把V3的相邻未曾访问节点入栈,则会使得V1再一次 入栈。所以算法一不正确。
相关文章推荐
- 邻接表存储图的深度优先、广度优先遍历非递归算法
- leetcode 464. Can I Win 100相加游戏 + 一个十分棒的深度优先遍历DFS的做法
- 关于图的深度优先的递归和非递归算法
- 二叉树深度优先遍历的非递归算法
- 关于邻接表和其深度优先遍历、广度优先遍历的问题
- 无向图的邻接矩阵,深度优先遍历和广度优先遍历的递归与非递归算法
- leetcode 491. Increasing Subsequences所有的递增序列 + 一个典型的深度优先遍历DFS的做法
- leetcode 329. Longest Increasing Path in a Matrix 矩阵中寻找最长递增序列 + 一个典型的深度优先遍历DFS的做法
- leetcode 473. Matchsticks to Square 火柴摆正方形 + 一个经典深度优先遍历DFS的应用
- 无向图的邻接矩阵,深度优先遍历广度优先遍历的递归与非递归算法
- leetcode 392. Is Subsequence 子序列判断 深度优先遍历DFS + 一个很简单的循环
- leetcode 508. Most Frequent Subtree Sum 子树和 + 一个简单的DFS深度优先遍历的做法
- c语言编程 输出一个无向图的邻接表,邻接矩阵,进行深度和广度优先遍历
- 一个小讨论 关于java 数据遍历时size不能修改
- leetcode 513. Find Bottom Left Tree Value 最左边的值 + 一个简单的DFS深度优先遍历
- 深度优先遍历
- 【数据结构实验】图的深度优先/广度优先遍历
- 深度优先遍历与广度优先遍历
- 图的邻接矩阵存储 深度优先遍历 广度优先遍历 C语言实现
- 一个关于Activiti或JBPM流程的回退的讨论