資料結構:點對之間最短距離--Floyd演算法,短距離--floyd

來源:互聯網
上載者:User

資料結構:點對之間最短距離--Floyd演算法,短距離--floyd

                           Floyd演算法

Floyd演算法

    Dijkstra演算法是用於解決單源最短路徑問題的,Floyd演算法則是解決點對之間最短路徑問題的。Floyd演算法的設計策略是動態規劃,而Dijkstra採取的是貪心策略。當然,貪心演算法就是動態規劃的特例。

演算法思想

    點對之間的最短路徑只會有兩種情況:

Min_Distance(Vi,Vj)=min{weight(Vi,Vj),weight(Vi,Vv)+weight(Vv,Vj)}。正是基於這種背後的邏輯,再加上動態規劃的思想,構成了Floyd演算法。故當Vv取完所有頂點後,Distance(Vi,Vj)即可達到最小。Floyd演算法的起點就是圖的鄰接矩陣。
題外話:代碼本身不重要,演算法思想才是精髓。思想極難得到,而有了思想,稍加經驗即可寫出代碼。向思想的開創者致敬!
思想很難,代碼卻比較簡單,直接上代碼代碼類定義
#include<iostream>  #include<iomanip>#include<stack>using namespace std;#define MAXWEIGHT 100#undef INFINITY#define INFINITY 1000class Graph{private://頂點數  int numV;//邊數  int numE;//鄰接矩陣  int **matrix;public:Graph(int numV);//建圖  void createGraph(int numE);//析構方法  ~Graph();//Floyd演算法void Floyd();//列印鄰接矩陣  void printAdjacentMatrix();//檢查輸入  bool check(int, int, int);};
類實現
//建構函式,指定頂點數目Graph::Graph(int numV){//對輸入的頂點數進行檢測while (numV <= 0){cout << "頂點數有誤!重新輸入 ";cin >> numV;}this->numV = numV;//構建鄰接矩陣,並初始化matrix = new int*[numV];int i, j;for (i = 0; i < numV; i++)matrix[i] = new int[numV];for (i = 0; i < numV; i++)for (j = 0; j < numV; j++){if (i == j)matrix[i][i] = 0;elsematrix[i][j] = INFINITY;}}void Graph::createGraph(int numE){/*對輸入的邊數做檢測一個numV個頂點的有向圖,最多有numV*(numV - 1)條邊*/while (numE < 0 || numE > numV*(numV - 1)){cout << "邊數有問題!重新輸入 ";cin >> numE;}this->numE = numE;int tail, head, weight, i;i = 0;cout << "輸入每條邊的起點(弧尾)、終點(弧頭)和權值" << endl;while (i < numE){cin >> tail >> head >> weight;while (!check(tail, head, weight)){cout << "輸入的邊不正確!請重新輸入 " << endl;cin >> tail >> head >> weight;}matrix[tail][head] = weight;i++;}}Graph::~Graph(){int i;for (i = 0; i < numV; i++)delete[] matrix[i];delete[]matrix;}/*弗洛伊德演算法求各頂點對之間的最短距離及其路徑*/void Graph::Floyd(){//為了不修改鄰接矩陣,多用一個二維數組int **Distance = new int*[numV];int i, j;for (i = 0; i < numV; i++)Distance[i] = new int[numV];//初始化for (i = 0; i < numV; i++)for (j = 0; j < numV; j++)Distance[i][j] = matrix[i][j];//prev數組int **prev = new int*[numV];for (i = 0; i < numV; i++)prev[i] = new int[numV];//初始化prevfor (i = 0; i < numV; i++)for (j = 0; j < numV; j++){if (matrix[i][j] == INFINITY)prev[i][j] = -1;elseprev[i][j] = i;}int d, v;for (v = 0; v < numV; v++)for (i = 0; i < numV; i++)for (j = 0; j < numV; j++){d = Distance[i][v] + Distance[v][j];if (d < Distance[i][j]){Distance[i][j] = d;prev[i][j] = v;}}//列印Distance和prev數組cout << "Distance..." << endl;for (i = 0; i < numV; i++){for (j = 0; j < numV; j++)cout << setw(3) << Distance[i][j];cout << endl;}cout << endl << "prev..." << endl;for (i = 0; i < numV; i++){for (j = 0; j < numV; j++)cout << setw(3) << prev[i][j];cout << endl;}cout << endl;//列印頂點對最短路徑stack<int> s;for (i = 0; i < numV; i++){for (j = 0; j < numV; j++){if (Distance[i][j] == 0);else if (Distance[i][j] == INFINITY)cout << "頂點 " << i << " 到頂點 " << j << " 無路徑!" << endl;else{s.push(j);v = j;do{v = prev[i][v];s.push(v);} while (v != i);//列印路徑cout << "頂點 " << i << " 到頂點 " << j << " 的最短路徑長度是 "<< Distance[i][j] << " ,其路徑序列是...";while (!s.empty()){cout << setw(3) << s.top();s.pop();}cout << endl;}}cout << endl;}//釋放空間for (i = 0; i < numV; i++){delete[] Distance[i];delete[] prev[i];}delete[]Distance;delete[]prev;}//列印鄰接矩陣  void Graph::printAdjacentMatrix(){int i, j;cout.setf(ios::left);cout << setw(7) << " ";for (i = 0; i < numV; i++)cout << setw(7) << i;cout << endl;for (i = 0; i < numV; i++){cout << setw(7) << i;for (j = 0; j < numV; j++)cout << setw(7) << matrix[i][j];cout << endl;}}bool Graph::check(int tail, int head, int weight){if (tail < 0 || tail >= numV || head < 0 || head >= numV|| weight <= 0 || weight >= MAXWEIGHT)return false;return true;}
主函數
int main(){cout << "******Floyd***by David***" << endl;int numV, numE;cout << "建圖..." << endl;cout << "輸入頂點數 ";cin >> numV;Graph graph(numV);cout << "輸入邊數 ";cin >> numE;graph.createGraph(numE);cout << endl << "Floyd..." << endl;graph.Floyd();system("pause");return 0;}
運行


