7-1 图的先深搜索+7-2 图的先广搜索

本文介绍了如何使用C++通过邻接表实现无向图的广度优先搜索(BFS),并给出了详细的代码示例。文章讨论了头插法和尾插法的区别,并指出在该问题中应使用头插法以符合题目的要求。同时,提供了邻接矩阵实现的DFS代码作为对比,强调其不符合题意。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于本人用指针,链表实现数据结构算法时经常有使用堆叠字节的警告以及栈溢出报错,于是就都用数组或者C++stl模拟了。。。

输出无向图的给定起点的先广序列。

输入格式:

输入第一行给出三个正整数,分别表示无向图的节点数N(1<N≤10)、边数M(≤50)和探索起始节点编号S(节点从1到N编号)。

随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号。

输出格式:

输出从S开始的无向图的先广搜索序列,用一个空格隔开,最后也有一个空格;如果为非连通图,再在结尾处另起一行输出一个0,表示此图非连通。

由于广度优先遍历的节点序列是不唯一的,为了使得输出具有唯一的结果,我们约定以表头插入法构造邻接表。

输入样例:

6 8 2
1 2
2 3
3 4
4 5
5 6
6 4
3 6
1 5

输出样例:

2 3 1 6 4 5 

 注意题目中的以表头插入法构造邻接表

顾名思义,头插就是将新元素插在链表头部,尾插就是将新元素插在链表尾部

个人总结,他们的区别在于,如果是头插法的话,那么新元素直接作为头结点,next指针指向旧的头结点即可,非常方便迅速效率高。如果是尾插法的话,添加新元素时需要遍历旧链表,直到某个节点的next指针为空,说明这个节点是尾节点,修改这个尾节点的next指针为新添加的元素即可

具体的可以参考如下: 

(188条消息) 头插法和尾插法的详细区别_史家欢yyds的博客-优快云博客_头插法和尾插法区别

下面是正解

#include<bits/stdc++.h>
using namespace std;
#define Maxnum 12
vector <int> ALGraph[Maxnum];
int visit[Maxnum];
int vexnum, arcnum, vex, num;//图的当前点数,边数和起始点
void BFS(int vex) {
	cout << vex << ' ';//访问结点vex
	visit[vex] = 1;//标记为访问过了
	num++;//计算输出的节点个数
	queue <int> q;//辅助队列q初始化
	q.push(vex);//vex进队列
	while (!q.empty()) {//队列非空
		int top = q.front();//队头元素出队并置为t
		q.pop();
		int len = ALGraph[top].size();
		for (int i = len - 1; i >= 0; i--) {
			/*for(int i=0;i<len;i++){*/
			if (!visit[ALGraph[top][i]])//访问top顶点尚未访问过的邻接顶点
			{
				cout << ALGraph[top][i]<<' ';
				visit[ALGraph[top][i]] = 1;
				num++;
				q.push(ALGraph[top][i]);
			}
		}
	}
}
int main() {
	cin >> vexnum >> arcnum >> vex;//输入图的当前点数,边数和起始点
	for (int k = 0; k < arcnum; k++) {//输入该条边直接连通的两个节点的编号
		int i, j;
		cin >> i >> j;
		ALGraph[i].push_back(j);//加入i的邻接顶点j
		ALGraph[j].push_back(i);//加入j的邻接顶点i
	}
	BFS(vex);
	if (num != vexnum)cout << endl << 0;//输出结点个数不等于总结点个数,为非完全图,输出0
	return 0;
}

如果用邻接矩阵来实现的话,相当于用了表尾插入法,与题意是不符合的

下面是邻接矩阵实现的深度优先搜索。不过因为不符合题意,所以答案不对。但思路都是一样的

#include<bits/stdc++.h>
using namespace std;
#define Maxnum 12
//邻接矩阵法实现图的深度优先搜索,相当于以表尾插入法构造邻接表
#if 0
typedef char VerTexType;
typedef int ArcType;
typedef struct {
	char vexs[Maxnum];//顶点表
	int arcs[Maxnum][Maxnum];//邻接矩阵
	int vexnum, arcnum;//图的当前点数和边数
}AMGraph;
int LocateVex(AMGraph G, char u) {
	for (int i = 0; i < G.vexnum; i++) {
		if (u == G.vexs[i])
			return i;
	}
	return -1;
}

