C语言实现最短路径问题(Dijkstra算法)

本文受此文启发:最短路径问题—Dijkstra算法详解

实现内容:求出从某个顶点V0到其余顶点的最短路径的权值,以及具体路径
具体方法:
建立一个Dij结构,D存权值,Path存路径,visit保存此顶点是否被访问过

①根据邻接矩阵初始化D
②找出D中最小的顶点pos,并把visit[pos]设为1
③设置变量j从0增加到VexNum-1(遍历邻接矩阵第pos行),判断D[j]是否大于D[pos]+<pos,j>的权值(注意要设置判断条件 INT_MAX做加法会溢出成负数)
④如果大,那么就更新D[j]为D[pos]+<pos,j>的权值,同时更新D[j]的路径为D[pos]
⑤循环③④步,最多N-1次,注意,如果找不到最小的顶点需要跳出循环

测试图:
在这里插入图片描述
文本文档内容:
在这里插入图片描述
测试结果:
在这里插入图片描述
实现代码:

/*
	实现内容:Dijkstra算法
	VS2019 编译通过 王大花 2020.8.9
*/

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MaxVexNameLength 2
#define MaxPathLength 30
#define TextPath "C:\\Users\\86132\\Desktop\\第7章 作业\\最短路径\\ALGraph.txt"

char ch[MaxVexNameLength + 1];
//顶点结点
typedef struct _VexNode {
	char Date[MaxVexNameLength + 1];

}VexNode;

typedef struct _DIJ {
	char** Path;
	int* D;
	int* visit;

}DIJ;

//图
typedef struct _ALGraph {
	VexNode* Vertics;
	int VexNum, ArcNum;
	int** ArcMatrix;
	DIJ Dij;

}ALGraph;

//找到顶点位置
int Locate(char* ch) {
	return (3 == strlen(ch)) ? 10 * (ch[1] - '0') + ch[2] - '0' : ch[1] - '0';

}

void Creat_ALGraph(ALGraph* G) {

	FILE* fp = fopen(TextPath, "r");
	fscanf(fp, "%d%d", &G->VexNum, &G->ArcNum);

	//读取顶点信息 同时初始化邻接矩阵
	G->Vertics = (VexNode*)malloc(sizeof(VexNode) * G->VexNum);
	G->ArcMatrix = (int**)malloc(sizeof(int*) * G->VexNum);

	for (int i = 0; i < G->VexNum; i++) {
		fscanf(fp, "%s", G->Vertics[i].Date);
		//初始化邻接矩阵
		G->ArcMatrix[i] = (int*)malloc(sizeof(int) * G->VexNum);
		for (int j = 0; j < G->VexNum; j++) 
			G->ArcMatrix[i][j] = INT_MAX;
	}

	//录入弧的信息
	for (int i = 0; i < G->ArcNum; i++) {
		char ch1[MaxVexNameLength + 1], ch2[MaxVexNameLength + 1];
		int tmp;
		fscanf(fp, "%s%s%d", ch1, ch2, &tmp);
		G->ArcMatrix[Locate(ch1)][Locate(ch2)] = tmp;
	}

	//初始化Dij
	G->Dij.D = (int*)malloc(sizeof(int) * G->VexNum);
	G->Dij.Path = (char**)malloc(sizeof(char*) * G->VexNum);

	G->Dij.visit = (int*)malloc(sizeof(int) * G->VexNum);
	memset(G->Dij.visit, 0, sizeof(int) * G->VexNum);

	for (int i = 0; i < G->VexNum; i++)
		G->Dij.Path[i] = (char*)malloc(sizeof(char) * MaxPathLength);
		
	fclose(fp);
}

void Shortest_Path_DIJ(ALGraph G) {

	//获得初始顶点信息
	printf("请输入开始点数据:");
	scanf("%s", ch);

		//初始化
	for (int i = 0; i < G.VexNum; i++) {
		G.Dij.D[i] = G.ArcMatrix[Locate(ch)][i];
		strcpy(G.Dij.Path[i], ch);
	}

	G.Dij.D[Locate(ch)] = 0;
	G.Dij.visit[Locate(ch)] = 1;

	//最多剩N-1个顶点
	for (int i = 1; i < G.VexNum; i++) {

		//寻找距离最小顶点的位置
		int tmp = INT_MAX, pos = Locate(ch);
		for (int j = 0; j < G.VexNum; j++) {
			if (!G.Dij.visit[j] && G.Dij.D[j] < tmp) {
				tmp = G.Dij.D[j];
				pos = j;
			}
		}

		//如果V0没有出度了
		if (pos == Locate(ch))
			break;

		G.Dij.visit[pos] = 1;
		strcat(G.Dij.Path[pos], " -> ");
		strcat(G.Dij.Path[pos], G.Vertics[pos].Date);

		for (int j = 0; j < G.VexNum; j++) {
			if (INT_MAX != G.ArcMatrix[pos][j] && INT_MAX != G.Dij.D[pos]) {
				if (INT_MAX == G.Dij.D[pos] || G.Dij.D[j] > G.ArcMatrix[pos][j] + G.Dij.D[pos])
					G.Dij.D[j] = G.Dij.D[pos] + G.ArcMatrix[pos][j];
				
				G.Dij.Path[j][0] = '\0';
				strcat(G.Dij.Path[j], G.Dij.Path[pos]);
			}

		}
	}
}

void Print_Shortest_Path_DIJ(ALGraph G) {

	printf("\n最短路径:\n\n\n");
	for (int i = 0; i < G.VexNum; i++) {

		if (Locate(ch) == i)
			continue;
		if (G.Dij.visit[i]) {
			printf("路径:%-20s\t权重:%d\n", G.Dij.Path[i], G.Dij.D[i]);
		}
		else
			printf("路径:%s -> %s \t\t\t不存在\n", ch, G.Vertics[i].Date);
	}
}

int main() {

	ALGraph G;
	Creat_ALGraph(&G);

	Shortest_Path_DIJ(G);
	Print_Shortest_Path_DIJ(G);

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值