Dijkstra算法小结

1,434 阅读3分钟

由于我的简历上写了2019年软挑的经历,而软挑基于的最基本的算法就是Dijkstra算法,经常电话面说视频面时,面试官会让我说一说这个算法,而这个算法又不是那么好说清楚,所以今天总结一下,以防面试官现场面时让我画给他看。

1.Dijkstra算法是干什么用的?

Dijkstra算法是求某一点到其余点最短路径的算法,其余的很多最短路径算法是为了弥补D算法不适用于负权图的缺陷,而在我们的场景下,不存在负权的情况,所以D算法很适用。

2.Dijkstra算法的基本思想

Dijkstra算法采用的是贪心的策略,维护一个数组dis,dis[i]表示起点到点i的距离,一开始,除了和起点直接相邻的点,其余点都被初始化成正无穷。维护一个set,set里的点表示已经找到最短路径的点,最开始,set中只有起点。

找到dis矩阵中未被添加到set中的点的最小值。并将该点加入set中,然后需要考察通过新添加的点到达其余点的路径和原路径哪个更短,如果新路径更短,需要更新dis数组的值。然后再找到dis矩阵中未被添加到set中的点的最小值,重复上述操作,直到set中包含了图中的所有点。

3.一个小例子

4.代码[主要突出D算法的写法,其余内容均做简化了]

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

#define INF 0xfffffff
#define SIZE 4
int graph[4][4] = { {0,4,INF,1},{ INF,0,3,INF}, {INF,INF,0,INF},{ INF,2,7,0} };//图的邻接矩阵

struct Dis
{
	bool visited;
	int value;
	string path;
	Dis()
	{
		visited = false;
		value = 0;
		path = "";
	}
};

Dis dis[SIZE];//dis数组用于记录地点到各点的最短路径,值,以该点是否已找到最短路径

void dijkstra (int begin)
{
	//初始化dis矩阵
	for (int i = 0; i < SIZE; i++)
	{
		dis[i].value = graph[begin][i];
		dis[i].path = "v" + to_string(begin) + "->" + "v" + to_string(i);
	}
	//设置起点
	dis[begin].value = 0;
	dis[begin].visited = true;
	//计算起点到剩余点的最短路径
	int count = 1;
	while (count != SIZE)
	{
		//找到剩余点中距离最短的点,tmp记录最小点的下标,min记录当前最小值
		int tmp = 0;
		int min = INF;
		for (int i = 0; i < SIZE; i++)
		{
			if (!dis[i].visited && dis[i].value < min)
			{
				min = dis[i].value;
				tmp = i;
			}
		}
		//将该点加入已经找到最短路径的集合中去
		dis[tmp].visited = true;
		++count;
		//更新矩阵的值
		for (int i = 0; i < SIZE; i++)
		{
			if ((!dis[i].visited) && (graph[tmp][i] != INF) && (dis[i].value > dis[tmp].value + graph[tmp][i]))
			{
				dis[i].value = dis[tmp].value + graph[tmp][i];
				dis[i].path = dis[tmp].path + "->v"+to_string(i);
			}
		}
	}
}

void print(int begin)
{
	for (int i = 0; i < SIZE; i++)
	{
		cout << "v" << begin << "  to  " << "v" << i << "  is: " << dis[i].path << ", value is: " << dis[i].value << endl;
	}
}

int main()
{
	int begin;
	cin >> begin;
	dijkstra(begin);
	print(begin);
	return 0;
}

图为上例中的四点图,起点为0时[A,B,C,D分别对应于0,1,2,3],输出: