Dijkstra算法

一,Dijkstra算法说明

1.举例说明

我们之前的prim和kruskal都是求最小生成树的n-1条边

而现在迪杰斯特拉是求单源点到其他顶点的最短距离

a.如下图当我们把每个点之间的路径当做绳子,最开始所有点平放在桌面上,把a提起来时顶点离开桌面的顺序取决于其到A的距离

b.下图离开桌面的顺序为A,B,D,C,E

c.当所有顶点离开桌面时,绷直的绳子就是他到其他顶点的最短路径

2.代码逻辑

首先我们需要三个数组

a.dist是源点到其他顶点的距离

b.path是记录到该顶点前经过的顶点

c.check描述该点是否被访问过

我们图结构如下,假如单源点为0,标记mark0为1,更新0的邻接点的dist和path

更新dist和path:假如该点未被激活过且新的路径长度比当前更短就覆盖当前路径长度并更新path,否则不更新

找与当前节点边最短的邻接点为待激活点,重复上述单源点的操作

二,Dijkstra代码实现

1.头文件中的接口

cpp 复制代码
//
// Created by 27893 on 2025/8/4.
//

#ifndef DIJKSTRA_H
#define DIJKSTRA_H
#include "../MatrixGraph/MatrixGraph.h"
void DijkstraMGraph(MGraph *graph, int start, int *dist, int *path);

void showShortPath(const int*path,int sum,int pos);
#endif //DIJKSTRA_H

2.将头文件中的接口一一实现

cpp 复制代码
//
// Created by 27893 on 2025/8/4.
//

#include "Dijkstra.h"

#include <stdio.h>
#include <stdlib.h>

void DijkstraMGraph(MGraph *graph, int start, int *dist, int *path) {
	//1.初始化激活第一个顶点
	int*mark=malloc(sizeof(int)*graph->nodeNum);
	for (int i=0;i<graph->nodeNum;++i) {
		dist[i]=graph->edges[start][i];
		mark[i]=0;
		if (graph->edges[start][i]<INF) {
			path[i]=start;
		}else {
			path[i]=-1;
		}
	}
	dist[start]=0;
	path[start]=-1;
	mark[start]=1;
	//2.核心循环
	for (int i=0;i<graph->nodeNum-1;++i) {
		int mini=INF,k=0;
		for (int j=0;j<graph->nodeNum;++j) {
			//3.找到最小值为待激活点
			if (mark[j]==0&&dist[j]<mini) {
				mini=dist[j];
				k=j;
			}
		}
		mark[k]=1;
		//4.激活,更新dist和path
		for (int j=0;j<graph->nodeNum;++j) {
			if (mark[j]==0&&dist[k]+graph->edges[k][j]<dist[j]) {
				dist[j]=dist[k]+graph->edges[k][j];
				path[j]=k;
			}
		}
	}
	free(mark);
}

void showShortPath(const int *path, int sum, int pos) {
	int*stack=malloc(sizeof(int)*sum);
	int top=-1;
	//1.倒序入栈
	while (path[pos]!=-1) {
		stack[++top]=pos;
		pos=path[pos];
	}
	stack[++top]=pos;
	//2.顺序出栈,遍历
	while (top!=-1) {
		printf("%d\t",stack[top--]);
	}
	printf("\n");
	free(stack);
}

3.测试代码是否有bug

cpp 复制代码
//
// Created by 27893 on 2025/8/4.
//
#include <stdio.h>
#include <stdlib.h>

#include "Dijkstra.h"
void setup(MGraph*graph) {
	const char *names[] = {"0", "1", "2", "3", "4", "5", "6",};
	initMGraph(graph, names, sizeof(names) / sizeof(names[0]), 1, INF);
	addMGraph(graph, 0, 1,4);
	addMGraph(graph, 0, 2, 6);
	addMGraph(graph, 0, 3, 6);
	addMGraph(graph, 1, 2, 1);
	addMGraph(graph, 1, 4, 7);
	addMGraph(graph, 2, 4, 6);
	addMGraph(graph, 2, 5, 4);
	addMGraph(graph, 3, 5, 5);
	addMGraph(graph, 3, 2, 2);
	addMGraph(graph, 4, 6, 6);
	addMGraph(graph, 5, 4, 1);
	addMGraph(graph, 5, 6, 8);
}
int main() {
	MGraph graph;
	setup(&graph);
	int*dist=malloc(sizeof(int)*graph.nodeNum);
	int*path=malloc(sizeof(int)*graph.nodeNum);
	if (dist==NULL||path==NULL) {
		return -1;
	}
	DijkstraMGraph(&graph,0,dist,path);
	printf("from #0 to #5:dist:%d\n",dist[5]);
	showShortPath(path,graph.nodeNum,5);
	printf("from #0 to #6:dist:%d\n",dist[6]);
	showShortPath(path,graph.nodeNum,6);
	free(dist);
	return 0;
}
相关推荐
隔窗听雨眠6 小时前
C语言函数递归从入门到精通(下):性能优化与工程实践
c语言·算法·性能优化
退休倒计时6 小时前
【每日一题】LeetCode 146. LRU 缓存 TypeScript
算法·leetcode·缓存·typescript
珊瑚里的鱼6 小时前
【递归】汉诺塔
算法·深度优先
MrZhao4006 小时前
一个最小 Agent 是怎么跑起来的:Agent Loop 与工具使用全链路
算法
Keven_116 小时前
算法札记:二分
算法·二分
TCW11216 小时前
AI底层系列:用C++实现线性代数的公式推导与算法设计-6.线性方程组的解集
c++·人工智能·算法
luoyayun3617 小时前
从零实现 EBU R128 LUFS 响度分析:K-weighting 滤波、双门限算法
算法·lufs响度分析
小糯米6017 小时前
JS 数组
数据结构·算法·排序算法
小欣加油7 小时前
leetcode3612 用特殊操作处理字符串I
数据结构·c++·算法·leetcode·职场和发展
拳里剑气7 小时前
C++算法:链表
c++·算法·链表