Dijkstra算法

Dijkstra 最短路径算法

输入: 图G=(V,E),V是点集合,E是边集合和原点s

集合X:已经被处理的点集合,初始化:仅包含原点s。

distTo[s]=0初始化s点的距离为0,其他点为无穷大

伪代码: 

(1) while (集合X$ eq$V)

(2)遍历所有的边$(v,w) in E$ 

其中$v in X$,$w otin X$

选择一条边能够使得当前$distTo[v] + l_{vw}$达到最小。

(3)将该点$w$加入X集合中。

(4)更新当前distTo[w]的值。重复上述过程,直到while结束。

1 未优化的C++ Dijkstra算法代码如下,复杂度为$O(mn)$,$n$为顶点数,$m$为边数,,运行时间为::0.037477s

    Dijkstra(Graph graph, int s)
    {
        distInit();        
        marked.push_back(s);//将原点加入集合X中
        distTo[s] = 0; //原点距离初始化为0
        /***当集合X点不包括图中的顶点时****/
        while(marked.size() < length)  
        {
            long int min = maxInt;
            int index1, index2, indexMin;
            /******marked:be added to set X,集合X中的点******/
            for(int i = 0; i < marked.size(); i++) 
            {
                EdgeNode *p = new EdgeNode(0,NULL);
                p = (graph.adjList+marked[i])->firstEdge;
                index1 = marked[i];//集合X中的点
                while(p)
                {
                    //try to traversed edges whose head is not in set X, tail in set X.
                    if(min > p->weight + distTo[index1] && !is_marked(p->adjvex))
                    {
                        indexMin = index1;//标记最小索引
                        min = p->weight + distTo[index1];
                        index2 = p->adjvex;//集合X之外的点
                    }
                    p = p->next;
                }
            }
            //如果找到了最小路径
            if(min < maxInt)
            {
                marked.push_back(index2);//将该点添加到集合X中
                distTo[index2] = min;//距离更新
                path[index2].insert(path[index2].begin(),path[indexMin].begin(),path[indexMin].end());//路径更新
                path[index2].push_back(index2);
            }
        }
        
    }

2.用优先队列优化后的代码,实现得有点问题,运行时间为:0.010996s

    Dijkstra(Graph graph, int s)
    {
        priority_queue<int, vector<int>, greater<int> > myQueue;//优先队列
        distInit();//距离初始化,原点距离为0其余各点距离初始化为无穷大
        myQueue.push(s);
        while(!myQueue.empty())
        {
            VertexNode *temp = new VertexNode;    
            EdgeNode *p = new EdgeNode(0,NULL);
            temp = (graph.adjList + myQueue.top());
            p = (graph.adjList + myQueue.top())->firstEdge;
            myQueue.pop(); //将该点弹出
            while(p)//遍历与该点相连的点
            {
                /*************找到能够更新的,压入队列******************/
                if(distTo[p->adjvex] > distTo[temp->data] + p->weight)
                {
                    myQueue.push(p->adjvex);
                    distTo[p->adjvex] = distTo[temp->data] + p->weight;
                    //路径更新
                    edgeTo[p->adjvex].clear();            
                    edgeTo[p->adjvex].insert(edgeTo[p->adjvex].begin(),edgeTo[temp->data].begin(),edgeTo[temp->data].end());
                    edgeTo[p->adjvex].push_back(p->adjvex);
                }
                p = p->next;
            }
        }
    }

3.图的存储

/***********边表***********/
class EdgeNode
{
public:
    int adjvex;
    int weight;
    EdgeNode *next;
    EdgeNode(long int adj, EdgeNode *n = NULL): adjvex(adj), next(n){}

};
/************顶点表*************/
class VertexNode 
{
public:
    long int data;
    EdgeNode *firstEdge;

};

 4.完整代码

https://github.com/Shinered/Dijkstra_algorithm/blob/master/test1.cpp

The Safest Way to Get what you Want is to Try and Deserve What you Want.
原文地址:https://www.cnblogs.com/Shinered/p/9019624.html