dijkstra算法

/*
	非负权值的单源最短路径(有向)
	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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值