小結Floyd演算法代碼看似很長,其實並不難。代碼中很多都是用於準備工作和輸出,關鍵代碼就是三層for迴圈。
完整代碼下載:Floyd演算法

轉載請註明出處,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/38366923
若有所協助,頂一個哦!
專欄目錄:
  • 資料結構與演算法目錄
  • c指標


資料結構 最短距離問題

這個是Floyd 演算法 的多點間的最短距離求解問題 你把Floyd 演算法 寫下就可以
void floyd(){
int path[][]=new int[n][n];
int dist[][]=new int[n][n];
for(int i=0;i<n;i++)
for(int j=0;j<nj++){
dist[i][j]=costValue[i][j];
if(i!=j && dist[i][j]<FrameMain,MAXNUM)
path[i][j]=i;
else
path[i][j]=0;
}
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int i=0;j<n;j++)
if( dist[i][k]+dist[k][j]<dist[i][j] ){
dist[i][j]= dist[i][k]+dist[k][j];
path[i][j]=path[k][j];
}
}
 
Floyd演算法思想

演算法描述:
(1) 用數組dis[i][j]來記錄i,j之間的最短距離。初始化dis[i][j],若i=j則dis[i][j]=0,
若i,j之間有邊串連則dis[i][j]的值為該邊的權值,否則dis[i][j]的值為 。
(2) 對所有的k值從1到n,修正任意兩點之間的最短距離,計算dis[i][k]+dis[k][j]的值,
若小於dis[i][j],則dis[i][j]= dis[i][k]+dis[k][j],否則dis[i][j]的值不變。
程式:
void Floyd(int dis[n+1][n+1],int path[n+1][n+1],int n)
{
int i,j,k;
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(dis[i][k]+dis[k][j]<dis[i][j])
{
dis[i][j] = dis[i][k]+dis[k][j];
Path[i][j]=k;
}
}
正確性證明(歸納法) :
對於任意兩點A,B:
(1)當從A到B之間的最短路徑,在中間沒有經過頂點或經過1個頂點號為1的頂點時,演算法顯然正確。
(2)假設A到B經過的最大頂點號不超過k-1時,演算法得到的最短距離是正確的
(3)當A到B經過的最大頂點號為k時,則從A到頂點號為k的頂點v 之間的頂點號均不大於k-1,從v 到B之間的頂點號也不大於k-1,由假設2得,A到vk的距離是中間頂點號不超過k-1的最短距離,vk到B的距離是中間頂點號不超過k-1的最短距離,所以A經vk到B為A,B之間經過最大號為k的路徑中距離最短的,由演算法修正A,B的最短距離,即可得到A,B間頂點號不超過k的最短距離。
(4)綜上所述,演算法是正確的
時間複雜度:O(n3)
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.