Dijkstra算法最短路径(C++控制台)

一、简介

根据传入的景点之间的路费邻接矩阵,找到两点之间费用最少的路径

二、代码

#include <stdio.h>
#define INFINITE 1000  // 定义无穷大为1000,根据实际需求可以定义的更大
#define LEN 10         // 城市的个数

// 邻接矩阵存储的图
// 因为每个景点之间都有路(全连通图),所以路线是无向图,所以没有无穷大
int TOLL[LEN][LEN] = {
	 0,  8, 31,  4, 15, 77, 88, 11, 12, 13,
	 8,  0, 24,  5,  6, 23, 33, 11, 12, 13,
	31, 24,  0,  6,  7,  2, 12, 11, 12, 13,
	 4,  5,  6,  0, 18,  8, 36, 11, 12, 13,
	15,  6,  7, 18,  0, 66, 77, 11, 12, 13,
	77, 23,  2,  8, 66,  0,  4, 11, 12, 13,
	88, 33, 12, 36, 77,  4,  0, 11, 12, 13,
	11, 11, 11, 11, 11, 11, 11,  0, 14, 14,
	12, 12, 12, 12, 12, 12, 12, 14,  0, 15,
	13, 13, 13, 13, 13, 13, 13, 14, 15,  0
};

// 标记各顶点是否已经找到最短路径,1表示找到了,0表示没找到
// 经过Init后的值为 1 0 0 0 0 0 0 0 0 0
// 一开始,A已经找到了最短路径,因为A->A的最短路径是0,所以是1,表示找到了,其余没找到的都是0
int final[LEN];

// 最短路径长度(最少花费)
// 经过Init后的值为 0 8 31 4 15 77 88 11 12 13
// 因为是全连通图,所以A可以到B-J中的任意一个地方
int  dist[LEN];

// 路径上的前驱
// 用于记录,想到达某一点的最短路径,必须要经过的路线,到达这点的前驱点
// 经过Init后的值为 -1 0 0 0 0 0 0 0 0 0
// 因为A能到达所有的点,所以所有的点前驱点一开始都是0(0代表A)
int  path[LEN];

// 用于初始化 dist path final 三个数组
void Init(int x)
{
	for (int i = 0; i < LEN; i++) {
		final[i] = 0;
	}
	final[0] = 1;

	for (int i = 0; i < LEN; i++) {
		dist[i] = TOLL[x][i];
	}

	for (int i = 0; i < LEN; i++) {
		path[i] = x;
	}
	path[x] = -1;
}

// 算法函数
void Dijkstra(int x)
{
	int min;     // 用于记录,每次循环没有被访问的城市中,能花最少的钱到的景点
	int min_pos; // 用于记录,上述的城市在 dist path final 三个数组中的位置

	// 循环查找 LEN -1 次(9次),每次找到通往某一个景点的路径,这个路径是其他通往这个景点的路径中花费的钱最少的
	// 通过9次循环就能找到A通往所有城市花费最少钱的路径
	for (int j = 0; j < LEN; j++) {
		if (j == x) {
			continue;
		}
		min = INFINITE;
		
		// 循环遍历,找到还没确定最短路径,且dist(花费)最小的顶点(景点)
		for (int i = 0; i < LEN; i++) {
			if (final[i] == 0) {
				if (dist[i] < min) {
					min_pos = i;
					min = dist[min_pos];
				}
			}
		}
		final[min_pos] = 1;  // 把这个景点设置为已经找到最短路径的状态

		// 更新没有找到最短路径的景点dist(花费)和 path(前驱)
		for (int i = 0; i < LEN; i++) {
			if (final[i] == 0) {  // 遍历所有没有找到最短路径的城市dist(花费)
				if (TOLL[min_pos][i] + dist[min_pos] < dist[i]) {
					// 如果经过景点 min_pos 能够花费更少的钱到达其他的景点,则更新dist为最新的花费的钱的数目
					dist[i] = TOLL[min_pos][i] + dist[min_pos];
					path[i] = min_pos;
				}
			}
		}
	}
}

void printMatrix()
{
	printf("\t");
	for (int x = 0; x < LEN; x++) {
		if (x == 0) {
			char A = 'A';
			printf("%c\t", A);
		}
		else if (x == 1) {
			char B = 'B';
			printf("%c\t", B);
		}
		else if (x == 2) {
			char C = 'C';
			printf("%c\t", C);
		}
		else if (x == 3) {
			char D = 'D';
			printf("%c\t", D);
		}
		else if (x == 4) {
			char E = 'E';
			printf("%c\t", E);
		}
		else if (x == 5) {
			char F = 'F';
			printf("%c\t", F);
		}
		else if (x == 6) {
			char G = 'G';
			printf("%c\t", G);
		}
		else if (x == 7) {
			char H = 'H';
			printf("%c\t", H);
		}
		else if (x == 8) {
			char I = 'I';
			printf("%c\t", I);
		}
		else if (x == 9) {
			char J = 'J';
			printf("%c\t", J);
		}
		else {
			char N = '?';
			printf("%c\t", N);
		}
		for (int j = 0; j < LEN; j++) {

		}
	}
	printf("\n");
	for (int x = 0; x < LEN; x++) {
		if (x == 0) {
			char A = 'A';
			printf("%c\t", A);
		}
		else if (x == 1) {
			char B = 'B';
			printf("%c\t", B);
		}
		else if (x == 2) {
			char C = 'C';
			printf("%c\t", C);
		}
		else if (x == 3) {
			char D = 'D';
			printf("%c\t", D);
		}
		else if (x == 4) {
			char E = 'E';
			printf("%c\t", E);
		}
		else if (x == 5) {
			char F = 'F';
			printf("%c\t", F);
		}
		else if (x == 6) {
			char G = 'G';
			printf("%c\t", G);
		}
		else if (x == 7) {
			char H = 'H';
			printf("%c\t", H);
		}
		else if (x == 8) {
			char I = 'I';
			printf("%c\t", I);
		}
		else if (x == 9) {
			char J = 'J';
			printf("%c\t", J);
		}
		else {
			char N = '?';
			printf("%c\t", N);
		}
		for (int j = 0; j < LEN; j++) {
			printf("%d\t", TOLL[x][j]);
		}
		printf("\n");
	}
	printf("\n");
}

