第8周学习总结

图的遍历

39826566dc57453d97372020770b0715.png

什么是图?图是由一些顶点和连接顶点的边组成的,例如上图就是由编号为1~5的五个顶点和(1-2,1-4,2-3,2-5,4-3,5-3,5-4)7条边组成的。而图又分为有向图和无向图

那么什么是有向图呢?例如顶点2和3之间,2可以通过边2-3到达3,而3不可到达2,一般用箭头来表示。有了对有向图的描述,那么可以得知无向图就是两个顶点之间可通过一条边互相到达。如下图所示,2可通过一条边到达3,3也可以通过此边到达2。

e85334c975b844f98db0088d8a4472e4.png

图的存储

如何存储一张图?这里采用图的邻接矩阵法。下图二维数组中i和j表示顶点i到顶点j是否有边。1表示有边,∞表示没有边,设自己到自己的距离为0。(这里设权值即边的长度为1)

013237aa5c9d4498b89300b95b646679.png

深度优先遍历

  • 以未被访问的顶点为起始点,沿其边走到未被访问过的顶点。
  • 当没有未被访问过的顶点时,则回到上一个顶点,继续遍历其他顶点。

现在从顶点1开始遍历,使用深度优先遍历会得到以下结果:

9b76f0888e7a42ab9380fd457d4b85a7.png

从图中可以看出有红色和蓝色两条路径,那么它们是怎么得出来的呢?假设以1为起始点(表示1已访问)开始遍历,顶点1有1-2,1-4两条边,首先选择1-2这条边将2访问。然后以2为起始点有2-3,2-5两条边,选择2-3这条边将3访问。再以3为起始点发现没有边可以到达其他顶点,此轮遍历到达最深处,退回上一个起始点2,从另一条边2-5开始遍历将5访问。再以5为起始点将4访问,此轮遍历到达最深处,逐一返回发现其他顶点都已访问,深度优先遍历结束。

广度优先遍历

  • 以未被访问的顶点作为起点,访问其所有相邻的顶点。
  • 对每个相邻的顶点,再访问它们相邻的顶点,直到所有顶点被访问。

使用广度优先遍历会得到以下结果

73c4eea98b8f4f308bad3a41fd922d28.png

假设以1为起始点,对它的两条边1-2,1-4进行扩展将2,4访问。然后以顶点1的第一条边访问到的顶点2为起始点对两条边2-3,2-5进行扩展,将3和5访问。再以顶点1的第二条边访问到的顶点4为起始点进行扩展,顶点4没有边不做操作。再以顶点3为起始点扩展,顶点3没有边不做操作。随后是顶点5,顶点5有边而顶点4已访问。所有顶点已访问到此广度优先遍历结束。

最短路径

Floyd-Warshall--求任意两点之间的最短路径(多源最短路径)

允许经过1~n号所有顶点进行中转,求任意两点间的最短路径。

假设允许经过1号顶点,只需判断e[i][1]+e[1][j]是否比e[i][j]小即可。(当任意两点间不允许经过第三个点时,这些点的最短路径就是原路径)

核心代码

for (k = 1; k <= n; k++)
		for (i = 1; i <= n; i++)
			for (j = 1; j <= n; j++)
				if (e[i][j] > e[i][k] + e[k][j])
					e[i][j] = e[i][k] + e[k][j];

Dijkstra--求一个点到其余各点的最短路径(单源最短路径)

这里先使用数组dis存放起始顶点到其他顶点的初始路程

  • 找未知路径中的最小值(距离起点最近的顶点)
  • 将该点放入已知的最短路径中(dis数组)
  • 从该点开始对每一条边松弛,以u为始边,如果存在一条边v使u->v(dis[u]+e[u][v])小于dis[v]则用新值代替dis[v]。
  • 最后dis存放的就是1到各点的最短距离

核心代码

	for (i = 1; i <= n - 1; i++)
	{
		//找距起始点最近的顶点
		min = inf;//inf为设置的无穷值
		for (j = 1; j <= n; j++)
		{
			if (book[j] == 0 && dis[j] < min)
			{

				min = dis[j];
				u = j;
			}
		}
		book[u] = 1;//将u标记为1放入最短路径
		for (v = 1; v <= n; v++)
		{
			if (e[u][v] < inf)//小于无穷
			{
				if (dis[v] > dis[u] + e[u][v])
					dis[v] = dis[u] + e[u][v];//用新值代替dis[v]
			}
		}
	}

刷题截图

7067b6792f6a4c2ba160871c1fbde805.png

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值