最短路径简单实现(Dijkastra算法和Floyd算法)

什么是最短路径:

图中的某一个节点到另外某一个节点的最短路径的权值和,如果是无权值的图,则理解为权值为1的图。

图的邻接矩阵结构:

要计算最短路径,首先需要一个图,这里用邻接矩阵来表示一个图。

typedef char VertexType;        //顶点类型 ,默认为char
typedef int EdgeType;              //边的权值  默认int
#define MAXVERTEX 10          //最大的顶点数    默认为10
#define INFINITY 65535              //表示无尽∞
								   //邻接矩阵的结构
struct MGraph
{
	VertexType vexs[MAXVERTEX];     //顶点数组
	EdgeType arc[MAXVERTEX][MAXVERTEX];    //邻接矩阵  即边数组
	int vertexNum;            //顶点数
	int edgeNum;                 //边数
};

Dijkastra算法:

Dijkastra算法把一个问题分解成小问题的集合,比如要计算V0~V9的最短路径,先计算V0~V1的最短路径,然后到V2,最终计算到V9的最短路径。

typedef int ShortPathWeight[MAXVERTEX];      //存储到各个顶点最短路径的权值
typedef int PathPercursor[MAXVERTEX];     //存储某个顶点最短路径的前驱顶点,如PathPercursor[v8]=7,则到v8的最短路径前一个是v7点

//Dijkastra算法最短路径
void DijkastraShortestPath(MGraph G, int v0, ShortPathWeight *S, PathPercursor *P)
{
	int i, j;  //用于循环
	int min;   //用于记录最短权值来比较
	int k;     //用于记录最小权值顶点下标
	int OverVertex[MAXVERTEX];     //用于记录已经求出最短路径的顶点,当数组值为0表示未求出,当数组值为1表示已经求出
	//初始化要使用的数组
	for (i = 0; i < G.vertexNum; i++)
	{
		OverVertex[i] = 0;     //默认没有求出任何点
		(*S)[i] = G.arc[0][i]; //把邻接矩阵的第一行数据记录到ShortPath数组
		(*P)[i] = 0;           //路径数组初始化为0
	}
	OverVertex[v0] = 1;          //源点V0不需要求,默认1
	(*S)[v0] = 0;              //V0到自身V0距离为0
	//循环遍历每一个顶点,来求出V0到每一个顶点vi的最短路径
	for (i = 1; i < G.vertexNum; i++)        //i从1开始遍历
	{
		//找出ShortPathWeight的最小值
		min = INFINITY;           //默认最小权值为不可能数
		for (j = 0; j < G.vertexNum; j++)
		{
			if (OverVertex[j] != 1 && (*S)[j] < min)   //找出到顶点的最小值
			{
				k = j;
				min = (*S)[j];      //k顶点离源点最近,最小权值为min
			}
		}
		OverVertex[k] = 1;           //把k顶点的标识符设为true
		//在已经找到k顶点为最短路径的基础上,循环寻找与K顶点连接的后面顶点的最短路径
		for (j = 0; j < G.vertexNum; j++)
		{
			//经过K顶点到某一顶点的路径比v0直接到某一顶点的路径短
			if (OverVertex[j] != 1 && (min + G.arc[k][j]) < (*S)[j])
			{
				(*S)[j] = min + G.arc[k][j];
				(*P)[j] = k;
			}
		}
	}
}
用了两个数组分别记录到某点的最短路径权值和前驱顶点,另外内部用一个标识符来表示是否已经求出某点的最短路径。

Floyd算法:

Floyd非常巧妙,它设定了一个中间顶点,比如要计算V0~V2的权值,中间顶点为V1:比较(V0~V2)和(V0~V1+V1~V2)的值,把较小的值记录为最短权值。

typedef int ShortPathWeightMatrix[MAXVERTEX][MAXVERTEX];      //任意顶点到任意顶点最短路径的权值矩阵
typedef int PathPercursorMatrix[MAXVERTEX][MAXVERTEX];       //任意顶点到任意顶点最短路径的前驱顶点矩阵

//Floyd算法最短路径
void FloydShortestPath(MGraph G, ShortPathWeightMatrix *S, PathPercursorMatrix *P)
{
	int i, j, k;  //用于循环
	//初始化数组
	for (i = 0; i < G.vertexNum; i++)
	{
		for (j = 0; j < G.vertexNum; j++)
		{
			(*S)[i][j] = G.arc[i][j];        //把S数组初始化为G的邻接矩阵
			(*P)[i][j] = j;                   //把P数组初始化为0-VertexNum的矩阵,即最短路径前驱为自身
		}
	}
	//三重循环嵌套,k为路径中间经过点
	for (k = 0; k < G.vertexNum; k++)
	{
		for (i = 0; i < G.vertexNum; i++)
		{
			for (j = 0; j < G.vertexNum; j++)
			{
				//找到Vi到Vj的权值大于(Vi~Vk)+(Vk~Vj)的点
				if ((*S)[i][j] > (*S)[i][k] + (*S)[k][j])
				{
					//改变记录的最短路径权值
					(*S)[i][j] = (*S)[i][k] + (*S)[k][j];
					//把某点的最短路径前驱顶点改为K
					(*P)[i][j] = (*P)[i][k];
				}
			}
		}
	}
}

算法的时间复杂度:

Dijkastra算法用了两重嵌套循环,所以时间复杂度为O(n^2);

Floyd算法用了三重嵌套循环,所以时间复杂度为O(N^3)。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值