基于C语言的最短路径--迪杰斯特拉算法

迪杰斯特拉算法(DiJkstra)

如果要从V0到V8,只需要找出V0所在的边的最短路径,然后在再另一个顶点中找出最短的路径,以此类推一直到目标点。

#define INFINITY 65535
#define max 100

//typedef struct  //测试样例
//{
//	char vex[max] = { 'a','b','c','d','e','f','g','h','i' };
//	int link[9][9] = { 0, 1,5,65535,65535,65535,65535,65535,65535,
//							1,0,3,7,5,65535,65535,65535,65535,
//							5,3,0,65535,1,7,65535,65535,65535,
//							65535,7,65535,0,2,65535,3,65535,65535,
//							65535,5,1,2,0,3,6,9,65535,
//							65535,65535,7,65535,3,0,65535,5,65535,
//							65535,65535,65535,3,6,65535,0,2,7,
//							65535,65535,65535,65535,9,5,2,0,4,
//							65535,65535,65535,65535,65535,65535,7,4,0}; // 测试样例
//	int vexnum = 9, edgnum = 15;
//}MGraph;

typedef struct
{
	char vex[max];
	int link[max][max];
	int vexnum, edgnum;
}MGraph; // 创建图

void MGraph_init(MGraph *G)   // 初始化图
{
	printf("请输入顶点数和边数");
	scanf_s("%d %d", &G->vexnum, &G->edgnum);
	for (int i = 0; i < G->vexnum; i++) // 初始化顶点信息
	{
		printf("请输入顶点信息");
		scanf_s(" %c", &G->vex[i]);
	}

	for (int i = 0; i < G->vexnum; i++) //初始化指向 0表示指向自己,INFINITY表示不指向
	{
		for (int j = 0; j < G->vexnum; j++)
		{
			G->link[i][j] = INFINITY; // 默认为不指向
		}
		G->link[i][i] = 0;
	}

	int i, j, w;
	for (int k = 0; k < G->edgnum; k++) // 初始化各各顶点的指向
	{
		printf("输入(vi,vj)的下标i,j和指向w \n");
		scanf_s("%d %d %d", &i, &j, &w);
		G->link[i][j] = w;
		G->link[j][i] = G->link[i][j]; // 因为在矩阵中,他们是对称的

	}

	for (int y = 0; y < G->vexnum; y++)  //打印二维数组
	{
		for (int u = 0; u < G->vexnum; u++)
		{
			printf("%d  ", G->link[y][u]);
		}
		printf("\n");
	}

}
// v0表示从v0点开始,到其他点的最短距离,vexsub储存从v0到v最短路径的最短路路径所连接的顶点,shorttable储存的是从v点到其他点最短权值
void Shortest_Dijkstra(MGraph G, int v0, int vexsub[max], int shorttable[max]) 
{

	int min, w, k,v;
	int final[max]; // 记录访问过的下标,每次访问过后下标置1
	for(int i = 0;i<G.vexnum;i++) // 初始化数据
	{
		final[i] = 0; 
		shorttable[i] = G.link[v0][i]; 
		vexsub[i] = 0;
	}
	
	shorttable[v0] = 0; // v到v忽略不计
	final[v0] = 1; // 不访问自身

	for (v = 1; v < G.edgnum; v++) // 开始循环,寻找最短路径
	{
		min = INFINITY;
		for (w = 0; w < G.edgnum; w++) // 寻找最小值
		{
			if (!final[w] && shorttable[w] < min)
			{
				min = shorttable[w];
				k = w;
			}
		}
		final[k] = 1; // 将访问过的最小值下标置为1
		//重置最小值,在所有经过最小值下标的路径的权值加上最小值与最小值顶点到另外顶点的最小值比较
		for (w = 0; w < G.vexnum; w++)
		{
			
			if (!final[w] && (min + G.link[k][w]) < shorttable[w])
			{
				shorttable[w] = min + G.link[k][w];
				vexsub[w] = k;  // 记录最小值顶点所指向的下标
			}
		}

		
		
	}
}
int main()
{
	MGraph G;
	int vexsub[max], shorttable[max];
	//MGraph_init(&G);
	Shortest_Dijkstra(G, 6, vexsub, shorttable);
	for (int u = 0; u < G.vexnum; u++)
	{
		printf("vexsub = %d,shorttable = %d \n", vexsub[u], shorttable[u]);
	}
}

