您的位置:首页 > 其它

关于深度优先遍历图的非递归算法的一个讨论

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再一次 入栈。所以算法一不正确。

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