單源最短路徑的迪克斯特拉(Dijkstra)演算法的改進
阿新 • • 發佈:2019-02-07
Dijkstra演算法
1.定義概覽
Dijkstra(迪傑斯特拉)演算法是典型的單源最短路徑演算法,用於計算一個節點(節點需為源點)到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。Dijkstra演算法是很有代表性的最短路徑演算法,注意該演算法要求圖中不存在負權邊。
例項:假設有A,B,C,D四個城市,(這裡討論的是有向網) 它們的距離為: A->B(10),A->C(11),B->D(12),C->D(13);
所謂単源路徑就是解決從源點 A開始找出到其他城市的最短距離(除本身外的其他所有城市)。Dijkstra演算法可以求出A->B(10),A->C(11),A->D(22);
拓展2:多源最短路徑(常用Floyd演算法)是解決任意兩點間的最短路徑的一種演算法,(不侷限於從源點出發,到其他各個頂點 )可以正確處理有向圖或負權的最短路徑問題,同時也被用於計算有向圖的傳遞閉包。Floyd演算法的時間複雜度為O(N3),空間複雜度為O(N2)。
圖的建立:
dijkstra演算法:void createGraph(tnode t){ cout<<"輸入頂點和邊數:"<<endl; cin>>t->v>>t->e; cout<<"輸入頂點資訊:"<<endl; for(int i = 1;i<=t->v;i++){ cin>>t->vex[i]; } for(int i = 1;i<=t->v;i++){ for(int j = 1;j<=t->v;j++){ t->wei[i][j] = LIMITLESS; } } cout<<"輸入兩連線點下標和權值:"<<endl; int k1,k2,weight; for(int i = 1;i<=t->e;i++){ cin>>k1>>k2>>weight; t->wei[k1][k2] = weight; } } void printGraph(tnode t){ for(int i = 1;i<=t->v;i++){ for(int j = 1;j<=t->v;j++){ if(t->wei[i][j]!=LIMITLESS){ cout<<t->wei[i][j]<<" "; } else{ cout<<"oo"<<" "; } } cout<<endl; } }
完整程式碼:void dijkstra(tnode t,int sour){ bool s[MAX_NUM]; //標識 int dist[MAX_NUM]; //源點到頂點距離 int prev[MAX_NUM] = {0}; //頂點的前置頂點 for(int i = 1;i<=t->v;i++){ dist[i] = t->wei[sour][i]; //記錄從源點到各頂點的路徑長 s[i] = false; //初始化標識陣列 if(dist[i]!=LIMITLESS){ //若源點到頂點的距離不為空,則將源點置為頂點的前置點 prev[i] = sour; } else{ prev[i] = 0; //0表示前置節點不存在 } } dist[sour] = 0,s[sour] = true; for(int i = 1;i<t->v;i++){ int item = LIMITLESS; int flag = sour; for(int j = 1;j<=t->v;j++){ //找到距源點距離最小且未被標識過的頂點 if(!s[j]&&dist[j]<item){ flag = j; item = dist[j]; } } s[flag] = true; for(int i = 1;i<=t->v;i++){ //從上面找到的頂點向其它頂點探索,優化源點到其他頂點的距離 if(!s[i]&&t->wei[flag][i]<LIMITLESS){ int newdist = dist[flag]+t->wei[flag][i]; if(newdist<dist[i]){ //其它頂點距離更新 dist[i] = newdist; prev[i] = flag; } } } } stack<int> ss[MAX_NUM]; //棧實現列印路徑構建 for(int i = 1;i<=t->v;i++){ cout<<"\n源點到頂點"<<i<<"的最短距離為:"<<dist[i]; cout<<",最短路徑構建為:"<<endl; int p = prev[i]; if(!p){ cout<<"源點到自身路徑構建為空!"<<endl; }else{ while(p){ ss[i].push(p); p = prev[p]; } while(!ss[i].empty()){ int k = ss[i].top(); cout<<k; ss[i].pop(); if(!ss[i].empty()){ cout<<"->"; } } if(i!=sour) cout<<"->"<<i; //頂點自身值列印 } }
/**
@單源最短路徑(dijkstra演算法)
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stack>
#define MAX_NUM 50
#define LIMITLESS 65535
using namespace std;
typedef struct Tnode{
int v,e;
int vex[MAX_NUM];
int wei[MAX_NUM][MAX_NUM];
}Tnode,*tnode;
void createGraph(tnode t){
cout<<"輸入頂點和邊數:"<<endl;
cin>>t->v>>t->e;
cout<<"輸入頂點資訊:"<<endl;
for(int i = 1;i<=t->v;i++){
cin>>t->vex[i];
}
for(int i = 1;i<=t->v;i++){
for(int j = 1;j<=t->v;j++){
t->wei[i][j] = LIMITLESS;
}
}
cout<<"輸入兩連線點下標和權值:"<<endl;
int k1,k2,weight;
for(int i = 1;i<=t->e;i++){
cin>>k1>>k2>>weight;
t->wei[k1][k2] = weight;
}
}
void printGraph(tnode t){
for(int i = 1;i<=t->v;i++){
for(int j = 1;j<=t->v;j++){
if(t->wei[i][j]!=LIMITLESS){
cout<<t->wei[i][j]<<" ";
}
else{
cout<<"oo"<<" ";
}
}
cout<<endl;
}
}
void dijkstra(tnode t,int sour){
bool s[MAX_NUM]; //標識
int dist[MAX_NUM]; //源點到頂點距離
int prev[MAX_NUM] = {0}; //頂點的前置頂點
for(int i = 1;i<=t->v;i++){
dist[i] = t->wei[sour][i]; //記錄從源點到各頂點的路徑長
s[i] = false; //初始化標識陣列
if(dist[i]!=LIMITLESS){ //若源點到頂點的距離不為空,則將源點置為頂點的前置點
prev[i] = sour;
}
else{
prev[i] = 0; //0表示前置節點不存在
}
}
dist[sour] = 0,s[sour] = true;
for(int i = 1;i<t->v;i++){
int item = LIMITLESS;
int flag = sour;
for(int j = 1;j<=t->v;j++){ //找到距源點距離最小且未被標識過的頂點
if(!s[j]&&dist[j]<item){
flag = j;
item = dist[j];
}
}
s[flag] = true;
for(int i = 1;i<=t->v;i++){ //從上面找到的頂點向其它頂點探索,優化源點到其他頂點的距離
if(!s[i]&&t->wei[flag][i]<LIMITLESS){
int newdist = dist[flag]+t->wei[flag][i];
if(newdist<dist[i]){ //其它頂點距離更新
dist[i] = newdist;
prev[i] = flag;
}
}
}
}
stack<int> ss[MAX_NUM]; //棧實現列印路徑構建
for(int i = 1;i<=t->v;i++){
cout<<"\n源點到頂點"<<i<<"的最短距離為:"<<dist[i];
cout<<",最短路徑構建為:"<<endl;
int p = prev[i];
if(!p){
cout<<"源點到自身路徑構建為空!"<<endl;
}else{
while(p){
ss[i].push(p);
p = prev[p];
}
while(!ss[i].empty()){
int k = ss[i].top();
cout<<k;
ss[i].pop();
if(!ss[i].empty()){
cout<<"->";
}
}
if(i!=sour) cout<<"->"<<i; //頂點自身值列印
}
}
}
int main(){
Tnode t;
createGraph(&t);
cout<<"構建的圖為:"<<endl;
printGraph(&t);
cout<<"dijkstra演算法構建的頂點最短路徑為:"<<endl;
dijkstra(&t,1);
return 0;
}
/*
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60
*/