// 通过给出的要到达的景点,递归的调用他的前驱景点,以此来完成先打印他的前驱景点的任务
void printRoute(int x)
{
	if (path[x] != -1) {
		printRoute(path[x]);
	}
	if (x == 0) {
		char A = 'A';
		printf(" %c", A);
	}
	else if (x == 1) {
		char B = 'B';
		printf(" %c", B);
	}
	else if (x == 2) {
		char C = 'C';
		printf(" %c", C);
	}
	else if (x == 3) {
		char D = 'D';
		printf(" %c", D);
	}
	else if (x == 4) {
		char E = 'E';
		printf(" %c", E);
	}
	else if (x == 5) {
		char F = 'F';
		printf(" %c", F);
	}
	else if (x == 6) {
		char G = 'G';
		printf(" %c", G);
	}
	else if (x == 7) {
		char H = 'H';
		printf(" %c", H);
	}
	else if (x == 8) {
		char I = 'I';
		printf(" %c", I);
	}
	else if (x == 9) {
		char J = 'J';
		printf(" %c", J);
	}
	else {
		char N = '?';
		printf(" %c", N);
	}
}

void Client() {
	int loop = 0;
	int x = -1;  // 入点
	int y = -1;  // 出点

	while (loop != 1) {
		printf("\t\t最少路费路径选择系统\n");
		printf("(1)退出当前客户端\t\t(2)查看景点之间路费的邻接矩阵\n");
		printf("(3)设置景点出发点和目的地\t(4)输出出发点到目的地之间最短路径\n");
		printf("(5)输出出发点到所有景点的最短路径\n");
		printf("请输入要执行的命令:");
		scanf_s("%d", &loop);
		if (loop == 2) {
			printMatrix();
		}
		if (loop == 3) {
			printf("用0-9代替A-J输入出发点:");
			scanf_s("%d", &x);
			printf("用0-9代替A-J输入目的地:");
			scanf_s("%d", &y);
			printf("\n");
		}
		if (loop == 4) {
			if (x != -1 || y != -1) {
				Init(x);
				Dijkstra(x);
				printf("%c->%c的最少花费为%d,路径为", x + 65, y + 65, dist[y]);
				printRoute(y);
				printf("\n\n");
			}
			else
			{
				printf("未初始化地址\n\n");
			}
		}
		if (loop == 5) {
			if (x != -1 || y != -1) {
				for (int i = 0; i < LEN; i++) {
					Init(x);
					Dijkstra(x);
					printf("%c->%c的最少花费为%d,路径为", x + 65, i + 65, dist[i]);  // 采用ASCII让int转字符
					printRoute(i);
					printf("\n");
				}
			}
			else
			{
				printf("未初始化地址\n\n");
			}
		}
		printf("-----------------------------------------------------------------------\n\n");
	}
}


int main(void)
{
	Client();
	
	return 0;
}

好的,下面是C++实现Dijkstra算法代码,注释经解释了每一步的含义。请注意,本代码中的图采用邻接矩阵来表示,可以根据需要进行修改。 ```cpp #include<iostream> #include<cstring> using namespace std; const int MAX = 100; const int INF = 0x3f3f3f3f; //INF表示正无穷 bool vis[MAX]; //标记数组,标记节点是否被访问 int dis[MAX]; //记录每个节点到源点的最短距离 int pre[MAX]; //记录每个节点的前驱节点 int graph[MAX][MAX]; //邻接矩阵表示图 int n; //节点个数 void dijkstra(int start) { memset(vis, false, sizeof(vis)); memset(dis, INF, sizeof(dis)); memset(pre, -1, sizeof(pre)); dis[start] = 0; //源点到自己的距离为0 //n个节点循环n次,每次找到一个距离最小的节点 for (int i = 0; i < n; i++) { int min_dis = INF, min_index; for (int j = 0; j < n; j++) { if (!vis[j] && dis[j] < min_dis) { min_dis = dis[j]; min_index = j; } } vis[min_index] = true; //标记该节点已访问 //更新当前节点的所有邻居节点的最短距离 for (int k = 0; k < n; k++) { if (!vis[k] && graph[min_index][k] != INF && dis[min_index] + graph[min_index][k] < dis[k]) { dis[k] = dis[min_index] + graph[min_index][k]; pre[k] = min_index; } } } } void print_path(int start, int end) { if (start == end) { cout << start << " "; return; } print_path(start, pre[end]); cout << end << " "; } int main() { //读入节点个数和邻接矩阵 cin >> n; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cin >> graph[i][j]; if (graph[i][j] == -1) //表示节点i和节点j之间没有直接连边 graph[i][j] = INF; } } dijkstra(0); //从源点0开始求最短路径 //输出每个节点到0点的最短距离和路径 for (int i = 0; i < n; i++) { cout << "节点" << i << "到0点的最短距离为:" << dis[i] << endl; cout << "路径为:"; print_path(0, i); cout << endl; } return 0; } ``` 需要注意的是,本代码中的邻接矩阵表示图中的-1表示两个节点之间没有直接连边,可以根据实际情况修改。另外,在求最短路径之前,需要先将邻接矩阵中的-1转化为INF,以便于后续计算。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

herb.dr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值