图的遍历(啊哈算法)

图的遍历

使用深度优先搜索进行图的遍历:

从一个未走过的顶点作为起始顶点,比如以1号顶点作为起点。沿1号顶点的边去尝试访问其他未走过的顶点,首先发现2号顶点还没有走到过,于是来到了2号顶点。再以2号顶点作为出发点继续尝试访问其他未走到过的顶点,这样有又来到了4号顶点。再以4号顶点作为出发点继续尝试访问其他为走过的顶点。但是此时沿4号顶点的边,已经不能访问到其他为走过的顶点了,所以需要返回到2号顶点,返回到2号顶点之后,发现沿2号顶点的边也不能访问到其他未走过的顶点了。因此还需要继续返回到一号顶点。在继续沿一号顶点的边看看还能否访问到其他未走过的顶点。此时就会来到3号顶点,再以3号顶点作为出发点继续访问其他未走到过的顶点,于是就来到了5号顶点。到此,end。


深度优先遍历的主要思想就是:

首先以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点:当没有未访问过的顶点是,则回到上一个顶点,继续试探访问别的顶点,直到所有的顶点都被访问过。显然,深度优先遍历是沿着图的某一条分支遍历直到末端,然后回溯,再沿着另一条进行同样的遍历,知道所有的顶点都被访问过为止。

如何存储图:

使用二维数组进行存储。

使用数组中第i行第j列表示的是顶点i到顶点j是否有边。1表示有边,无穷表示没有边,将i=j的时候(自己到自己)设置成为0;这种方法叫做矩阵存储法。

注意:无向图和有向图的区别就在于这个矩阵是否沿对角线对称,沿对角线对称的是无向图、不对称的是有向图。

#include <stdio.h>

int e[100][100], book[100], n, sum = 0;

void dfs(int cur) {//cur是当前顶点编号
	int i;
	printf("%d ", cur);
	sum++;//每访问一个顶点,sum就加一;
	// 边界
	if (sum == n) {//所有顶点都已经访问过则直接跳出
		return;
	}
	// 尝试每一步
	for (i = 1; i <=n; i++) {//从1号顶点到n号顶点依次进行尝试,看哪些顶点与当前顶点cur有边相连。
//	//判断当前顶点cur到顶点i是否有边,并且顶点i是否已访问过;
		if (e[cur][i] == 1 && book[i] == 0) {
			book[i] = 1;//标记顶点i已经访问过;
			dfs(i);//从顶点i再出发继续遍历;
		}
	}
	return;
}

int main() {
	int i, j, m, a, b;

	scanf("%d %d", &n, &m);
	//初始化二维矩阵;
	for (i = 1; i <= n; i++)
		for (j = 1; j <= n; j++)
			if (i == j) e[i][j] = 0;
			else e[i][j] = 999999;//相当于无穷大;

	// 二位数组是沿着主对角线对称,即无向图
	for (i = 1; i <= m; i++) {
		scanf("%d %d", &a, &b);
		e[a][b] = 1;
		e[b][a] = 1;//这里是无向图,所以需要将e[b][a]也赋值为1;
	}
//从1号顶点出发;
	book[1] = 1;//标记1号顶点已经访问过;
	dfs(1);//从1号顶点开始遍历;

	printf("\n");
//下面只是将矩阵打印出来;
	for (i = 1; i <= n; i++) {
		for (j = 1; j <= n; j++) {
			printf("%5d ", e[i][j]);
		}
		printf("\n");
	}

	return 0;
}

使用官渡优先搜索来遍历这个图的过程如下。首先以一个未被访问过的顶点作为起始顶点,比如以1号顶点为起点。将1号顶点放入到队列中,然后将与1号顶点相邻的未访问的顶点即2号、3号、5号顶点一次放入队列中。

广度优先搜索主要思想:

首先以一个未被访问过的顶点作为起始顶点,访问其所有的相邻的顶点,然后对每个相邻的顶点,再访问它们相邻的未被访问过的顶点,直到所有的顶点都被访问过,end。

#include <cstdio>

int main() {

	int e[100][100], book[100] = {0}, n, sum = 0;
	int i, j, m, a, b, cur;

	// 初始化队列
	struct node {
		int n;
	} que[100];
	int head = 0;
	int tail = 0;

	scanf("%d %d", &n, &m);
//初始化二维矩阵;
	for (i = 1; i <= n; i++)
		for (j = 1; j <= n; j++)
			if (i == j) e[i][j] = 0;
			else e[i][j] = 999999;

	// 二位数组是沿着主对角线对称,即无向图
	for (i = 1; i <= m; i++) {
		scanf("%d %d", &a, &b);
		e[a][b] = 1;
		e[b][a] = 1;
	}

	book[1] = 1;
	que[tail].n = 1;
	tail++;

	while (head < tail) {
		cur = que[head].n;

		for (i = 1; i <= n; i++) {
			if (e[cur][i] == 1 && book[i] == 0) {
				book[i] = 1;
				que[tail].n = i;
				tail++;
			}

			if (tail > n) {
				break;
			}
		}

		head++;
	}

	for (i = 0; i < tail; i++)
		printf("%d ", que[i].n);

	return 0;
}
(*^▽^*)就是这个样子啦~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

加油当当

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值