迪杰斯特拉算法学习

转自: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和斐波那契堆是什么。

posted @ 2021-02-01 14:15  lypbendlf  阅读(101)  评论(0编辑  收藏  举报