/*
非负权值的单源最短路径(有向)
dijkstra算法为贪心算法,每个阶段总是选取当前状态下的最优解,
当得到当前状态下的最优点(最短距离)i时,该点即为终点i的最短距离,因为如果走其他点,必定大于当前距离。
*/
#include<iostream>
#include<stack>
using namespace std;
const int INF=0XFFFF;//最大值,表示两点之间无穷远,没有路径可达
const int N=100;
void insert(int a[][N],int i,int j,int w){
a[i][j]=w;
}
void printf_dijkstra(int path[],int end_v){
stack<int> ss;//辅助栈,用于输出
int i=end_v;
if(path[i]==-1){
cout<<"到达不了"<<endl;
return;
}
while(path[i]!=-1){
ss.push(i);
i=path[i];
}
ss.push(i);
while(!ss.empty()){
cout<<ss.top()<<" ";
ss.pop();
}
cout<<endl;
}
int* dijkstra(int a[][N],int n,int start_v,int end_v){
bool s[N]; //每往该集合添加 i 顶点,表示得到以 i 为终点的路径
int dist[N]; //记录以原点 start_v,以顶点 i 为终点的当前最短距离
static int path[N]; //存放路径 path[i] 为 i 的前一个顶点
for(int i=0;i<n;i++){
path[i]=-1;
s[i]=false;
dist[i]=a[start_v][i];
if(i!=start_v&&a[start_v][i]<INF){
path[i]=start_v;
}
}
s[start_v]=true;
for(int i=0;i<n-1;i++){
int min=INF;int u=start_v; //注意:这里有必要 u = v ,因为可能其他路径为 INF 。 s[u]=true;
for(int j=0;j<n;j++){
if(!s[j]&&dist[j]<min&&dist[j]<INF){ //注意:这里有必要dist[j]<INF,理由同上 ,逻辑上若不通的路其他条件不必判断。
min=dist[j];
u=j;
}
}
s[u]=true;
//更新 dist[] ,由于 u 加入集合 s,主要判断其他终点到原点的距离 有没受 u 加入集合后的影响
for(int k=0;k<n;k++){
int w=a[u][k];
if(!s[k]&&w<INF&&dist[u]+w<dist[k]){ //注意这里也有必要 w<INF,逻辑上若不通的路就不必再判断,后面dist[u]也以防溢出
dist[k]=dist[u]+w;
path[k]=u;
}
}
}
return path;
}
int main(){
int start_v,end_v;
int a[N][N];
int n;
cout<<"请输入矩阵大小n=5:";
cin>>n;
//初始化图
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i==j)a[i][j]=0;
a[i][j]=INF;
}
}
insert(a,0,1,10);insert(a,0,3,30);insert(a,0,4,100);
insert(a,1,2,50);
insert(a,2,4,10);
insert(a,3,2,20);insert(a,3,4,60);
cout<<"请输入初始顶点start_v,如0:";
cin>>start_v;
cout<<"请输入结束顶点end_v,如4:";
cin>>end_v;
int* path=dijkstra(a,n,start_v,end_v);
printf_dijkstra(path,end_v);
}
dijkstra算法
最新推荐文章于 2024-06-06 20:23:22 发布