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

由于本人用指针,链表实现数据结构算法时经常有使用堆叠字节的警告以及栈溢出报错,于是就都用数组或者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的博客-CSDN博客_头插法和尾插法区别

下面是正解

#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

 

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值