算法-图论-Dijstra寻找最短路径

Dijstra 算法 寻找最短路径

在图论中,经常要遇到的就是寻找最短路径。今天先学了下Dijstra算法

思想:在加权有向图中,从当前节点出发,寻找邻居节点中路径最短的那条。然后将该节点作为下次出发的节点。如果下次遍历到已经访问的节点,比较从该路径到达此节点的路径长度,更新最短的距离。

实现方法:利用数组A记录下每个节点的到起始节点的最短距离。

                    利用数组B记录下节点是否已经访问过了。此访问与遍历图的访问概念不同。只有遍历完此节点的邻居节点才能算访问结束。

本文的图结构为如下所示:


分析:

本文设置的是从D点开始,也就是索引为3。程序将计算其它节点到该点的最短距离。

从D开始,分析邻居节点,标记A与H到D点的距离,edge(DH)<edge(DA)。将D标记为已访问。

而后从H点开始,标记E与H点,分析到A,E,I中E的currDist值最小。将H标记为已访问。

从E开始,更新A,FcurrDist,待比较的元素为A,F,I,因此又从A开始,以此类推

过程如下:

节点       距离

D          0

A           -1,4

H          -1,1

E          -1,-1,6,5

I            -1,,1,10,10,10,9

F           -1,-1,-1,-1,8,

B           -1,-1,-1,-1,-1,9,

C            -1,-1,-1,-1,-1,11,11,

G            -1,-1,-1,-1,-1,15,15,12

J             -1,-1,-1,-1,-1,-1,11,



代码如下:

void Graph::findPathTest()
{
	int weightGraph[10][10]=
	{
		{0,0,0,0,1,0,0,10,0,0},//A
		{0,0,2,0,0,0,0,0,0,0},//B
		{0,2,0,0,0,0,0,0,0,0},//C
		{4,0,0,0,0,0,0,1,0,0},//D
		{0,0,0,0,0,3,0,0,0,0},//E
		{0,1,3,0,0,0,7,0,1,0},//F
		{0,0,0,0,0,0,0,0,0,0},//G
		{0,0,0,0,5,0,0,0,9,0},//H
		{0,0,0,0,0,0,0,0,0,2},//I
		{0,0,0,0,0,0,1,0,0,0},//J

	};//初始化带权图


	int currDist[10];
	for (int i=0;i<10;i++)
	{
		currDist[i]=-1;
	}
	int nStartNodePos=3;

	//设起始点为d.矩阵的大小为10*10
	DijkstraAlgorithm(weightGraph,nStartNodePos,currDist);
	cout<<endl<<endl<<"各节点到"<<nStartNodePos<<"的最短距离为:"<<endl;
	for (int i=0;i<10;i++)
	{
		cout<<" "<<currDist[i];
	}
}


/************************************************************************/
	/*函数功能:最短路径
	  参数说明:weightGraph 加权有向图
	            startNodePos 开始节点
				currDist 各节点到起始节点的最短路径
	*/
	/************************************************************************/
void Graph::DijkstraAlgorithm( int weightGraph[10][10],int startNodePos,int currDist[10] )
{
	currDist[startNodePos]=0;//起始点的最短路径为0。
	int compare[10];//访问标记,-1为未访问,0为已经访问过了,1代表下次应该访问
	for(int i=0;i<10;i++)
	{
		compare[i]=-1;
	}
	int tempNodeFlag=startNodePos;//当前访问的索引
	int num=0;//计算已经访问的个数
	while(num<10)//当访问的个数<10
	{
		int weightValue=-1;//计算从该点出发的路径最短的点
		for (int i=0;i<10;i++)
		{
			if (weightGraph[tempNodeFlag][i]>0)//保证是未被访问过的节点
			{
				int data=weightGraph[tempNodeFlag][i]+currDist[tempNodeFlag];
				if (currDist[i]==-1)//若还未进行赋值
				{
					currDist[i]=data;
				}
				else if (currDist[i]>data)//若权重更小,则重新赋值
				{
					currDist[i]=data;
				}
				if (compare[i]==-1)
				{
					compare[i]=1;//将数据的索引赋予tempArray。比较的时候从currDist中对应的索引取数据
				}
			}
		}
		compare[tempNodeFlag]=0;//将访问的标志设为true
		num++;//访问节点数目加1
		for (int i=0;i<10;i++)
		{
			if (compare[i]==1)//如果下次应该访问
			{
				if (weightValue==-1)
				{
					weightValue=currDist[i];
					tempNodeFlag=i;
				}
				else if (currDist[i]<weightValue)
				{
					tempNodeFlag=i;//找到最小的那个元素
				}
			}
		}
	}
	//算法分析:复杂度为O(V^2).while执行O(V),分析是否有邻居节点以及是否要比较的元素均为O(V)


运行结果:

小结

             1)结束也可以用是否所有的点的visited都为true判断。

             2)还是标志

            3)各位大牛还多多指教

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值