图之有权最短路径-迪杰斯特拉

采用邻接矩阵表示图,5点有权图如下:


参考书目《数据结构与算法分析(C语言描述)》

1.Dijkstra算法,用于解决单源最短有权路径问题,它和无权最短路径算法一样,按阶段进行。在每个阶段,选择一个顶点v,它在所有未知顶点中具有最小的d,同时算法声明,从s到v的最短路径是已知的。同时对于下个顶点(队列结构储存),需要不断更新最短距离信息,而路径的保存则用不相交ADT来保存路径信息(路径求并)。

//main函数入口

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSIZE 20
#define INFINITY 65535
typedef char VertexType;
typedef struct Graph  //邻接矩阵表示法
{
	VertexType ver[MAXSIZE+1];
	int edge[MAXSIZE][MAXSIZE];
}Graph;
void CreateGraph(Graph *g)
{
	int i=0;
	int j=0;
	int VertexNum;
	VertexType Ver;
	printf("please input the vertex of graph:\n");
	while('\n'!=(Ver=getchar()))
		g->ver[i++]=Ver;
	g->ver[i]='\0';
	VertexNum=strlen(g->ver);
	printf("input adjacency matrix of matrix:\n");
	for(i=0;i<VertexNum;i++)
	{
		for(j=0;j<VertexNum;j++)
			scanf("%d",&g->edge[i][j]);
	}
}
void PrintGraph(Graph G)
{
	int i,j;
	int VertexNum=strlen(G.ver);
	printf("vertex of graph:\n");
	for(i=0;i<VertexNum;i++)
		printf("%c",G.ver[i]);
	printf("\n");
	printf("adjacency matrix of graph:\n");
	for(i=0;i<VertexNum;i++)
	{
		for(j=0;j<VertexNum;j++)
			printf("%d",G.edge[i][j]);
		printf("\n");
	}
}
int CalVerNum(Graph G)
{
	return strlen(G.ver);
}
void SetWeight(Graph *g)  //不邻接点设置无穷大
{
	int i,j;
	for(i=0;i<CalVerNum(*g);i++)
		for(j=0;j<CalVerNum(*g);j++)
		{
			if(0==g->edge[i][j])
				g->edge[i][j]=INFINITY;
		}
}
void Dijkstra(Graph g,int first,int end)
{
	int VertexNum=CalVerNum(g);
	int i,j,k,mini;
	int *used=(int *)malloc(sizeof(int)*VertexNum);  //动态申请内存 由于数组小标必须为常量 这里为变量
	int *distance=(int *)malloc(sizeof(int)*VertexNum);
	int *parent=(int *)malloc(sizeof(int)*VertexNum);
	SetWeight(&g);
	for(i=0;i<VertexNum;i++)
	{
		used[i]=0;
		distance[i]=g.edge[0][i];
		parent[i]=0;
	}
	used[0]=1;
	for(i=0;i<VertexNum-1;i++)
	{
		j=0;
		mini=INFINITY;
		for(k=0;k<VertexNum;k++)
			if((0==used[k])&&(distance[k]<mini))
			{
				mini=distance[k];
				j=k;
			}
		used[j]=1;
		for(k=0;k<VertexNum;k++)
			if((0==used[k])&&(distance[k]>distance[j]+g.edge[j][k]))
			{
				distance[k]=distance[j]+g.edge[j][k];
				parent[k]=j; //路径求并
			}
	}
	printf("%c to %c the least path:\n",g.ver[first],g.ver[end]);
	i=end;
	while(parent[i]!=0)
	{
		printf("%c",g.ver[parent[i]]);
		i=parent[i];
	}
	printf("\n");
	printf("length of the least path:%d\n",mini);
	free(used);
	free(distance);
	free(parent);
}
int main(void)
{
	int i,j;
	Graph g;
	CreateGraph(&g);
	PrintGraph(g);
	printf("please enter first and end number:\n");//输入起点和终点的顶点序号
	scanf("%d %d",&i,&j);
	Dijkstra(g,i,j);
	return 0;
}

运行测试结果如下:


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
迪杰斯特拉最短路径算法是一种解决有权中单源最短路径问题的算法。它采用贪心策略,以起始点为中心向外层层扩展,直到扩展到终点为止。该算法主要特点是将中的节点集分为最短路径计算完成的节点集S和未计算完成的节点集T,每次将从T中挑选V0->Vt最小的节点Vt加入S,并更新V0经由Vt到T中剩余节点的更短距离,直到T中的节点全部加入S中。迪杰斯特拉算法只支持非负权,它计算的是单源最短路径,即单个源点到剩余节点的最短路径,时间复杂度为O(n²)。 以下是迪杰斯特拉最短路径算法的具体步骤: 1. 初始化:将起始点s加入S集合,将与s直接相连的节点的距离加入dis数组,将其余节点的距离设为无穷大。 2. 重复执行以下步骤,直到T集合为空: a. 从dis数组中选择值最小的节点v,将其加入S集合。 b. 更新dis数组:对于T集合中的每个节点w,如果存在一条从v到w的边,则计算出v到w的距离,并将其与原有距离进行比较,如果更小则更新dis数组中w的值。 3. 得到起始点s到各个节点的最短路径。 以下是Python实现迪杰斯特拉最短路径算法的代码示例: ```python import sys def dijkstra(graph, start): # 初始化 dis = {node: sys.maxsize for node in graph} # 距离数组 dis[start] = 0 S = set() # 最短路径节点集合 T = set(graph.keys()) # 未计算最短路径节点集合 while T: # 选择距离起点最近的节点 v = min(T, key=lambda node: dis[node]) S.add(v) T.remove(v) # 更新距离数组 for w in graph[v]: if dis[w] > dis[v] + graph[v][w]: dis[w] = dis[v] + graph[v][w] return dis # 测试 graph = { 'A': {'B': 5, 'C': 1}, 'B': {'A': 5, 'C': 2, 'D': 1}, 'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8}, 'D': {'B': 1, 'C': 4, 'E': 3, 'F': 6}, 'E': {'C': 8, 'D': 3}, 'F': {'D': 6} } start = 'A' print(dijkstra(graph, start)) # 输出:{'A': 0, 'B': 3, 'C': 1, 'D': 4, 'E': 7, 'F': 10} ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值