图——最短路径Dijkstra算法

Dijkatra算法解决了从某个源点到其余各顶点的最短路径问题。时间复杂度为O(n^{2})。如果我们还需要知道v3到v5、v1到v7这样任一顶点到其余其他顶点的最短距离,可以对每个顶点当作源点运行一次Dijkstra算法,等于在原有算法的基础上,再来一次循环,此时整个算法的时间复杂度就成了O(n^{3})。Floyd算法就是求所有顶点到所有顶点的算法,算法非常简洁优雅,能让人感觉到智慧的无穷魅力,其时间复杂度就是O(n^{3})

Dijkatra算法所使用到的三个额外数组:

visited[MaxVex]标记数组,visited[w]=1表示已求得V0至Vw的最短路径,0表示还未求得
Distance[MaxVex],用于存储其他顶点到V0的最短距离
pre[MaxVex],用于记录从V0到该顶点的最短路径中,该下标的顶点的前驱顶点下标,通过pre数组可以找到任意顶点到V0的最短路径所经过哪些顶点

Dijkatra算法和Prim算法的相似点与不同点:

两个算法的代码极其相似。Dijkatra算法思想是全局最短,目的是计算出最短路径;Prim算法是局部连接到生成树的权值最小,目的是得到生成树。Prim算法用到两个数组

lowcost[MaxVex],记录未加入生成树的顶点到生成树的最小权值距离min_cost,已加入生成树的权值lowcost=0

adjvex[MaxVex],记录未加入生成树的顶点与生成树相连的最小权值距离的顶点下标

比Dijkatra算法少使用一个visited[MaxVex]标记数组,这是因为Prim算法可以通过lowcost=0标记该顶点已经加入生成树了,不用记录下权值距离,这是因为Prim算法强调最后得到一颗生成树,而Dijkatra算法强调计算出最短路径和最短距离,需要Distance数组记录最短距离。

#include<iostream>
using namespace std;
#define MaxVex 100  //定义最大顶点数
#define Inf 65535  //定义无穷大
typedef char VertexType;  //定义顶点数据类型
typedef int EdgeType;  //定义边上权值数据类型
int visited[MaxVex];  //标记数组,visited[w]=1表示已求得V0至Vw的最短路径,0表示还未求得
int Distance[MaxVex];  //用于存储其他顶点到V0的最短距离
int pre[MaxVex];  //用于记录从V0到该顶点的最短路径中,该下标的顶点的前驱顶点下标,通过pre数组可以找到任意顶点到V0的最短路径所经过哪些顶点
//邻接矩阵存储图的结构
typedef struct Graph
{
	VertexType vex[MaxVex];  //一维数组存储顶点信息
	EdgeType arc[MaxVex][MaxVex];  //二维数组存储边的权值信息,也就是邻接矩阵
	int numVex,numArc;  //记录图中当前顶点数、边数
}MatrixGraph;
//建立无向网图的邻接矩阵表示
void CreateMatrixGraph(MatrixGraph *G)
{
	int i,j,k,weight;
	//输入顶点数和边数
	cin>>G->numVex>>G->numArc;
	//输入顶点信息,建立顶点表
	for(i=0;i<G->numVex;i++)
		cin>>G->vex[i];
	//初始化邻接矩阵
	for(i=0;i<G->numVex;i++)
		for(j=0;j<G->numVex;j++)
			G->arc[i][j]=Inf;
	//输入边信息,建立邻接矩阵
	for(k=0;k<G->numArc;k++)
	{
		cin>>i>>j>>weight;
		G->arc[i][j]=weight;
		G->arc[j][i]=G->arc[i][j];  //无向图,矩阵对称
	}
}
void Dijkstra(MatrixGraph G,int v0)
{
	int i,j,min_vex,min_Distance;
	//初始化visited、Distance、pre三个数组
	for(i=0;i<G.numVex;i++)
	{
		visited[i]=0;  //初始化visited数组为0,表示还未求得V0到其他顶点的最短路径
		Distance[i]=G.arc[v0][i];  //用于存储其他顶点到V0的最短距离
		pre[i]=0;  //初始化数组pre为0,还未求得顶点的最短路径
	}
	Distance[v0]=0;  //v0到v0的距离为0
	visited[v0]=1;  //已求得v0的最短路径
	//开始主循环,循环numVex-1次,找到除v0外其他顶点到v0的最短路径,每次循环求得一个顶点的最短路径
	for(i=1;i<G.numVex;i++)
	{
		min_Distance=Inf;
		//寻找离v0最近的点min_vex,v0到min_vex最短距离为min_Distance
		for(j=0;j<G.numVex;j++)
		{
			if(!visited[j] && Distance[j]<min_Distance)
			{
				min_vex=j;
				min_Distance=Distance[j];
			}
		}
		visited[min_vex]=1;  //已找到min_vex到v0的最短距离,标记为1
        //因为min_vex到v0的最短路径已经找到,可以计算出与min_vex相邻顶点到v0的最短路径和最短距离
		for(j=0;j<G.numVex;j++)
		{
			if(!visited[j] && (min_Distance+G.arc[min_vex][j]<Distance[j]))
			{
				Distance[j]=min_Distance+G.arc[min_vex][j];
				pre[j]=min_vex;
			}
		}
	}
}
int main()
{
	//邻接矩阵法创建图并用Dijkstra算法求最短路径
	MatrixGraph G;
	CreateMatrixGraph(&G);
	int v0=0,v3=3,k;
	Dijkstra(G,v0);
	//打印v0到v3的最短距离
    cout<<Distance[v3]<<endl;
	k=v3;
	//打印v0到v3的最短路径
	cout<<G.vex[v3];
	while(pre[k]!=0)
	{
		cout<<G.vex[pre[k]];
		k=pre[k];
	}
	cout<<G.vex[pre[k]];
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值