【学习记录】Dijkstra算法求有向图最短路径

算法参考资料:

Dijkstra算法求最短路径_哔哩哔哩_bilibili(过程表格)

【算法】最短路径查找—Dijkstra算法_哔哩哔哩_bilibili (动画过程)

代码参考资料:自购纸质资料答案修改

 题目:求点0到点6的距离

思路:

目的是找某点到顶点的最小距离,先全设为超大值m

设一个点k,其表示目前到顶点距离最小的点,先把顶点序号赋给k。

从顶点开始,对其连通点的距离进行更新,遍历整个图,找最小值点(此时顶点不参与),把找到点的序号赋给k,

再从k开始对与其连通点的距离进行更新,遍历整个图,找最小值点(此时为k的点不参与),把找到点的序号赋给k,

直到所有点都遍历完,更新完毕。

难点:

1.循环次数

点数*点数,for循环

2.此时为k的点不参与

给所有点一个标记,当这个点作为k时,标记变化,下一轮找k时不再参与。

3.更新距离

判断目前点i的距离和目前k点距离+k点到i点距离,若大于,则更新。

 步骤:

1.图的表示

输入图的邻接矩阵:七行表示七个点,每个元素为各点到其他点的距离,不相通点之间距离用自定义的超大数m表示。

2.初始化

设置每个节点所需变量:int dist[ 7], path[ 7], mark [ 7] = {0}, vex[7];

        dist[i] = m;
        path[i] = -1;
        vex[i] = -2;

/*设为全局变量便于函数调用或主函数中打印

dist目前每个点到顶点的最小距离, path目前每个点的前一个点, mark 目前点是否已经在最短链中,初始时均不在链中。*/

3.写一个遍历每个点的函数min(),找出目前有最小距离的点,将其赋予K

4.从第一个点开始更新距离

①判断和更新

int  k, i;
	k = start;
	dist[k] = 0;

	for(int number=0;number < 7;number++) {
		for (i = 0; i < 7; i++) {
			if (mark[i] == 0) {
				if (dist[i] > dist[k] + A[k][i]) {
					//将与K点联通的点的距离进行判断更新
					dist[i] = dist[k] + A[k][i];
					path[i] = k;
				}
			}
		}
		k = Min();
		
		mark[k] = 1;
	}

②找k点

int Min( ) {
	int w = 0;
	while (mark[w] != 0) {
		w++;
	}

	for ( int i = 0; i < 7; i++) {
		if (mark[ i] == 0 && dist[i] < dist[w]) {
			w = i;
		}
	}

	return w;
}

③标记变化

   mark[k] = 1;

④下一轮

#更新

if (mark[i] == 0) {
                if (dist[i] > dist[k] + A[k][i])

#找k

        if (mark[ i] == 0 && dist[i] < dist[w]) {
            w = i;
        }

上一轮的k不再参与

5.输出终点的距离

代码: 

#include <stdio.h>
#include <string.h>
#include <math.h>
# define m 5201314

int A[ 7] [ 7] = {
	{ m, 4, 6, 6, m, m, m},
	{ m, m, 1, m, 7, m, m},
	{ m, m, m, m, 6, 4, m},
	{ m, m, 2, m, m, 5, m},
	{ m, m, m, m, m, m, 6},
	{ m, m, m, m, 1, m, 8},
	{ m, m, m, m, m, m, m}
};


int dist[ 7], path[ 7], mark [ 7] = {0};

void initial() {
	int i;
	for ( i = 0; i < 7; i++) {
		dist[i] = m;
		path[i] = -2;
	}
}


int Min( ) {
	int w = 0;
	while (mark[w] != 0) {
		w++;
	}

	for ( int i = 0; i < 7; i++) {
		if (mark[ i] == 0 && dist[i] < dist[w]) {
			w = i;
		}
	}

	return w;
}


void _Dijkstra_(int start, int last) {
	int  k, i;
	k = start;
	dist[k] = 0;

	for(int number=0;number < 7;number++) {
		for (i = 0; i < 7; i++) {
			if (mark[i] == 0) {
				if (dist[i] > dist[k] + A[k][i]) {
					//将与K点联通的点的距离进行判断更新
					dist[i] = dist[k] + A[k][i];
					path[i] = k;
				}
			}
		}
		k = Min();
		
		mark[k] = 1;
	}
}

int main() {
	int start, end;
	scanf("%d", &start);
	getchar();
	scanf("%d", &end);
	initial();
	_Dijkstra_(start, end);
	printf("%d\n", dist[6]);
	for (int u = 0; u < 7; u++) {
	printf("%d->%d\ndist[%d]=%d\n", path[u], u, u, dist[u]);
	}

}

 结果:

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值