由于我的简历上写了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],输出:
