最短路徑(Dijskra算法)

聲明:圖片及內容基於:https://www.bilibili.com/video/BV16C4y1H7Zc?from=articleDetailios

最短路徑

Dijkstra算法

原理

 

數據結構

核心代碼

findMinDist()算法

int MGraph::findMinDist(){ int length=INFINIT; for(int i=0;i<vertexNum;i++){ if(s[i]==0){ if(length>dist[i]&&dist[i]!=0&&dist[i]!=INFINIT){ length=i;   //注意記錄的是下標,我原來寫成length=dist[i]了,太慘了 
 } } } return length; }

displayPath()數組

void MGraph::displayPath(){            //打印最短路徑 
    for(int i=0;i<vertexNum;i++){ if(i==startV) cout<<i<<endl;   //起點直接打印 
        if(i!=startV){                 //其餘結點 
            int tmp=i; stack<int> s;              //逆序輸出使用棧 
            while(tmp!=startV){ s.push(path[tmp]); tmp=path[tmp]; } while(!s.empty()){ cout<<s.top()<<"->"; s.pop(); } cout<<i; cout<<endl; } } }

Dijkstra(int startV)數據結構

void MGraph::Dijkstra(int startV){ this->startV=startV;            //別忘了,startV也是MGraph的數據成員 
    for(int i=0;i<vertexNum;i++){ dist[i]=arc[startV][i];     //dist數組初始化 
        
        if(dist[i]!=INFINIT)        //path數組初始化 
            path[i]=startV; else path[i]=-1; } for(int i=0;i<vertexNum;i++)    //s數組初始化 
        s[i]=0; s[startV]=1;                    //startV放入集合 
    int num=1;                      //集合數據個數1 
    while(num<vertexNum){ int min=findMinDist();      //min是當前dist數組中最短路徑的下標,前提是s[i]=0,即查找的 //是集合的補集元素 
        s[min]=1;                   //min放入集合 
        for(int i=0;i<vertexNum;i++){      //更新dist和path數組 
            if(s[i]==0&&(dist[i]>dist[min]+arc[min][i])){ dist[i]=dist[min]+arc[min][i]; path[i]=min; } } num++; } displayPath(); //顯示所有最短路徑 
}

完整代碼

