转自:https://zhuanlan.zhihu.com/p/40338107
1.介绍
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。
但它不能处理负权路径,如果先找到一条不为负的最短,但当前目标节点已经被访问过,就无法更新包括负权的路径了。
2.基本过程
- 指定起点s,定义两个集合S、U,其中S表示已经求出最短路径的节点,U表示待求的
- 初始时S中只有s节点,从U中选取出距离最近的加入,并且更新U中其他节点经过u到s的最短距离。
- 直到所有节点都被访问完。
3.实现
https://blog.csdn.net/qq_35644234/article/details/60870719
void Graph_DG::Dijkstra(int begin){ //首先初始化我们的dis数组 int i; for (i = 0; i < this->vexnum; i++) { //设置当前的路径 //begin默认为0,更新直接相连的为默认距离 dis[i].path = "v" + to_string(begin) + "-->v" + to_string(i + 1); dis[i].value = arc[begin - 1][i]; } //设置起点的到起点的路径为0 dis[begin - 1].value = 0; dis[begin - 1].visit = true;//标记初始节点访问过 int count = 1; //计算剩余的顶点的最短路径(剩余this->vexnum-1个顶点) while (count != this->vexnum) { //temp用于保存当前dis数组中最小的那个下标 //min记录的当前的最小值 int temp=0; int min = INT_MAX; for (i = 0; i < this->vexnum; i++) {//选择距离最小的顶点 if (!dis[i].visit && dis[i].value<min) { min = dis[i].value; temp = i; } } //cout << temp + 1 << " "<<min << endl; //把temp对应的顶点加入到已经找到的最短路径的集合中 dis[temp].visit = true;//标记已找到最小距离 ++count; for (i = 0; i < this->vexnum; i++) { //注意这里的条件arc[temp][i]!=INT_MAX必须加,不然会出现溢出,从而造成程序异常 if (!dis[i].visit && arc[temp][i]!=INT_MAX && (dis[temp].value + arc[temp][i]) < dis[i].value) { //如果新得到的边可以影响其他为访问的顶点,那就就更新它的最短路径和长度 dis[i].value = dis[temp].value + arc[temp][i]; dis[i].path = dis[temp].path + "-->v" + to_string(i + 1); } } } }
4.时空复杂度
https://www.cnblogs.com/gaochundong/p/dijkstra_algorithm.html
m为边数,n为节点数,如果用邻接矩阵存储,并且只使用普通的数组存储距离的话,那么时间复杂度为O(n^2)。
下图中V是顶点数目,E是边:
//不太明白binary heap和斐波那契堆是什么。