返回

追溯前人脚步,算法学习的无尽乐趣:Dijkstra算法的乐章

闲谈

前奏:算法简介

Dijkstra算法,以其创造者Edsger Wybe Dijkstra的名字命名,是图论算法中一颗璀璨的明珠。它能够求解特定起点到图中任何其他顶点的最短路径。Dijkstra算法的应用场景十分广泛,从导航软件的路径规划,到网络路由协议的选择,再到物流运输的路线优化,它都发挥着举足轻重的作用。

乐章一:算法原理

Dijkstra算法的运作原理,就如同在错综复杂的迷宫中寻找最便捷的出口。它通过逐个探索顶点,并不断更新最短距离,最终找到从起点到其他所有顶点的最短路径。算法的核心思想是:从起点出发,依次访问与其相邻的顶点,并将最短距离更新为当前距离加上相邻顶点的距离。如此循环往复,直到访问所有顶点。

乐章二:算法步骤

  1. 初始化:
  • 将起点设为已访问,并将其最短距离标记为0。
  • 将所有其他顶点设为未访问,并将其最短距离标记为无穷大。
  1. 循环:
  • 从已访问顶点中选择一个最短距离最小的顶点,将其标记为当前顶点。
  • 对于当前顶点的所有未访问邻接顶点,计算从当前顶点到这些邻接顶点的距离。
  • 如果计算得到的距离比邻接顶点的最短距离更短,则更新邻接顶点的最短距离。
  1. 重复:
  • 重复步骤2,直到所有顶点都标记为已访问。

乐章三:算法实现

1. C++语言实现

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

using namespace std;

// 定义图的结构
struct Graph {
    int num_vertices;
    vector<vector<pair<int, int>>> adj_list;

    // 构造函数,初始化图
    Graph(int num_vertices) : num_vertices(num_vertices) {
        adj_list.resize(num_vertices);
    }

    // 添加边
    void add_edge(int u, int v, int weight) {
        adj_list[u].push_back({v, weight});
    }

    // Dijkstra算法
    vector<int> dijkstra(int start) {
        // 初始化距离数组
        vector<int> distances(num_vertices, INT_MAX);
        distances[start] = 0;

        // 创建优先队列,按距离升序排列
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
        pq.push({0, start});

        // 循环,直到访问所有顶点
        while (!pq.empty()) {
            // 取出距离最小的顶点
            int u = pq.top().second;
            pq.pop();

            // 对于当前顶点的每个邻接顶点
            for (auto edge : adj_list[u]) {
                int v = edge.first;
                int weight = edge.second;

                // 如果通过当前顶点到达邻接顶点的距离更短,则更新邻接顶点的距离
                if (distances[v] > distances[u] + weight) {
                    distances[v] = distances[u] + weight;
                    pq.push({distances[v], v});
                }
            }
        }

        return distances;
    }
};

int main() {
    // 创建一个图
    Graph graph(9);
    graph.add_edge(0, 1, 4);
    graph.add_edge(0, 6, 7);
    graph.add_edge(1, 2, 9);
    graph.add_edge(1, 6, 14);
    graph.add_edge(2, 3, 2);
    graph.add_edge(2, 5, 11);
    graph.add_edge(3, 4, 9);
    graph.add_edge(3, 5, 6);
    graph.add_edge(4, 5, 2);
    graph.add_edge(4, 7, 10);
    graph.add_edge(5, 6, 2);
    graph.add_edge(5, 7, 1);
    graph.add_edge(6, 7, 1);
    graph.add_edge(6, 8, 15);
    graph.add_edge(7, 8, 5);

    // 从顶点0开始运行Dijkstra算法
    vector<int> distances = graph.dijkstra(0);

    // 打印结果
    for (int i = 0; i < graph.num_vertices; i++) {
        cout << "最短路径距离[" << i << "] = " << distances[i] << endl;
    }

    return 0;
}

2. Python语言实现

import heapq

# 定义图的结构
class Graph:
    def __init__(self, num_vertices):
        self.num_vertices = num_vertices
        self.adj_list = [[] for _ in range(num_vertices)]

    # 添加边
    def add_edge(self, u, v, weight):
        self.adj_list[u].append((v, weight))

    # Dijkstra算法
    def dijkstra(self, start):
        # 初始化距离数组
        distances = [float('inf')] * self.num_vertices
        distances[start] = 0

        # 创建优先队列,按距离升序排列
        pq = [(0, start)]

        # 循环,直到访问所有顶点
        while pq:
            # 取出距离最小的顶点
            u = heapq.heappop(pq)[1]

            # 对于当前顶点的每个邻接顶点
            for v, weight in self.adj_list[u]:
                # 如果通过当前顶点到达邻接顶点的距离更短,则更新邻接顶点的距离
                if distances[v] > distances[u] + weight:
                    distances[v] = distances[u] + weight
                    heapq.heappush(pq, (distances[v], v))

        return distances

# 创建一个图
graph = Graph(9)
graph.add_edge(0, 1, 4)
graph.add_edge(0, 6, 7)
graph.add_edge(1, 2, 9)
graph.add_edge(1, 6, 14)
graph.add_edge(2, 3, 2)
graph.add_edge(2, 5, 11)
graph.add_edge(3, 4, 9)
graph.add_edge(3, 5, 6)
graph.add_edge(4, 5, 2)
graph.add_edge(4, 7, 10)
graph.add_edge(5, 6, 2)
graph.add_edge(5, 7, 1)
graph.add_edge(6, 7, 1)
graph.add_edge(6, 8, 15)
graph.add_edge(7, 8, 5)

# 从顶点0开始运行Dijkstra算法
distances = graph.dijkstra(0)

# 打印结果
for i in range(graph.num_vertices):
    print(f"最短路径距离[{i}] = {distances[i]}")

尾声:算法的价值

Dijkstra算法是一颗璀璨的算法明珠,在计算机科学领域有着广泛的应用。它以其简单、高效的特性,为我们解决各种图论问题提供了有效的工具。从导航软件的路径规划,到网络路由协议的选择,再到物流运输的路线优化,Dijk