v0表示从v0点开始,到其他点的最短距离,vexsub储存从v0到v最短路径的最短路路径所连接的顶点,shorttable储存的是从v点到其他点最短权值,final数组用来记录访问过的顶点,避免重复访问。

初始化的时候,vexsub初始化为0,shorttable记录V0顶点到其他顶点的最短路程,final全部初始化为0,表示现在所有的顶点都还没有访问。之后将final[v0] = 1;表示开始访问该顶点,shorttable[v0] = 0,表示不从v0点到v0点。

测试样例图:
样例图示

开始时,将min置于最大值,找出V0顶点到领边顶点的最小值,并且将最小下标赋值给k,最小值赋值给min,之后在将访问过的下标置1,之后开始进一步的比较,让min加上其他边的权值与shorttable中的值比较。如果更加的小就写进shorttable中,并且将下标写进vexsub。

比如:v0 - v2在shorttable中权值是5,但是v0的最短路径是v1,所以min = 1 ,这个时候进一步循环,发现,min+G[k][w] <shorttable,所以v0到V2的最短距离不再是5,而是4。以此类推,第二次循环的时候开始循环 v1。直到循环解释

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
迪杰斯特拉算法是一种用于求解带权图中单源最短路径问题的贪心算法。它的基本思想是从源点开始,依次确定各个顶点到源点的最短路径长度,直到求出源点到图中所有其他顶点的最短路径。 具体来说,迪杰斯特拉算法的实现步骤如下: 1. 初始化:将源点的最短路径长度设置为0,将所有其他顶点的最短路径长度设置为无穷大。 2. 选择顶点:从所有未确定最短路径的顶点中选择一个距离源点最近的顶点,将其标记为确定最短路径。 3. 更新:对于与选定顶点相邻的所有未确定最短路径的顶点,根据选定顶点到源点的距离以及选定顶点到这些顶点的距离,更新它们的最短路径长度。 4. 重复以上步骤,直到所有顶点的最短路径长度都被确定。 以下是一个简单的C语言实现: ```c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define MAX_VERTICES 100 #define INFINITE 1000000 int graph[MAX_VERTICES][MAX_VERTICES]; int dist[MAX_VERTICES]; bool visited[MAX_VERTICES]; int num_vertices; void dijkstra(int start) { // 初始化 for (int i = 0; i < num_vertices; i++) { dist[i] = INFINITE; visited[i] = false; } dist[start] = 0; // 选择顶点 for (int i = 0; i < num_vertices - 1; i++) { int min_dist = INFINITE; int min_vertex = -1; for (int j = 0; j < num_vertices; j++) { if (!visited[j] && dist[j] < min_dist) { min_dist = dist[j]; min_vertex = j; } } visited[min_vertex] = true; // 更新 for (int k = 0; k < num_vertices; k++) { if (!visited[k] && graph[min_vertex][k] != 0 && dist[k] > dist[min_vertex] + graph[min_vertex][k]) { dist[k] = dist[min_vertex] + graph[min_vertex][k]; } } } } int main() { // 读入图 scanf("%d", &num_vertices); for (int i = 0; i < num_vertices; i++) { for (int j = 0; j < num_vertices; j++) { scanf("%d", &graph[i][j]); } } // 运行算法 dijkstra(0); // 输出结果 for (int i = 0; i < num_vertices; i++) { printf("%d ", dist[i]); } printf("\n"); return 0; } ``` 在这个实现中,`graph`数组表示输入的带权图,`dist`数组表示每个顶点到源点的最短路径长度,`visited`数组表示每个顶点是否已经确定最短路径算法的核心部分在`dijkstra`函数中实现,其中使用两个嵌套的循环分别进行顶点的选择和路径长度的更新。最终结果输出在`dist`数组中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值