深度优先搜索DFS和广度优先搜索BFS

DFS详细介绍

DFS——不断回溯的过程。

类似于树的先序遍历,从任一未被遍历过的点开始,将改点标记为visited,然后去找改点连通的点,如果没有被遍历则标记为visited,然后继续探索。。。。当没有可以探索的点时,则回溯到上一个点。
在这里插入图片描述
以上图为例,遍历过程为:v1 v2 v4 v 8 v 5 v3 v6 v7
注意:DFS结果不是唯一的,看自己是如何设定的,以下也可以使DFS遍历的结果
v1 v3 v7 v6 v2 v5 v8 v4

int MGraph::FirstAdj(int i){//找到第一个没有被visited的邻近点
	for (int j =0; j < this->vexnum; j++){
		if (this->visited[j] == false && this->arcs_matrix[i][j] != 0)
			return j;
	}
	return -1;
}
int MGraph::NextAdj(int i,int w){//下一个没有被visited的邻近点
	for (int j = w+1; j < this->vexnum; j++){
		if (this->visited[j] == false && this->arcs_matrix[i][j] != 0)
			return j;
	}
	return -1;
}
void MGraph::DFS(int i){
	visited[i] = true;
	cout << vexs[i] << " ";
	for (int w = FirstAdj(i); w >= 0; w = NextAdj(i,w)){
		DFS(w);
	}
}
void MGraph::DFSTraverse(){
	cout << "深度优先遍历" << endl;
	for (int i = 0; i < this->vexnum; i++){//针对非连通图,如果是连通图一次DFS则可以
	//全部遍历完
		if (visited[i] == false)//false表示没有被visited
			DFS(i);
	}
	//this->reset();复位是否visited
	cout << endl;
}

DFS是一个不断回溯的过程,递归的方法本质上是系统帮我们实现了压栈出栈的过程,一切的递归过程都可以改为非递归。所以我们也可以用手动的压栈出栈。


仍然以上图为例:
在这里插入图片描述
手动压栈主要分为以下四个过程
在这里插入图片描述
注意:(文中所有的连通,都包括没有被visited这一条件)
从v1开始将v1压栈
访问栈顶v1,标记为visited,查找v1连通的点
找到v2 入栈
访问栈顶v2 标记为visited 查找v2连通的点
找到v4入栈
访问栈顶v4 标记为visited 查找v4连通的点
。。。。
最终访问完v1v2v4v8v5 栈中成员如上图1所示

开始回溯
栈顶v5 没有连通的点 出栈
栈顶v8 没有连通的点 出栈
。。。。。
最终栈中如图2所示

访问栈顶v1 找到v3
压栈。。。
最后结过如图3所示

再回溯 依次出栈 栈空 结束!

BFS

类似于树的层次遍历,通过队列实现。从任一未被visited的点开始,将其放入队列。
while(队列非空){
出队,标记为visited;
找到出队元素连通的点,入队 ;

void MGraph::BFSTraverse(){
	cout << "广度优先遍历" << endl;
	queue<int>q;//注意这里队列中记录是元素的下标
	for (int i = 0; i < this->vexnum; i++){
		if (visited[i] == false)
			q.push(i);
		while (!q.empty())
		{
			int temp = q.front();
			q.pop();
			if (visited[temp] == false){//加这一步判断是因为
				//如果一个结点和多个结点连通,这个结点可能会被多次放入队列中
				visited[temp] = true;
				cout << vexs[temp] << " ";
			}
			for (int w = FirstAdj(temp); w >= 0; w = NextAdj(temp, w)){
				q.push(w);
			}
		}
	}
	//this->reset();
	cout << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值