Dijkstra 最短路径算法
输入: 图G=(V,E),V是点集合,E是边集合和原点s
集合X:已经被处理的点集合,初始化:仅包含原点s。
distTo[s]=0初始化s点的距离为0,其他点为无穷大
伪代码:
(1) while (集合X$\neq$V)
(2)遍历所有的边$(v,w) \in E$
其中$v \in X$,$w \notin 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