Dijkstra算法

server/2025/3/16 15:21:47/

Dijkstra算法(迪杰斯特拉算法)是一种经典的单源最短路径算法,用于在加权图中找到从一个源点到所有其他顶点的最短路径。它要求图中不能有负权边,因为负权边可能会导致算法的贪心策略失效。

Dijkstra算法的基本思想

Dijkstra算法的核心思想是贪心算法,通过逐步扩展已知最短路径的集合,最终找到从源点到所有顶点的最短路径。

算法步骤:
  1. 初始化

    • 将源点到自身的距离设为0,即 dist[source] = 0
    • 将源点到其他所有顶点的距离设为无穷大,即 dist[v] = +∞
    • 使用一个优先队列(最小堆)来存储待处理的顶点,初始时将源点加入队列。
  2. 松弛操作

    • 从优先队列中取出距离最小的顶点 u
    • 对于顶点 u 的所有出边 (u, v),尝试更新从源点到顶点 v 的距离:
      if dist[u] + weight(u, v) < dist[v]:dist[v] = dist[u] + weight(u, v)
      
    • 如果更新了 dist[v],则将顶点 v 加入优先队列。
  3. 重复上述过程,直到优先队列为空。

Dijkstra算法的实现

以下是Dijkstra算法的标准实现,使用优先队列(最小堆)来优化松弛操作。

#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;const int MAXN = 100005; // 最大顶点数
const int INF = 0x3f3f3f3f; // 表示无穷大struct Edge {int to, weight;
};vector<Edge> graph[MAXN]; // 邻接表存储图
int dist[MAXN];           // 存储从源点到每个顶点的最短距离
bool visited[MAXN];       // 标记顶点是否已经被处理// Dijkstra算法
void dijkstra(int n, int source) {// 初始化for (int i = 1; i <= n; i++) {dist[i] = INF;visited[i] = false;}dist[source] = 0;// 使用优先队列(最小堆)priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;pq.push({0, source}); // {距离, 顶点}while (!pq.empty()) {int u = pq.top().second; // 当前顶点int d = pq.top().first;  // 当前顶点的距离pq.pop();if (visited[u]) continue; // 如果已经处理过,跳过visited[u] = true;// 遍历所有出边for (const auto& edge : graph[u]) {int v = edge.to;int weight = edge.weight;// 尝试松弛if (dist[u] + weight < dist[v]) {dist[v] = dist[u] + weight;pq.push({dist[v], v}); // 将更新后的顶点加入队列}}}
}int main() {int n, m, source;cout << "Enter number of vertices and edges: ";cin >> n >> m;cout << "Enter source vertex: ";cin >> source;cout << "Enter edges (u, v, weight):" << endl;for (int i = 0; i < m; i++) {int u, v, weight;cin >> u >> v >> weight;graph[u].push_back({v, weight}); // 添加边}dijkstra(n, source);cout << "Shortest distances from source vertex " << source << ":" << endl;for (int i = 1; i <= n; i++) {if (dist[i] == INF) {cout << "Vertex " << i << ": No path" << endl;} else {cout << "Vertex " << i << ": " << dist[i] << endl;}}return 0;
}

算法复杂度

  • 时间复杂度
    • 如果使用普通数组实现,时间复杂度为 O(V²)
    • 如果使用优先队列(最小堆)实现,时间复杂度为 O(E + V log V),其中 E 是边数,V 是顶点数。
  • 空间复杂度O(V + E),主要用于存储图的邻接表和辅助数组。

适用场景

Dijkstra算法适用于以下场景:

  1. 图中不包含负权边
  2. 需要快速计算从单个源点到所有其他顶点的最短路径。
  3. 图的边数较多,且顶点数较少(适合稀疏图)。

注意事项

  1. 负权边问题

    • Dijkstra算法不能处理负权边。如果图中可能包含负权边,应使用Bellman-Ford算法或SPFA算法
  2. 图的表示

    • 在实际应用中,图可以用邻接表或邻接矩阵表示。邻接表更适合稀疏图,而邻接矩阵更适合稠密图。
  3. 优化

    • 如果图中包含大量顶点,但只有少数顶点需要计算最短路径,可以使用启发式算法(如A*算法)来进一步优化。

总结

Dijkstra算法是一种高效的单源最短路径算法,特别适合处理不包含负权边的图。它通过贪心策略逐步扩展已知最短路径的集合,并利用优先队列优化松弛操作,从而在大多数情况下能够快速找到最短路径。


http://www.ppmy.cn/server/175459.html

相关文章

matlab 火电厂给水控制系统仿真

1、内容简介 略 matlab157-火电厂给水控制系统仿真 可以交流、咨询、答疑 2、内容说明 略 摘 要 虽然现在新能源发电领域比较火爆&#xff0c;但至今火力发电厂依然在我的的发电领域中拥有很重要的地位。我国虽然还是发展中国家&#xff0c;但是近年来GDP的增长已经处于世界…

Kotlin 协程基础详解(总结面试)

在异步编程领域&#xff0c;Kotlin 协程以其轻量级、高并发和简洁的代码风格&#xff0c;成为现代 Android 的首选方案。 协程的核心优势 轻量级任务单元 协程基于线程池调度&#xff0c;单个线程可同时运行数千个协程&#xff0c;相比传统线程&#xff08;约 1MB 栈空间&…

prompt提示词

提示词 12345 1 你是一个高级代码分析智能助手&#xff0c;专门帮助开发者通过逆向思维深入理解代码。所谓逆向思维&#xff0c;在这里是指从项目的最终目的和需求出发&#xff0c;反向探索为何需要编写特定代码段以及这些代码是如何支持整体目标的。你的任务是基于这种思维方…

让双向链表不在云里雾里

又来博客留下我的足迹了&#xff0c;哈哈哈&#xff0c;这次是对于双向链表的理解 目录 创建双向链表&#xff1a; 申请结点&#xff1a; 双向链表初始化&#xff1a; 双向链表插入结点&#xff1a; 双向链表删除结点&#xff1a; 双向链表的打印&#xff1a; 双向链表…

Kubernetes学习笔记-移除Nacos迁移至K8s

项目服务的配置管理和服务注册发现由原先的Nacos全面迁移到Kubernetes上。 一、移除Nacos 移除Nacos组件依赖。 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <…

mac安装navicat及使用

0.删除旧的 sudo rm -Rf /Applications/Navicat\ Premium.app sudo rm -Rf /private/var/db/BootCaches/CB6F12B3-2C14-461E-B5A7-A8621B7FF130/app.com.prect.NavicatPremium.playlist sudo rm -Rf ~/Library/Caches/com.apple.helpd/SDMHelpData/Other/English/HelpSDMIndexF…

Rubick:基于 Electron 的开源插件化桌面效率工具箱

Rubick 是一款基于 Electron 构建的开源桌面工具箱&#xff0c;专为追求高效办公和个性化体验的用户设计。它通过自由集成丰富的插件&#xff0c;让用户能够根据自己的需求打造极致的桌面端效率工具。 软件命名由来Rubick 的名字来源于《DOTA2》中的英雄 Rubick&#xff08;拉…

深入解析java Socket通信中的粘包与拆包问题及解决方案(中)

推荐关联阅读&#xff1a;Java Socket通信基础及拆包粘包问题模拟&#xff08;上&#xff09; 一、粘包与拆包现象解析 1.1 问题本质 在TCP协议的网络通信中&#xff0c;发送端写入的数据单元与接收端读取的数据单元不一致的现象称为粘包&#xff08;合并数据包&#xff09;…