dijkstra算法詳細分析

// dijkstra.cpp : Defines the entry point for the console application.
//


#include "stdafx.h"


//狄傑斯特拉算法尋找圖中的最短距離//


#include <iostream>
#include "stdio.h"
#include "stdlib.h"
#include <deque>
#include <vector>
#include <algorithm>
using namespace std;






 //數據元素最大個數//
  const int maxnum =100; 
 //定義無窮大用來初始化特殊路徑數組;表示s中的點沒有能夠鏈接到此點。
  const int maxint =999999;


  //各個數組都是從下標1開始的


  int dist1[maxnum];     //用來存貯當前點到源點的距離//
  int prev1[maxnum];     //記錄當前點的前一個節點;
  int c1[maxnum][maxnum];//記錄圖的兩點間路徑的長度;
  int n1,line1;           //圖的節點數和路徑數//
  void dijkstra(int n,int v,int *dist,int *prev,int c[maxnum][maxnum]);
  void initGraph(string path);
  void searchPath(int *prev,int v, int u);


int _tmain(int argc, _TCHAR* argv[])
{
//初始化圖
 initGraph("input.txt");
//狄傑斯特拉算法進行最短距離計算//
 dijkstra(n1,1,dist1,prev1,c1);
 //輸出元點到各個點的最短距離;
 searchPath(prev1,1,n1);





//輸出;
return 0;
}




         //函數名: freopen
//功 能: 替換一個流,或者說重新分配文件指針,實現重定向。如果stream流已經打開,則先關閉該流。如果該流已經定向,則freopen將會清除該定向。此函數一般用於將一個指定的文件打開一個預定義的流:標準輸入、標準輸出或者標準出錯。
//用 法: FILE *freopen(const char *filename,const char *type, FILE *stream);
         //頭文件:stdio.h
//返回值:如果成功則返回該指向該stream的指針,否則爲NULL//
   void initGraph(string path)
   {
     freopen(path.c_str(),"r",stdin);
//輸入點數//
cin>>n1;
// 輸入路徑數;
cin>>line1;
int p,q,len;





 //初始化爲最大整數//
for (int i=1;i<=n1;i++)
{
for (int j=1;j<=n1;j++)
{
c1[i][j]=maxint;
}
}


//輸入點和邊
for (int i=1;i<=line1;i++)
{
cin>>p>>q>>len;
if (len<c1[p][q])//有重邊
{
c1[p][q]=len;//p指向q
c1[q][p]=len;//q指向p;表示無向圖;


}

}
//初始化當前距離數組爲最大整數值
for (int i=1;i<=n1;i++)
{
dist1[i]=maxint;
}


//輸出到屏幕所輸入的結果;
for(int i=1; i<=n1; ++i)
{
for(int j=1; j<=n1; ++j)
printf("%9d", c1[i][j]);
printf("\n");
}
   }


   // n -- n nodes
   // v -- the source node
   // dist[] -- the distance from the ith node to the source node
   // prev[] -- the previous node of the ith node
   // c[][] -- every two nodes' distance
   void dijkstra(int n,int v,int *dist,int *prev,int c[maxnum][maxnum])
   {
      //初始化s集合//
  bool s[maxnum];
  ////////////////////與源點(當前點)相連接的點的點的距離記錄下來/////////////////////////
  for (int i=1;i<=n;i++)
  {
  dist[i]=c[v][i];
  s[i]=0;//初始都未使用過該點;
  if(dist[i]==maxint)
  {
  prev[i]=0;


  }
  else
  prev[i]=v;//該點前一個點爲起始點//
  }
  dist[v]=0;
  s[v]=1;//第一個點在s集合中//




  //依次將未放入S集合的結點中取dist【】最小的結點放入s中
  //一旦S中包含了所有V中的頂點dist就記錄了從源點到所有其他頂點之間的最短路徑長度
  //注意是從第二個結點開始的第一個爲源結點。//
  for(int i=2;i<=n;i++)
  {
  int tmp =maxint;
  int u =v;
  for (int j=1;j<=n;j++)
  {
  if (!s[j]&&dist[j]<tmp)//如果未訪問過,且距離比最大值小
  {
  u=j;    //u保存當前臨接點中距離最小的編號//
  tmp =dist[j];
  }
  }


  s[u]=1;//將u放入s中;


  //更新數組
  for(int i=1;i<=n;i++)
  {
               //中存放的是當前頂點;要用當前頂點算源點與各個點的距離//
 if (!s[i]&&c[u][i]<maxint)
 {
 int newdst =dist[u]+c[u][i];//上一個節點距離當前節點的值+當前節點離各個點,得到上一個點離該點的距離(途徑當前);
 if (newdst<dist[i])//上一個節點直接到這個節點的距離大於,上一個節點途徑當前節點再到這個節點的距離;那麼就更新;
 {
 dist[i]=newdst;
 prev[i]=u;
 }
 }
  


  }
  }
   }


   void searchPath(int *prev,int v, int u)
   {
  int que[maxnum];
  int tot = 1;
  que[tot] = u;
  tot++;
  int tmp = prev[u];
  while(tmp != v)
  {
  que[tot] = tmp;
  tot++;
  tmp = prev[tmp];
  }
  que[tot] = v;
  for(int i=tot; i>=1; --i)
  if(i != 1)
  cout << que[i] << " -> ";
  else
  cout << que[i] << endl;
   }
發佈了52 篇原創文章 · 獲贊 18 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章