#include<iostream>
#define MAX 50
#define INFINIT 65535 #include <stack>
using namespace std; class MGraph{ private: int vertexNum,arcNum;    //頂點數,邊數
        int arc[MAX][MAX];       //鄰接矩陣 
        int vertex[MAX];  //頂點信息 
        int dist[MAX];      //記錄單源到每一個點的最短路徑的長度 
        int path[MAX];      //記錄當前從某點到某點的最短路徑,存放的是某點起點的頂點信息 
        int s[MAX];         //記錄已經肯定的最短路徑的結點集合 
        int startV; public: MGraph(int v[],int n,int e); void display(); void Dijkstra(int startV); int findMinDist(); void displayPath(); void displayDistPathS(); }; void MGraph::displayDistPathS(){ cout<<"dist:"<<endl; for(int i=0;i<vertexNum;i++){ cout<<dist[i]<<" "; } cout<<endl; cout<<"path:"<<endl; for(int i=0;i<vertexNum;i++){ cout<<path[i]<<" "; } cout<<endl; cout<<"S:"<<endl; for(int i=0;i<vertexNum;i++){ cout<<s[i]<<" "; } cout<<endl; } MGraph::MGraph(int v[],int n,int e){   //n是頂點數,e是邊數
    vertexNum=n; arcNum=e; for(int i=0;i<vertexNum;i++){ vertex[i]=v[i]; } for(int i=0;i<arcNum;i++){        //初始化鄰接矩陣 
        for(int j=0;j<arcNum;j++){ if(i==j) arc[i][j]=0; else arc[i][j]=INFINIT; } } int vi,vj,w; for(int i=0;i<arcNum;i++){ cout<<"請輸入有向邊的兩個頂點和這條邊的權值"<<endl; cin>>vi>>vj>>w;   //輸入邊依附的兩個頂點的編號 和權值 
        arc[vi][vj]=w; //有邊標誌 
 } } void MGraph::display(){ cout<<"鄰接矩陣:"<<endl; for(int i=0;i<vertexNum;i++){ for(int j=0;j<vertexNum;j++){ if(arc[i][j]==INFINIT) cout<<""<<"\t"; else cout<<arc[i][j]<<"\t"; } cout<<endl; } cout<<endl; cout<<"結點信息:"<<endl; for(int i=0;i<vertexNum;i++){ cout<<vertex[i]<<" "; } cout<<endl; } int MGraph::findMinDist(){ int length=INFINIT; for(int i=0;i<vertexNum;i++){ if(s[i]==0){ if(length>dist[i]&&dist[i]!=0&&dist[i]!=INFINIT){ length=i;   //注意記錄的是下標,我原來寫成length=dist[i]了,太慘了 
 } } } return length; } void MGraph::displayPath(){            //打印最短路徑 
    for(int i=0;i<vertexNum;i++){ if(i==startV) cout<<i<<endl;   //起點直接打印 
        if(i!=startV){                 //其餘結點 
            int tmp=i; stack<int> s;              //逆序輸出使用棧 
            while(tmp!=startV){ s.push(path[tmp]); tmp=path[tmp]; } while(!s.empty()){ cout<<s.top()<<"->"; s.pop(); } cout<<i; cout<<endl; } } } void MGraph::Dijkstra(int startV){ this->startV=startV;            //別忘了,startV也是MGraph的數據成員 
    for(int i=0;i<vertexNum;i++){ dist[i]=arc[startV][i];     //dist數組初始化 
        
        if(dist[i]!=INFINIT)        //path數組初始化 
            path[i]=startV; else path[i]=-1; } for(int i=0;i<vertexNum;i++)    //s數組初始化 
        s[i]=0; s[startV]=1;                    //startV放入集合 
    int num=1;                      //集合數據個數1 
    while(num<vertexNum){ int min=findMinDist();      //min是當前dist數組中最短路徑的下標,前提是s[i]=0,即查找的 //是集合的補集元素 
        s[min]=1;                   //min放入集合 
        for(int i=0;i<vertexNum;i++){      //更新dist和path數組 
            if(s[i]==0&&(dist[i]>dist[min]+arc[min][i])){ dist[i]=dist[min]+arc[min][i]; path[i]=min; } } num++; } displayPath(); //顯示所有最短路徑 
} int main(){ int n,e; int v[MAX]; cout<<"請輸入頂點數和邊數"<<endl; cin>>n>>e; cout<<"請輸入頂點信息"<<endl; for(int i=0;i<n;i++){ cin>>v[i]; } cout<<"請輸入起點:"<<endl; int t; cin>>t; MGraph mgraph(v,n,e); mgraph.display(); mgraph.Dijkstra(t); mgraph.displayDistPathS(); return 0; }

 

輸入:ide

7 12
0 1 2 3 4 5 6
0
0 1 4
0 2 6
0 3 6
1 2 1
1 4 7
2 4 6
2 5 4
3 2 2
3 5 5
4 6 6
5 4 1
5 6 8this

輸出:spa

鄰接矩陣:
0 4  6  6 ∞  ∞ ∞
∞ 0 1  ∞ 7  ∞ ∞
∞ ∞ 0 ∞ 6  4 ∞
∞ ∞ 2 0 ∞  5 ∞
∞ ∞ ∞ ∞ 0  ∞ 6
∞ ∞ ∞ ∞ 1  0 8
∞ ∞ ∞ ∞ ∞ ∞ 03d

結點信息:
0 1 2 3 4 5 6
0
0->1
0->1->2
0->3
0->1->4
0->1->2->5
0->1->4->6
dist:
0 4 5 6 11 9 17
path:
0 0 1 0 1 2 4
S:
1 1 1 1 1 1 1code

相關文章
相關標籤/搜索