Dijkstra算法:求单源最短路径

本文详细介绍了Dijkstra算法,包括其定义、工作原理、步骤以及C++代码实现,适用于解决单源最短路径问题,特别指出不适用于负权图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        

目录

一、什么是单源最短路径?

二、Dijkstra算法原理

三、Dijkstra算法步骤

四、Dijkstra算法代码实现

1. 图

2. Dijkstra

3. 打印最短路径

五、完整代码

六、运行结果


        Dijkstra算法是一种常用的解决单源最短路径问题贪心算法。在本篇文章中,我们将深入了解Dijkstra算法的原理、代码实现以及一些应用场景。不适用负权图,无法正确求出最短路径,但算法可执行完

一、什么是单源最短路径?

        单源最短路径问题是在一个带权重的有向图中寻找从一个特定顶点到其他顶点的最短路径。最短路径可以通过边的权重之和来度量。

二、Dijkstra算法原理

        Dijkstra算法的主要思想是从源顶点开始,逐步扩展到其他顶点,找到最短路径。算法维护一个距离数组,用于记录源顶点到每个顶点的当前最短距离。每次选择未访问的顶点中距离最短的顶点,然后更新距离数组,再以新选定的顶点为中心继续扩展。

三、Dijkstra算法步骤

  1. 初始化距离数组,将源顶点距离设为0,与源顶点有关联的顶点距离设为其对应的边权值,在final数组中将源顶点标为true,表示源顶点已经找到到自身的最短路径。并将path数组也都初始化。
  2. 选择当前距离最小且未被标记的顶点作为中心顶点。
  3. 更新其他未访问顶点的距离,通过中心顶点计算新的距离。
  4. 标记中心顶点为已访问。
  5. 重复步骤2~4,直到所有顶点都被访问。

四、Dijkstra算法代码实现

以下是代码中创建的图:

 0到2的最短路径应该是0->4->1->2                最短带权路径长度是5+3+1=9

以下是使用C++实现Dijkstra算法的示例代码:

1. 图
#define V 5			//顶点个数
struct Edge {		//边结点
	int vex;
	int weight;
	Edge* next;
};
struct Vex {		//顶点结点
	Edge* firstEdge;//顶点连的第一条边
};
Vex graph[V];		//图的邻接表存储,数组下标就是顶点标识
void initGraph() {	//图初始化
	for (int i = 0; i < V; i++) {
		graph[i].firstEdge = NULL;
	}
}
//添加边
void insertEdge(int source, int destination, int weight) {
	if (source >= 0 && source < V && destination >= 0 && destination < V) {
		Edge* newEdge = (Edge*)malloc(sizeof(Edge));
		newEdge->vex = destination;
		newEdge->weight = weight;
		newEdge->next = graph[source].firstEdge;
		graph[source].firstEdge = newEdge;
	}
	else {
		cout << "添加失败" << endl;
	}
}
2. Dijkstra
bool final[V];		//标记是否已经确认到某顶点的最短路径
int dist[V];		//最短路径长度
int path[V];		//路径上的前驱
//返回dist数组中未确定最短路径且dist最小的顶点的数组下标
int findMin() {
	int Min = INT_MAX;
	int min_index = -1;
	for (int i = 0; i < V; i++) {
		if (!final[i] && dist[i] < Min) {
			Min = dist[i];
			min_index = i;
		}
	}
	return min_index;
}
void Dijkstra(int begin) {
	//初始化上面三个辅助算法的数组
	for (int i = 0; i < V; i++) {
		final[i] = false;
		dist[i] = INT_MAX;
		path[i] = -1;
	}
	final[begin] = true;
	dist[begin] = 0;
	Edge* p = graph[begin].firstEdge;
	while (p != NULL) {
		dist[p->vex] = p->weight;
		path[p->vex] = begin;
		p = p->next;
	}

	for (int i = 0; i < V - 1; i++) {
		int min_index = findMin();
		final[min_index] = true;
		p = graph[min_index].firstEdge;
		while (p != NULL) {
			int newDist = dist[min_index] + p->weight;
			if (newDist < dist[p->vex]) {
				dist[p->vex] = newDist;
				path[p->vex] = min_index;
			}
			p = p->next;
		}
	}
}
3. 打印最短路径
void printMinRoad(vector<int> arr, int begin, int end) {
	cout << "Dijkstra算法得到的由顶点" << begin << "到顶点" << end
		<< "的最短路径:";
	int i = end;
	arr.push_back(i);
	while (path[i] != begin) {
		arr.push_back(path[i]);
		i = path[i];
	}
	arr.push_back(begin);

	for (int i = arr.size() - 1; i > 0; i--) {
		cout << arr[i] << "->";
	}
	cout << arr[0] << endl;
	cout << "最短带权路径长度是:" << dist[end] << endl;
}

