1. 程式人生 > >單源最短路-dijkstra的算法

單源最短路-dijkstra的算法

strong com 初始化 csdn ostream 最短距離 長度 main turn

迪傑斯特拉算法用於求解單源最短路問題,能求解出從一個點出發到剩余所有節點的最短距離。

原理:

使用貪心選擇,將全部節點分為兩部分,已經找出最短路徑的點和沒有為找出最短路徑的點,初始情況下源點為唯一一個找出最短距離的點,每次從未找出最短路徑的點中選中距離源點最近的點設置為已經找到最短路徑的點並記錄下相應的最短距離。

具體過程:

算法的時間瓶頸在於怎麽獲得一個節點到源點的距離和查找出距離最短的點的編號。

解決方法是花額外的空間定義一個lowdis數組代表對應下標的節點到源點的最短距離。初始化時如果一個節點和源點是直接連通的,則對應元素初始化為相應的道路長度,否則初始化為無限大INF,每次從中選出值最小的節點,然後更新lowdis數組,更新的原因是再加入一個新的節點後可能存在lowdis[i]>lowdis[minn]+dis[minn][i]的情況,其中minn就是新找到最短距離的節點的編號,也就是當前節點取道minn節點可能會更近。

如果要統計最短路徑節點信息,可以再添加一個last數組,存放每個節點的上一個節點編號,最後再倒序輸出就行。

示例代碼:給出一個圖的信息,求從一個點到另外一個點的最短距離和最短路徑。

[cpp] view plain copy
  1. #include<iostream>
  2. #include<cstring>
  3. #include<stack>
  4. using namespace std;
  5. #define MaxN 100
  6. #define INF 99999
  7. int dis[MaxN][MaxN]; //存放亮點間距離
  8. int last[MaxN]; //存放每個節點的上一個節點
  9. int N; //存放節點數量
  10. int search(int START,int END){ //迪傑斯特拉算法
  11. bool vis[MaxN]={0}; //標記訪問情況
  12. vis[START]=true;
  13. int lowdis[MaxN];
  14. for(int i=0;i<=N;i++){
  15. lowdis[i]=dis[START][i];
  16. last[i]=START;
  17. }
  18. int min,minn;
  19. for(int i=1;i<N;i++){
  20. min=INF;
  21. for(int j=1;j<=N;j++){
  22. if(vis[j]==0){
  23. if(lowdis[j]<min){
  24. min=lowdis[j];
  25. minn=j;
  26. }
  27. }
  28. }
  29. if(min<INF){
  30. vis[minn]=true;
  31. for(int j=0;j<=N;j++){ //更新lowdis數組
  32. if(lowdis[j]>dis[minn][j]+lowdis[minn]){
  33. lowdis[j]=dis[minn][j]+lowdis[minn];
  34. last[j]=minn;
  35. }
  36. }
  37. }
  38. else return -1;
  39. }
  40. return lowdis[END];
  41. }
  42. void showway(int START,int END){ //打印最短道路信息
  43. stack<int> way; //利用棧來倒序輸出
  44. way.push(END);
  45. int at=END;
  46. while(at!=START){
  47. way.push(last[at]);
  48. at=last[at];
  49. }
  50. while(!way.empty()){
  51. cout<<way.top()<<‘ ‘;
  52. way.pop();
  53. }
  54. }
  55. int main(){ //測試
  56. int M,a,b,c;
  57. for(int i=0;i<MaxN;i++)for(int j=0;j<MaxN;j++)dis[i][j]=dis[j][i]=INF;
  58. cout<<"一共有多少個地點多少條道路?"<<endl;
  59. cin>>N>>M;
  60. cout<<"輸入道路信息(輸入連接的兩個地點編號和長度如1 2 3代表1,2間存在長度為3的道路)"<<endl;
  61. while(M--){
  62. cin>>a>>b>>c;
  63. dis[a][b]=dis[b][a]=c;
  64. }
  65. cout<<"從哪到哪"<<endl;
  66. cin>>a>>b;
  67. cout<<"最短距離:"<<search(a,b)<<endl;
  68. cout<<"最短道路:";
  69. showway(a,b);
  70. cout<<endl;
  71. }

附上一組簡單的測試數據

5 7

1 2 3 2 3 4 3 4 5 4 5 6 1 3 1 4 1 10 1 5 99

1 5

單源最短路-dijkstra的算法