迪杰斯特拉算法

最短路径问题是指:从在带权图的某一顶点出发,找出一条通向另一顶点的最短路径。这里仅考虑,非负权值的单源路径最短

迪杰斯特拉算法,按路径的递增次序,逐步产生最短路径的算法。首先求出长度最短的一条最短路径,然后参照它求出长度次短的一条最短路径,依次类推,直到从顶点v到其他各顶点的最短路径全部求出为止。

迪杰斯特拉是位计算机大神,大师级人物.

该算法的思想:设定一个最短路径顶点集合,用于标记,每次找到当前最短路径,然后动态查找改变,下一个最短路径次序。

/*
Dijkstra算法:(i,j,k)
1、声明一个访问过结点集,用于标示每次是否被访问,初始化为假,对应已访问顶点集为空。
2、v=0;设置path数组,当此结点未访问,且小于最大值,设置路径为初始结点,
然后初始化当前最短路径数组dest,然后把初始结点设置为已访问过。
3、循环处理:
*/

void Dijkstra(int weight[5][5],int v,int dest[],int path[])
{
	int road[5];
	int i,j ,k;
	bool shortset[5];
	int min;		//记录当前最小,选择一个结点和其他结点连接的最短路
	int u;			//用于记录是否经过u达到最短路径
	int w;			//辅助
	for(i=0;i<5;i++)
	{
		dest[i]=weight[v][i];
		shortset[i]=false;
		if(dest[i]<MaxValue)	//如果有路,则将path数组设置为初始结点
			path[i]=v;
		else
			path[i]=-1;

	}

	shortset[v]=true;
	dest[v]=0;

	for(i=0;i<4;i++)	//循环处理到n-1个结点,里面的操作可以把最后一个结点加入到已访问集中
	{
		min=MaxValue;u=v;	//最新访问的

		for(j=0;j<5;j++)
			if(shortset[j]==false&&dest[j]<min)
			{
				u=j;		//j即为选出的最短路径结点
				min=dest[j];	
			}
		//将此结点加入到最短路径集中
			shortset[u]=true;
			
		for(k=0;k<5;k++)	//动态测试模块:只修改路径,不访问结点
		{
			w=weight[u][k];	//经过u到达其他结点
			if(shortset[k]==false&&w<MaxValue&&dest[u]+w<dest[k])
			{
				//缩短了路径,则把该结点加入到最短路径集中
				dest[k]=dest[u]+w;
		//		shortset[k]=true;	//典型错误:
				path[k]=u;			//类似并查集的索引
			}
		}
	}

	//测试
	cout<<"最短路径数组:"<<endl;
	for(i=0;i<5;i++)
	{
		cout<<dest[i]<<" ";
	}
	cout<<endl;
	cout<<"最短路径序列数组:"<<endl;
	for(i=0;i<5;i++)
	{
		cout<<path[i]<<" ";	
	}
	cout<<endl;
	cout<<"访问控制数组:"<<endl;
	for(i=0;i<5;i++)
	{
		cout<<shortset[i]<<" ";	
	}
	cout<<endl;

	//输出到各顶点的最短路径和最短路径序列
	cout<<"-------测试结果---------------"<<endl;
	for(i=1;i<5;i++)
	{
		cout<<"顶点0到顶点"<<i<<"的最短路径长度为:"<<dest[i]<<endl;
		cout<<"最短路径序列为:"<<endl;
		
		//处理类似数组下标作为索引的数据结构的标准代码
		k=0;
		int j=i;
		while(j>0)
		{
		//	road[k++]=path[j--]; 有纰漏
			road[k++]=j;
			j=path[j];		//顺次调用
		}
		while(k>0)
			cout<<road[--k]<<" ";	//k使用完还加1了,所以应该使用--k
		cout<<endl;
		cout<<endl;
	}

}

主程序:

#define MaxValue 1999999

int _tmain(int argc, _TCHAR* argv[])
{
	int weight[5][5]=				//用矩阵表示有向带权图
	{
		{0,10,MaxValue,30,100},
		{MaxValue,0,50,MaxValue,MaxValue},
		{MaxValue,MaxValue,0,MaxValue,10},
		{MaxValue,MaxValue,20,0,60},
		{MaxValue,MaxValue,MaxValue,MaxValue,0}
	};
	int dest[5];		//记录起始点到各个点的最短路径
	int path[5];		//记录当该顶点经过的顶点次序
	for(int i=0;i<5;i++)	//都初始化为0
	{
		dest[i]=0;
		path[i]=0;
	}
	//经验:典型,重点,难点,勿钻研生僻点
	cout<<"------最短路径之Dijkstra算法------"<<endl;
	void Dijkstra(int weight[5][5],int v,int dest[],int path[]);

	
	//测试
	Dijkstra(weight,0,dest,path);
	

	return 0;
}

测试结果:

------最短路径之Dijkstra算法------
最短路径数组:
0 10 50 30 60
最短路径序列数组:
0 0 3 0 2
访问控制数组:
1 1 1 1 1
-------测试结果---------------
顶点0到顶点1的最短路径长度为:10
最短路径序列为:
1

顶点0到顶点2的最短路径长度为:50
最短路径序列为:
3 2

顶点0到顶点3的最短路径长度为:30
最短路径序列为:
3

顶点0到顶点4的最短路径长度为:60
最短路径序列为:
3 2 4

请按任意键继续. . .

posted @ 2013-05-22 19:22  李VS超  阅读(478)  评论(0编辑  收藏  举报