五、完整代码

#include<iostream>
#include<vector>
using namespace std;

#define V 5			//顶点个数
struct Edge {		//边结点
	int vex;
	int weight;
	Edge* next;
};
struct Vex {		//顶点结点
	Edge* firstEdge;//顶点连的第一条边
};
Vex graph[V];		//图的邻接表存储,数组下标就是顶点标识
void initGraph() {	//图初始化
	for (int i = 0; i < V; i++) {
		graph[i].firstEdge = NULL;
	}
}
//添加边
void insertEdge(int source, int destination, int weight) {
	if (source >= 0 && source < V && destination >= 0 && destination < V) {
		Edge* newEdge = (Edge*)malloc(sizeof(Edge));
		newEdge->vex = destination;
		newEdge->weight = weight;
		newEdge->next = graph[source].firstEdge;
		graph[source].firstEdge = newEdge;
	}
	else {
		cout << "添加失败" << endl;
	}
}
bool final[V];		//标记是否已经确认到某顶点的最短路径
int dist[V];		//最短路径长度
int path[V];		//路径上的前驱
//返回dist数组中未确定最短路径且dist最小的顶点的数组下标
int findMin() {
	int Min = INT_MAX;
	int min_index = -1;
	for (int i = 0; i < V; i++) {
		if (!final[i] && dist[i] < Min) {
			Min = dist[i];
			min_index = i;
		}
	}
	return min_index;
}
void Dijkstra(int begin) {
	//初始化上面三个辅助算法的数组
	for (int i = 0; i < V; i++) {
		final[i] = false;
		dist[i] = INT_MAX;
		path[i] = -1;
	}
	final[begin] = true;
	dist[begin] = 0;
	Edge* p = graph[begin].firstEdge;
	while (p != NULL) {
		dist[p->vex] = p->weight;
		path[p->vex] = begin;
		p = p->next;
	}

	for (int i = 0; i < V - 1; i++) {
		int min_index = findMin();
		final[min_index] = true;
		p = graph[min_index].firstEdge;
		while (p != NULL) {
			int newDist = dist[min_index] + p->weight;
			if (newDist < dist[p->vex]) {
				dist[p->vex] = newDist;
				path[p->vex] = min_index;
			}
			p = p->next;
		}
	}
}
void printMinRoad(vector<int> arr, int begin, int end) {
	cout << "Dijkstra算法得到的由顶点" << begin << "到顶点" << end
		<< "的最短路径:";
	int i = end;
	arr.push_back(i);
	while (path[i] != begin) {
		arr.push_back(path[i]);
		i = path[i];
	}
	arr.push_back(begin);

	for (int i = arr.size() - 1; i > 0; i--) {
		cout << arr[i] << "->";
	}
	cout << arr[0] << endl;
	cout << "最短带权路径长度是:" << dist[end] << endl;
}
int main() {
	initGraph();		//初始化图
	//添加边
	insertEdge(0, 1, 10);
	insertEdge(0, 4, 5);
	insertEdge(1, 4, 2);
	insertEdge(4, 1, 3);
	insertEdge(1, 2, 1);
	insertEdge(4, 2, 9);
	insertEdge(4, 3, 2);
	insertEdge(2, 3, 4);
	insertEdge(3, 2, 6);
	insertEdge(3, 0, 7);
	//Dijkstra算法求顶点0到其他顶点的最短路径
	Dijkstra(0);
	//打印
	vector<int> arr;
	printMinRoad(arr, 0, 2);
	return 0;
}

六、运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不想学习啊啊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值