深度优先搜索遍历类似于树的先序遍历(根节点→左子树→右子树),借助了栈结构以实现递归;
广度优先搜索遍历则类似于层次遍历,借助于队列结构实现。
因为图的任意两个顶点都有可能存在联系,所以在访问某个顶点后,可能沿着某条路径又会回到访问过的顶点。为了避免同一顶点被访问多次,在遍历图的过程中,必须用一个数组visited[]记录每个访问过的顶点。
以邻接矩阵为存储结构的遍历,时间复杂度为O(n²);以邻接表为存储结构的遍历,时间复杂度为O(n+e)。
目录
一.深度优先遍历(DFS)
1.DFS定义
2.递归实现DFS
邻接矩阵:
邻接表:
3.非递归实现DFS
邻接矩阵:
邻接表:
二. 广度优先遍历(BFS)
邻接矩阵
邻接表
假设给定图的所有状态都是未曾访问过.在G中任选一个点V作为初始点。则深度优先遍历的定义如下:
首先访问出发点V,并将其标记为已访问过。然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的处发点继续进行深度优先遍历,直至图中所有和源点v路径相通的顶点均被访问。若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。
图的深度优先遍历类似于图的前序遍历。采用搜索方法的特点是尽可能对纵深方向进行搜索。这种搜索方法被称为深度优先搜索
遍历过程:
(1)从图中的某个顶点开始访问;
(2)若顶点存在未被访问的邻接顶点,则继续访问它的其中一个邻接顶点;
(3)重复步骤(2)直至某个顶点不存在未被访问的邻接顶点;
(4)从步骤(3)的某个顶点开始回溯访问,若回溯访问的邻接顶点存在未被访问的邻接顶点,则再执行步骤(2)(3)(4);
(5)重复步骤(2)(3)(4)直至所有顶点均被遍历,visted[n] 的值都非0。
这种一条路走到底,走不通再返回的特征正是“深度”一词的体现,“回溯”体现在标记数组visited[]中。
int visited[MAX]
void DFSTrave(Graph G)
{
for(int i=0;i
int visited[MAX];
void DFSTraverse(ALGraph G)
{
for(int i=0;iadjvex])
{
DFS(G,p->adjvex);
}
p=p->nextarc;
}
}
借助栈实现
思路:
1.初始化栈
2.输出起始的顶点,起始顶点改为“已访问”的标志,将起始顶点进栈
3.重复一下的操作直至栈为空:
取栈顶元素顶点,存在着未被访问的邻结点W
输出顶点W,将顶点W改为“已访问”,将W进栈;
否则,当前顶点退栈
void dfs(MGraph G,int v)
{
cout< s;//创建一个栈
s.push(v);//入栈
while(!s.empty())
{
int i,data;
data=s.top();//取top的顶点
for(i=0;i
void dfs(ALGraph G,int i)
{
cout< ,因为G是结构体,P是结构体指针
visited[i]=1;
stack s;
s.push(i);
while(!s.empty())
{
ArcNode *p;
p=G.vexs[s.top()].firstarc;
while(p)
{
if(!visited[p->adjvex])
{
visited[p->adjvex]=1;
cout<adjvex].data;
s.push(p->adjvex);
p=G.vexs[p->adjvex].firstarc;
}
else
p=p->nextarc;
}
if(!p)
{
s.pop();
}
}
}
广度优先搜索遍历类似于树的层次遍历。广度优先是一层一层地遍历,而不会从某个顶点开始一直往下遍历,直到不符合遍历的条件。以横向遍历为先,即访问顶点v1后,顺序访问v1的邻接顶点v2,v3,然后先顺序访问v2的邻接顶点,再顺序访问v3的邻接顶点,如此类推。
深度优先利用栈结构实现递归,广度优先则需要队列来实现每一层的顺序执行:
(1)v1入队,访问顶点v1,并在visited[]将顶点v1对应的元素值=1;
(2)检查v1的邻接顶点,v2和v3顺序入队;
(3)v1出队;
(4)访问顶点v2,检查v2的邻接顶点并使它们顺序入队;
(5)v2出队,访问顶点v3;
(6)访问顶点v3,检查v3的邻接顶点并使它们顺序入队;
(7)之后的入队、出队过程如此类推。
*利用队列“先来先服务”的性质,在编写代码时可以将思路转化为先求队列,再遍历。
void BFS(MGraph G)
{
queueq;//队
for(int i=0;i
void BFS(ALGraph G)
{
queueq;//队
for(int i=0;iadjvex])
{//节点未被访问
visited[p->adjvex]=1;
cout<adjvex].data;
q.push(p->adjvex);//入队
}
p=p->nextarc;
}
}
}
}
}