int begin_num=0;
int visit[Maxnum];
void CreateUDN(AMGraph& G) {	
	cin >> G.vexnum >> G.arcnum>>begin_num;
	for (int k = 0; k < G.arcnum; k++) {
		int i, j;
		cin >> i >> j;//输入边直接连通的两个节点的编号
		G.arcs[i][j] = 1;
		G.arcs[j][i] = 1;
	}
}
void dfs(AMGraph G, int begin_num) {
	cout << begin_num << ' ';
	visit[begin_num] = true;
	for (int w = 1; w <= G.vexnum; w++) {
		if ((G.arcs[begin_num][w] == 1) && (!visit[w]))
			dfs(G, w);
	}
}
int main() {
	AMGraph G;
	CreateUDN(G);
	dfs(G, begin_num);
	return  0;
}
#endif

7-2 图的先广搜索

输出无向图的给定起点的先广序列。

输入格式:

输入第一行给出三个正整数,分别表示无向图的节点数N(1<N≤10)、边数M(≤50)和探索起始节点编号S(节点从1到N编号)。

随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号。

输出格式:

输出从S开始的无向图的先广搜索序列,用一个空格隔开,最后也有一个空格;如果为非连通图,再在结尾处另起一行输出一个0,表示此图非连通。

由于广度优先遍历的节点序列是不唯一的,为了使得输出具有唯一的结果,我们约定以表头插入法构造邻接表。

输入样例:

6 8 2
1 2
2 3
3 4
4 5
5 6
6 4
3 6
1 5

输出样例:

2 3 1 6 4 5 

用辅助队列来实现非递归下的广度优先搜索 ,对比下图具体实现思路修改BFS代码即可

#include<bits/stdc++.h>
using namespace std;
#define MaxInt 32767
#define Maxnum 12
vector <int> ALGraph[Maxnum];
int visit[Maxnum];
int vexnum, arcnum, vex, num;//图的当前点数,边数和起始点
void BFS(int vex) {
	cout << vex << ' ';//访问结点vex
	visit[vex] = 1;//标记为访问过了
	num++;//计算输出的节点个数
	queue <int> q;//辅助队列q初始化
	q.push(vex);//vex进队列
	while (!q.empty()) {//队列非空
		int top = q.front();//队头元素出队并置为t
		q.pop();
		int len = ALGraph[top].size();
		for (int i = len - 1; i >= 0; i--) {
			/*for(int i=0;i<len;i++){*/
			if (!visit[ALGraph[top][i]])//访问top顶点尚未访问过的邻接顶点
			{
				cout << ALGraph[top][i]<<' ';
				visit[ALGraph[top][i]] = 1;
				num++;
				q.push(ALGraph[top][i]);
			}
		}
	}
}
int main() {
	cin >> vexnum >> arcnum >> vex;//输入图的当前点数,边数和起始点
	for (int k = 0; k < arcnum; k++) {//输入该条边直接连通的两个节点的编号
		int i, j;
		cin >> i >> j;
		ALGraph[i].push_back(j);//加入i的邻接顶点j
		ALGraph[j].push_back(i);//加入j的邻接顶点i
	}
	BFS(vex);
	if (num != vexnum)cout << endl << 0;//输出结点个数不等于总结点个数,为非完全图,输出0
	return 0;
}

 可参考如下视频第10周14--6.5图的遍历4--广度优先搜索遍历及其实现_哔哩哔哩_bilibiliicon-default.png?t=M85Bhttps://www.bilibili.com/video/BV1nJ411V7bd?p=125&vd_source=3bba6c1adede36ba00771e043da67d9a

 

 

