Dijkstra算法原理及代码实现(c++版)

本文深入解析了迪杰斯特拉算法,一种用于求解图中单源点到其他所有点最短路径的经典算法。文章详细阐述了算法的基本思想、适用条件、实现步骤,并提供了完整的代码实现案例,帮助读者理解算法的运作机制。

目录

 

1 算法简介

2 算法原理

1)初始化

2)循环体

3)进行一次循环

4)结束条件

3 代码实现

4 参考


1 算法简介

算法任务:求图G中一源点C其他所有点最短路径的算法

基本思路:将图G中的点(记为集合V)分为两部分,已找到最短路径的点集S与尚未找到最短路径的点集\overline{S}(=V-S)。按到源点C由近  到远的顺序,逐个将\overline{S}中离源点C最近的点加入点集S,直到将所有的点都加入S,算法完成。

使用条件:边权不为负的连通图(有向无向均可)

2 算法原理

问题描述:求下图(记为图G)从点V_{0}到其他点的最短路径(用dis[n]存储,n为图中点的总数,dis[i]代表点V_{i}V_{0}的最短路径除了dis[n]之外,还需要这定义这几个变量:

矩阵edge[n][n]:使用邻接表方式来存储带权图 ,数组visit[n]:记录点V_{i}是否已经找到最短路径(true表示已找到,false表示未找到)

解答步骤:按照初始化,循环体,结束条件三步进行描述,符合代码实现的要求

1)初始化

由于已经确定了源点是V_{0},那么现在可以初始化得到dis[0]=0,visit[0]=true

已找到最短路径的点集S中仅含V_{0}一个点(S={V_{0}}),此时\overline{S}中的点要与S中的点建立路径,只能通过与V_{0}相连。

V_{0}直接相连的点为V_{1}V_{2},则初始化的dis[n]={ 0 , 1 , 5 ,INF,INF,INF,INF,INF,INF}

2)循环体

首先将目前的dis[n]中距离最小的点加入点集S,目前S={V_{0}V_{1}},比起之前,我们多了一个S与\overline{S}之间点建立路径的中介:点V_{1}

然后更新dis[n],因为多了一个中介点,所以我们可以通过V_{0}\rightarrowV_{1}\rightarrow其他点来建立新的路径,与V_{1}直接相连的为V_{2}V_{3}V_{4},那么通过中介点V_{1},dis[n]={ 0 , 1 ,dis[1]+edge[1][2]=4 , dis[1]+edge[1][3]=8 ,dis[1]+edge[1][4]=6,INF,INF,INF,INF},再与上一步的dis[n]比较,dis[n]={ 0 , 1 , 5 ,INF,INF,INF,INF,INF,INF},比较这两个dis[n],保留相同点距离源点距离更小的那条路径。

则这一步更新得到的dis[n]={0 , 1 , 4,8,6,INF,INF,INF,INF}。

3)进行一次循环

首先将目前的dis[n]中距离最小的点加入点集S,目前S={V_{0}V_{1}V_{2}},比起之前,多了一个S与\overline{S}之间点建立路径的中介:点V_{2}

然后更新dis[n],只需要比较V_{0}\rightarrow其他点和通过V_{0}\rightarrowV_{2}\rightarrow其他点的路径,保留距离更小的路径即完成更新。

4)结束条件

点集S包含图G内的所有点。用上面已定义的变量表示就是visit[n]全部为true。

 

3 代码实现

#include<iostream>
using namespace std;
const int INF = 99999;
int main() {
	int edge[9][9] = {
			{ 0 , 1 , 5 ,INF,INF,INF,INF,INF,INF},
			{ 1 , 0 , 3 , 7 , 5 ,INF,INF,INF,INF},
			{ 5 , 3 , 0 ,INF, 1 , 7 ,INF,INF,INF},
			{INF, 7 ,INF, 0 , 2 ,INF, 3 ,INF,INF},
			{INF, 5 , 1 , 2 , 0 , 3 , 6 ,INF,INF},
			{INF,INF, 7 ,INF, 3 , 0 ,INF, 5 ,INF},
			{INF,INF,INF, 3 , 6 ,INF, 0 , 2 , 7 },
			{INF,INF,INF,INF, 9 , 5 , 2 , 0 , 4 },
			{INF,INF,INF,INF,INF,INF, 7 , 4 , 0 }
	};
	int dis[9]; fill(dis, dis + 9, INF);
	bool visit[9]; fill(visit, visit + 9, false);
	//对应步骤1):初始化
	int c1 = 0;
	dis[c1] = 0;

	//最外层循环对应步骤3):结束条件,把n个点均放入点集S
	for (int i = 0; i < 9; i++) {

		//这一层循环对应步骤2):循环体中的寻找当前dis[n]中距离最小的点加入点集S
		int mind = INF, u = -1;
		for (int j = 0; j < 9; j++) {
			if (visit[j] == false && dis[j] < mind) {
				u = j;
				mind = dis[j];
			}
		}
		if (u == -1) break;
		visit[u] = true;
		//这一层循环对应步骤2):循环体中的更新dis[n]步骤
		for (int v = 0; v < 9; v++) {
			if (visit[v] == false && edge[u][v] < INF) {
				if (dis[u] + edge[u][v] < dis[v]) {
					dis[v] = dis[u] + edge[u][v];
				}
			}
		}
	}
	for (int i = 0; i < 9; i++)
		cout << dis[i] << ' ';

	system("pause");
	return 0;
}

运行结果:

4 参考

示例图来源:

https://www.jianshu.com/p/b8734fd2ab57

 

### Dijkstra算法C++实现 为了提供一个完整的Dijkstra算法模板,以下是基于优先队列优化本的实现方式。此方法能够有效地处理加权图中的最短路径计算问题。 ```cpp #include <vector> #include <queue> #include <climits> using namespace std; typedef pair<int, int> iPair; void dijkstra(vector<vector<iPair>> adjList, int src) { int V = adjList.size(); vector<int> dist(V, INT_MAX); priority_queue<iPair, vector<iPair>, greater<iPair>> pq; pq.push(make_pair(0, src)); dist[src] = 0; while (!pq.empty()) { int u = pq.top().second; pq.pop(); for (auto& edge : adjList[u]) { int v = edge.first; int weight = edge.second; if (dist[v] > dist[u] + weight) { dist[v] = dist[u] + weight; pq.push(make_pair(dist[v], v)); } } } // 打印结果 printf("Vertex Distance from Source\n"); for (int i = 0; i < V; ++i) printf("%d \t\t %d\n", i, dist[i]); } ``` 上述代码定义了一个`dijkstra`函数来执行该算法[^1]。这里使用了邻接表表示法存储图形数据结构,并通过最小堆(优先级队列)实现了节点的选择过程。对于每一个顶点,程序会尝试更新其相邻顶点的距离值;如果找到更优解,则将其加入到待处理集合中继续探索。 #### 数据结构说明: - `adjList`: 邻接列表形式表示的有向带权图。 - `src`: 起始源点编号。 - `dist[]`: 记录从起点到达各点之间的最短距离数组。 - `priority_queue<iPair>`: 使用STL库提供的二叉堆作为底层容器构建的小根堆,在每次迭代时取出当前未访问过的具有最小估计代价的顶点进行扩展。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值