Dijkstra算法数据结构c语言

Dijstra算法是一种用于解决带权图中单源最短路径问题的贪心算法,也就是说,给定一个图和一个源节点,该算法会找到从源节点到图中所有其它节点的最短路径
以下是Dijkstra算法的计本步骤
1.初始化
创建一个距离数组dlist[],其中dlist[i]表示从源节点到节点i的当前已知最短距离,
开始是,将所有距离设置为无穷大,除了源节点,其距离设置为0
创建一个已访问节点的集合,开始时该集合为空
2.迭代
在所有未访问的节点中,选择距离最小的节点u(即dilist[u]的值最小)
将节点u添加到已访问节点的集合中。对于与节点相邻的每个节点v,检查是否可以通过u找到一个更短的路径到v1,换句话说,如果dlist[u]+weight(u,v)(即从源节点到u的距离加上从u到v的边的权重)小于dlist[v],则更新dlist[v]的值为dlist[u]+weight(u,v);重复上述步骤,直到所有节点都被访问过
3.结果
当算法完成时,dlist[]数组将包括从源节点到图中所有其它节点的最短路径

需要注意的是,Dijkstra算法不能用于包含负权边的图,因为负权边可能会导致算法给出错误的结果


#include<stdio.h>
#include<stdlib.h>
#define MAXV 100//定义图中最多能有的顶点数量
#define INF 1000//定义无穷大值,用于表示两个顶点之间没有直接的边
typedef struct
{
	int edgs[MAXV][MAXV];//邻接矩阵,存储边的权重
	int n, e;//顶点的数量和边的数量
}MatGraph;//定义图的结构体
//一般会写一个函数DisPath用于打印路径,这里写在Dijkstra里
void Create(MatGraph *G)//创建一个图
{
	int i, j, w;
	//读取顶点数量和边的数量
	scanf("%d %d", &G->n, &G->e);
	//初始化邻接矩阵,所有边都设置为无穷大
	for (i = 0; i < G->n; i++)
	{
		for ( j = 0; j < G->n; j++)
		{
			G->edgs[i][j] = INF;
		}
	}
	//读取每一条边的起点。终点和权重,并更新邻接矩阵
	for (int p= 0; p < G->e; p++)
	{
		scanf("%d %d %d", &i, &j, &w);
		G->edgs[i][j] = w;//注意:在无向图中,你可能还需设置G->edgs[j][i]=w;
	}
}
//使用Dijkstra算法计算从顶点v到所有其它顶点的最短路径
void Dijkstra(MatGraph* G, int v)//v指的是起点
{
	int visited[MAXV];//标记顶点是否已被访问
	int path[MAXV];//存储最短路径的前一个顶点
	int dist[MAXV];//存储从起点到每个顶点的最短路径
	int u, Max;
	//初始化距离和路径数组
	for (int i = 0; i < G->n; i++)
	{
		dist[i] = G->edgs[v][i];
		visited[i] = 0;
		if (G->edgs[v][i] != INF)
		{
			path[i] = v;
		}
		else
		{
			path[i] = -1;//初始化为-1,表示没有路径
		}
	}
	//将起点标记为已访问,并将其距离设置为0,但在此代码中已经设置为起点到自身的权重
	visited[v] = 1;
	//遍历n-1遍,每次找到未访问的顶点中距离最短的顶点
	for (int i = 0; i < G->n - 1; i++)
	{
		Max = INF;
		for (int j = 0; j < G->n; j++)
		{
			if (visited[j] == 0 && dist[j] < Max)
			{
				Max = dist[j];
				u = j;
			}
		}
		visited[u] = 1;//将找到的点标记为已访问
		for (int j = 0; j < G->n; j++)
		{//更新从起点到所有未访问顶点的距离
			if (visited[j] == 0&& dist[j] >G->edgs[u][j] + dist[u])
			{
				dist[j] = G->edgs[u][j] + dist[u];
				path[j] = u;//更新最短路径的前一个顶点
			}
		}
	}
	//打印从起点到每个可达顶点的最短距离和路径
	int d = 0;
	int k = 0;
	int apath[MAXV];
	for (int i = 0; i < G->n; i++)
	{
		if (visited[i]==1&&i!=v)
		{
			printf("%d到顶点%d的距离为%d\t路径如下:",v ,i, dist[i]);
			d = 0; apath[d] = 0;
			k = i;
			while (k != v)
			{
				apath[++d] = k;
				k = path[k];
			}
			printf("%d", v);
			for (int j = d; j >= 1; j--)
			{
				printf(",%d", apath[j]);
			}
			printf("\n");


		}//说明是被选过的,如果是自
	}
}
int main()
{
	MatGraph G;
	Create(&G);
	Dijkstra(&G, 0);
	return 0;
}


下面是运行结果,这里有一个孤立点.

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值