迪杰斯特拉算法

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#define inf 65535 //定义无穷大 
using namespace std;
void Dijkstra(int n,int v,int dist[],int pre[],int c[][6]) //n为顶点个数,v代表源点,dist[i]记录每轮下来源点到第i个顶点的最短路径,pre[i]代表到第i个顶点的最短路径中i的上一个顶点的号码,c[][]为邻接矩阵
{
	int s[6];  //s[]为记录每个顶点是否纳入S集合,1代表纳入,0代表不纳入,即s[i]属于V-S 
	for(int i=1;i<=n;i++)//初始化,先让每个节点的s[]都为0,dist[]为与顶点v直接相连的长度,如果没有就为无穷大 
	{
		dist[i]=c[v][i];
		s[i]=0;
		pre[i]=dist[i]!=inf?v:inf;//如果dist[]存在说明顶点i与v有直接通路,那么i的上一个顶点就是v,否则就是无穷大 
	}
	s[v]=1;//源点v肯定是要第一个送到集合S里面的 
	for(int i=1;i<=n-1;i++)//开始迭代,因为有n个顶点,因此一共需要迭代n-1轮 
	{
		int min=inf,minv;//min和minv用于记录每轮dist[]的最小值和最小值对应的那个顶点号 
		for(int j=1;j<=n;j++)//一层循环搞定,就是擂台赛,注意一定要在不属于S的集合里面去寻找!所以要!s[j] 
			if(!s[j]&&dist[j]<min)
			{
				min=dist[j];
				minv=j;
			}
		s[minv]=1;//找到之后把那个最小值对应的顶点纳入S集合 
		for(int j=1;j<=n;j++)//纳入集合之后需要修改剩余各个顶点(即不属于S集合)的 dist[]值,因为还有可能存在更短的路径! 
			if(!s[j]&&dist[minv]+c[minv][j]<dist[j])//如果真的存在的话 
			{
				dist[j]=dist[minv]+c[minv][j];//修改dist[]值 
				pre[j]=minv;//同时也要更新它的上一个顶点,变成minv了 
			}
	}
}
void print(int pre[],int v,int n,int dist[])//知道pre[]了,我想输入最终结果咋办呢?用这个函数实现 
{
	int s[20],top;//定义一个栈,因为最后的输出需要不断的弹栈,所以要建立这样的数据结构 
	for(int j=1;j<=n;j++)//针对顶点1到顶点n 
	{
		int i=j;//因为后面j的值需要变化, 因此让i=j以避免影响for循环! 
		if(pre[i]==inf)//pre[i]=inf说明不通 
			continue;
		else  //如果通的话,先压栈,再弹栈 
		{
			top=0;//初始化栈 
			do//只要最后的i不为源点序号v,说明它的前面一定还有顶点,就不断的压栈,
			{
				s[top++]=i;//压栈操作 
				i=pre[i];//同时i的值也随之改变 
			}while(i!=v);
			cout<<v<<"-->";//下面是输出结果 ,一开始是从v开始 
			while(top!=0)//只要栈不空,就弹栈 
			{
				cout<<s[--top];//弹栈操作 
				if(top!=0)//这里是个小技巧,如果当前顶点不是最后一个顶点,即栈不空,就要输出“-->”这个符号 ,最后一个顶点的后面当然啥符号也没有 
					cout<<"-->";
			}
			cout<<" 距离为"<<dist[j]<<endl;//同时输出最短路径的距离,注意这里输出的是dist[j],不是 dist[i],因为i的值早就发生了变化! 
		}
	}
}

int main()
{
	int c[6][6]={{inf,inf,inf,inf,inf,inf},//我的顶点是从1~5的,因此从0开始的就用inf代替,不影响最后结果 
				 {inf,inf,10,inf,30,100},
				 {inf,inf,inf,50,inf,inf},
				 {inf,inf,inf,inf,inf,10},
				 {inf,inf,inf,20,inf,60},
				 {inf,inf,inf,inf,inf,inf}
				};
	int pre[6],dist[6],n=5;
	Dijkstra(n,1,dist,pre,c);
	print(pre,1,n,dist);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值