返回
追溯前人脚步,算法学习的无尽乐趣:Dijkstra算法的乐章
闲谈
2023-09-14 21:38:21
前奏:算法简介
Dijkstra算法,以其创造者Edsger Wybe Dijkstra的名字命名,是图论算法中一颗璀璨的明珠。它能够求解特定起点到图中任何其他顶点的最短路径。Dijkstra算法的应用场景十分广泛,从导航软件的路径规划,到网络路由协议的选择,再到物流运输的路线优化,它都发挥着举足轻重的作用。
乐章一:算法原理
Dijkstra算法的运作原理,就如同在错综复杂的迷宫中寻找最便捷的出口。它通过逐个探索顶点,并不断更新最短距离,最终找到从起点到其他所有顶点的最短路径。算法的核心思想是:从起点出发,依次访问与其相邻的顶点,并将最短距离更新为当前距离加上相邻顶点的距离。如此循环往复,直到访问所有顶点。
乐章二:算法步骤
- 初始化:
- 将起点设为已访问,并将其最短距离标记为0。
- 将所有其他顶点设为未访问,并将其最短距离标记为无穷大。
- 循环:
- 从已访问顶点中选择一个最短距离最小的顶点,将其标记为当前顶点。
- 对于当前顶点的所有未访问邻接顶点,计算从当前顶点到这些邻接顶点的距离。
- 如果计算得到的距离比邻接顶点的最短距离更短,则更新邻接顶点的最短距离。
- 重复:
- 重复步骤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