dijkstral 算法

来源:互联网 发布:mac内存不足怎么清理 编辑:程序博客网 时间:2024/06/05 11:07

​在图论中,Prim算法是计算最小生成树的算法,而Dijkstra算法是计算最短路径的算法。二者看起来比较类似,因为假设全部顶点的集合是V,已经被挑选出来的点的集合是U,那么二者都是从集合V-U中不断的挑选权值最低的点加入U,那么二者是否等价呢?也就是说是否Dijkstra也可以计算出最小生成树而Prim也可以计算出从第一个顶点v0到其他点的最短路径呢?答案是否定的,否则就不必有两个算法了。

二者的不同之处在于“权值最低”的定义不同,Prim的“权值最低”是相对于U中的任意一点而言的,也就是把U中的点看成一个整体,每次寻找V-U中跟U的距离最小(也就是跟U中任意一点的距离最小)的一点加入U;而Dijkstra的“权值最低”是相对于v0而言的,也就是每次寻找V-U中跟v0的距离最小的一点加入U

一个可以说明二者不等价的例子是有四个顶点(v0, v1, v2, v3)和四条边且边值定义为(v0, v1)=20, (v0, v2)=10, (v1, v3)=2, (v3, v2)=15的图,用Prim算法得到的最小生成树中v0v1是不直接相连的,也就是在最小生成树中v0v1的距离是v0->v2->v3->v1的距离是27,而用Dijkstra算法得到的v0v1的距离是20,也就是二者直接连线的长度。

#include "iostream"#include "vector"#include "fstream"using namespace std;std::vector<vector<double> > weight;std::vector<int> closeset;int vertexnum;int edgenum;void initialvector(){weight.resize(vertexnum); for(int i = 0; i< vertexnum; i++){ weight[i].resize(vertexnum,100000.0); } }void getData(){   ifstream in("data");   in>>vertexnum>>edgenum;   initialvector();   int from,to;   double weight1;   while(in>>from>>to>>weight1){   weight[from][to] = weight1;   weight[from][from] = 0;   weight[to][to] = 0;   //weight[to][from] = weight1;   }}void dijkstra(int source){std::vector<double> lowcost(vertexnum);std::vector<bool> mark(vertexnum);closeset.resize(vertexnum);for(int i = 0;i < vertexnum;i++){lowcost[i] = weight[source][i];if(lowcost[i] != 100000.0){closeset[i] = source;}mark[i] = false;}mark[source] = true;//把节点source添加到closeset中lowcost[source] = 0; for(int i = 0;i < vertexnum;i++){double min = 100000.0;int j = 0;for(int k = 0;k < vertexnum;k++){ //在剩余节点中,选择离closeset距离最近的点if(lowcost[k] < min && !mark[k]){min = lowcost[k];j = k;}}mark[j] = true; /*添加j节点到closeset集合*/for(int k = 0;k < vertexnum;k++){if((weight[j][k] +lowcost[j]) < lowcost[k] && !mark[k]){lowcost[k] = weight[j][k]+lowcost[j];//更新lowcostcloseset[k] = j;}}}}int main(int argc, char const *argv[]){getData();for(int i = 0;i < vertexnum;i++){for(int j = 0;j < vertexnum;j++){cout<<weight[i][j]<<"\t";}cout<<endl;}int source = 0;int dest = 1;int goal = dest;std::vector<int> path(vertexnum);dijkstra(source);int k = 0;    while (dest != source)      {  cout<<closeset[dest]<<endl;        path[k++] = closeset[dest];          dest = closeset[dest];      }      cout<<"The path is ";      for (int j = k-1; j >= 0; j--)      {          cout<<path[j]<<" ->";      }      cout<<goal<<endl;return 0;}

数据:

8 15
4 5 0.35
5 4 0.35
4 7 0.37
5 7 0.28
7 5 0.28
5 1 0.32
0 4 0.38
0 2 0.26
7 3 0.39
1 3 0.29
2 7 0.34
6 2 0.40
3 6 0.52
6 0 0.58
6 4 0.93

参考:http://blog.csdn.net/superdiablo/article/details/6173001


原创粉丝点击