### 回答1: 算法7-4:度优搜索 1. 从起点开始,将其标记为已访问。 2. 对于起点的每个未访问的邻居,递归地执行步骤1-2。 3. 重复步骤2,直到没有未访问的邻居。 算法7-5:度优搜索(非递归) 1. 从起点开始,将其标记为已访问,并将其压入栈中。 2. 当栈不为空时,弹出栈顶元素,并对其每个未访问的邻居执行步骤1-2,并将其标记为已访问并压入栈中。 3. 重复步骤2,直到栈为空。 ### 回答2: 一、定义 度优搜索(Depth First Search,DFS)是论中的基本算法,是从的某个节点出发,访问这个节点,然后依次访问这个节点的每个未被访问的邻居节点,直至遍历完整个。 二、实现 度优搜索可以通过递归或栈的方式实现。递归实现简单,但难以控制递归度,容易发生栈溢出。栈的实现需要手动模拟栈,但可以灵活控制度,避免栈溢出。 递归实现: 1.从某个节点v开始遍历。 2.标记该节点v为已访问。 3.对于v的每个未被访问的邻居节点w,递归访问w。 栈实现: 1.从某个节点v开始遍历。 2.将v入栈,并标记v为已访问。 3.当栈非空时循环执行以下步骤:弹出栈顶节点u,对于u的每个未被访问的邻居节点w,将w入栈并标记w为已访问。 、应用 度优搜索可以用来判断是否连通,可用于求解最小生成树、拓扑排序、连通分量等问题。 由于度优搜索需要存储所有已访问节点的路径,所以针对大规模的遍历可能导致空间复杂度较高。 四、算法7-4,7-5代码分析 算法7-4: 算法7-4是对度优遍历的递归实现。首遍历该节点,并标记为已访问,然后将该节点的所有邻居节点都遍历一遍。如果邻居节点未被访问,则对该节点进行递归调用进行遍历。 具体思路: 1.定义全局vis数组,用于记录节点是否已被访问。 2.定义一个函数dfs(u),对节点u进行度优遍历。遍历完u的所有邻居节点后,会回溯到该节点u的上一个节点。 3.主函数遍历所有节点,对未被访问的节点进行度优遍历。 算法7-5: 算法7-5是对度优遍历的栈实现。使用了一个栈来存储待访问节点。首将初始节点加入栈中,并标记为已访问,然后循环遍历栈中的节点,直至栈为空。 具体思路: 1.定义全局vis数组,用于记录节点是否已被访问。 2.定义一个函数dfs(u),对节点u进行度优遍历。遍历完u的所有邻居节点后,会回溯到该节点u的上一个节点。 3.主函数遍历所有节点,对未被访问的节点进行度优遍历。在遍历到未被访问的节点时,加入栈中并标记为已访问,然后循环遍历栈中的节点,直至栈为空。 ### 回答3: 算法7-4,7-5是关于的遍历中的度优搜索(DFS),主要是用来搜索和遍历中所有的节点和边的算法。 度优搜索的核心思想是:从一个未访问的节点开始,度优遍历到最处,然后回溯到上一个节点,再从上一个未遍历节点开始继续度优遍历。在具体实现过程中,我们可以使用递归或栈来实现度优搜索算法。 度优搜索算法在的遍历、搜索、路径查找等方面有着广泛的应用,如迷宫问题、拓扑排序、关键路径等。 在算法7-4中,我们给出了使用递归实现度优搜索的伪代码: ```python void DFS(int u) { vis[u] = true; // 标记已经访问过 // 遍历所有邻接节点 for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; // 取出邻接节点 if (!vis[v]) { DFS(v); // 继续遍历 } } } ``` 而在算法7-5中,我们使用栈来实现度优搜索,具体实现过程如下: ```python void DFS(int u) { stack<int> s; // 定义一个栈 s.push(u); // 将起始节点放入栈中 vis[u] = true; // 标记已经访问过 while (!s.empty()) { int v = s.top(); // 取出栈顶节点 s.pop(); // 将该节点出栈 // 遍历所有邻接节点 for (int i = 0; i < G[v].size(); i++) { int w = G[v][i]; // 取出邻接节点 if (!vis[w]) { s.push(w); // 将未访问节点放入栈中 vis[w] = true; // 标记已访问 } } } } ``` 总之,度优搜索算法是一种基本的遍历算法,其核心思想和实现方法都比较简单,但是能够灵活应用在众多相关的算法问题中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值