Dijkstra算法详解及C++实现-最短路径的高效求解

2025-05-01 24

Image

Dijkstra算法详解及C++实现

算法

Dijkstra算法是由荷兰计算机科学家艾兹赫尔·戴克斯特拉(Edsger W. Dijkstra)在1956年提出的一种解决单源最短路径问题的贪心算法。它用于计算图中一个节点到其他所有节点的最短路径,主要适用于有向图和无向图(边权重必须为非负值)。

算法原理

  1. 初始化:设置起始点到自身的距离为0,到其他所有点的距离为无穷大。
  2. 选择当前距离最小的节点:从未处理的节点中选择距离起始点最近的节点。
  3. 松弛操作:对于当前节点的所有邻居,检查是否可以通过当前节点获得更短的路径。
  4. 标记为已处理:当前节点处理完毕后,标记为已处理,不再参与后续计算。
  5. 重复:重复步骤2-4,直到所有节点都被处理。

C++实现

以下是Dijkstra算法的C++实现,包含优先队列优化:

#include <iostream>
#include <vector>
#include <queue>
#include <climits>

using namespace std;

// 定义图的邻接表表示
typedef pair<int, int> iPair; // <顶点, 权重>

class Graph {
    int V; // 顶点数
    vector<vector<iPair>> adj; // 邻接表

public:
    Graph(int V) : V(V), adj(V) {}
    
    // 添加边
    void addEdge(int u, int v, int w) {
        adj[u].emplace_back(v, w);
        adj[v].emplace_back(u, w); // 无向图需要添加双向边
    }
    
    // Dijkstra算法实现
    void dijkstra(int src) {
        // 优先队列,存储<距离, 顶点>
        priority_queue<iPair, vector<iPair>, greater<iPair>> pq;
        
        // 初始化所有距离为无穷大
        vector<int> dist(V, INT_MAX);
        
        // 插入源点,距离为0
        pq.push(make_pair(0, src));
        dist[src] = 0;
        
        while (!pq.empty()) {
            // 取出距离最小的顶点
            int u = pq.top().second;
            pq.pop();
            
            // 遍历所有邻接顶点
            for (auto &[v, weight] : adj[u]) {
                // 松弛操作
                if (dist[v] > dist[u] + weight) {
                    dist[v] = dist[u] + weight;
                    pq.push(make_pair(dist[v], v));
                }
            }
        }
        
        // 打印结果
        cout << "顶点\t距离源点的距离\n";
        for (int i = 0; i < V; ++i) {
            cout << i << "\t" << dist[i] << endl;
        }
    }
};

int main() {
    int V = 9;
    Graph g(V);
    
    // 添加图的边
    g.addEdge(0, 1, 4);
    g.addEdge(0, 7, 8);
    g.addEdge(1, 2, 8);
    g.addEdge(1, 7, 11);
    g.addEdge(2, 3, 7);
    g.addEdge(2, 8, 2);
    g.addEdge(2, 5, 4);
    g.addEdge(3, 4, 9);
    g.addEdge(3, 5, 14);
    g.addEdge(4, 5, 10);
    g.addEdge(5, 6, 2);
    g.addEdge(6, 7, 1);
    g.addEdge(6, 8, 6);
    g.addEdge(7, 8, 7);
    
    g.dijkstra(0);
    
    return 0;
}

复杂度分析

  • 时间复杂度

    • 使用优先队列优化的版本:O((V+E) log V)
    • 未优化的版本:O(V²)
  • 空间复杂度:O(V)(用于存储距离和优先队列)

算法特点

  1. 贪心算法:每次选择当前的局部解。
  2. 非负权重:不能处理负权边,因为负权边会破坏贪心选择性质。
  3. 单源最短路径:计算从一个源点到所有其他点的最短路径。

应用场景

  • 路由算法
  • 交通导航
  • 网络路由协议
  • 地图应用中的路径规划

注意事项

  1. 图中不能有负权边,否则需要使用Bellman-Ford算法。
  2. 对于稠密图,使用未优化的版本(即不使用优先队列)可能效率更高。
  3. 如果需要计算所有点对之间的最短路径,可以考虑Floyd-Warshall算法。

希望这个详细的Dijkstra算法解释和C++实现对你有所帮助!

(本文地址:https://www.nzw6.com/6646.html)

1. 本站所有资源来源于用户上传和网络,因此不包含技术服务请大家谅解!如有侵权请邮件联系客服!cheeksyu@vip.qq.com
2. 本站不保证所提供下载的资源的准确性、安全性和完整性,资源仅供下载学习之用!如有链接无法下载、失效或广告,请联系客服处理!
3. 您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容资源!如用于商业或者非法用途,与本站无关,一切后果请用户自负!
4. 如果您也有好的资源或教程,您可以投稿发布,成功分享后有积分奖励和额外收入!
5.严禁将资源用于任何违法犯罪行为,不得违反国家法律,否则责任自负,一切法律责任与本站无关