别再死记硬背了!用C++手把手带你‘画’出Dijkstra算法的执行过程(附可运行代码)

张开发
2026/4/27 13:24:26 15 分钟阅读

分享文章

别再死记硬背了!用C++手把手带你‘画’出Dijkstra算法的执行过程(附可运行代码)
用C动态可视化Dijkstra算法从理论到实践的全景教学第一次接触Dijkstra算法时你是否也被那些抽象的距离数组和贪心选择弄得晕头转向作为图论中最经典的算法之一Dijkstra的教科书式讲解往往让人知其然而不知其所以然。本文将带你用C搭建一个动态可视化的算法演示系统通过控制台动画让算法执行过程一目了然。不同于传统的代码展示我们会重点关注如何用控制台打印模拟算法每一步的状态变化设计可视化标记系统展示关键变量的演变通过分步快照理解贪心选择的实际含义完整可运行的教学级代码含详细过程注释1. 为什么需要可视化学习Dijkstra算法学习最大的障碍在于抽象概念到具体实现的鸿沟。当我们阅读伪代码时看到的只是静态的文字描述while 存在未访问节点: 选择当前距离最小的节点u 标记u为已访问 更新u的邻居节点距离但这样的描述掩盖了算法执行过程中数据结构如何协同工作的关键细节。可视化学习能带来三点独特优势直观展示内存状态看到dist[]和visited[]数组的实时变化揭示贪心本质观察每次选择的节点如何影响后续决策错误诊断友好当结果不符合预期时可以回溯每一步的执行1.1 传统学习方法的局限性大多数教材和教程采用的方式存在明显缺陷教学方法优点缺点伪代码讲解逻辑清晰无法看到实际数据流静态代码展示完整实现执行过程不可见手动演算参与感强效率低易出错我们的可视化方案正是为了弥补这些不足而生。2. 设计可视化演示系统2.1 核心数据结构标注首先增强基础数据结构添加可视化输出能力struct Graph { int V; // 顶点数 vectorvectorint adj; // 邻接矩阵 vectorint dist; // 距离数组 vectorbool visited; // 访问标记 void printState(int current) { cout 当前节点: current endl; cout 距离数组: [; for (int d : dist) cout (d INT_MAX ? ∞ : to_string(d)) ; cout ]\n访问状态: [; for (bool v : visited) cout (v ? ✓ : ×) ; cout ]\n\n; } };2.2 算法执行的可视化改造接下来修改Dijkstra算法实现插入状态打印点void dijkstra(Graph g, int src) { // 初始化 g.dist[src] 0; g.printState(-1); // 初始状态 for (int count 0; count g.V-1; count) { int u minDistance(g); g.visited[u] true; g.printState(u); // 选择节点后的状态 for (int v 0; v g.V; v) { if (!g.visited[v] g.adj[u][v] g.dist[u] ! INT_MAX g.dist[u] g.adj[u][v] g.dist[v]) { g.dist[v] g.dist[u] g.adj[u][v]; g.printState(u); // 更新邻居后的状态 } } } }2.3 可视化输出示例执行上述代码时控制台会输出类似这样的过程当前节点: -1 距离数组: [0 ∞ ∞ ∞ ∞ ] 访问状态: [× × × × × ] 当前节点: 0 距离数组: [0 4 5 ∞ ∞ ] 访问状态: [✓ × × × × ] 当前节点: 1 距离数组: [0 4 5 ∞ 14 ] 访问状态: [✓ ✓ × × × ]3. 完整教学代码实现下面给出完整的可运行代码包含详细的注释和测试用例#include iostream #include vector #include climits using namespace std; class DijkstraVisualizer { private: int V; vectorvectorint graph; public: DijkstraVisualizer(int vertices) : V(vertices) { graph.resize(V, vectorint(V, 0)); } void addEdge(int u, int v, int weight) { graph[u][v] weight; graph[v][u] weight; // 无向图 } void printState(const vectorint dist, const vectorbool visited, int current) { cout ├─当前节点: ; if (current -1) cout 初始化; else cout current; cout \n├─距离数组: [; for (int i 0; i V; i) { if (dist[i] INT_MAX) cout ∞; else cout dist[i]; if (i ! V-1) cout , ; } cout ]\n└─访问状态: [; for (int i 0; i V; i) { cout (visited[i] ? ✓ : ×); if (i ! V-1) cout , ; } cout ]\n\n; } void run(int src) { vectorint dist(V, INT_MAX); vectorbool visited(V, false); dist[src] 0; printState(dist, visited, -1); for (int count 0; count V-1; count) { int u -1, min_dist INT_MAX; for (int v 0; v V; v) { if (!visited[v] dist[v] min_dist) { min_dist dist[v]; u v; } } if (u -1) break; visited[u] true; printState(dist, visited, u); for (int v 0; v V; v) { if (!visited[v] graph[u][v] dist[u] ! INT_MAX dist[u] graph[u][v] dist[v]) { dist[v] dist[u] graph[u][v]; printState(dist, visited, u); } } } } }; int main() { DijkstraVisualizer g(5); // 构建测试图 g.addEdge(0, 1, 4); g.addEdge(0, 2, 5); g.addEdge(1, 2, 1); g.addEdge(1, 4, 10); g.addEdge(2, 3, 2); g.addEdge(3, 4, 6); cout Dijkstra算法执行过程可视化:\n; cout \n; g.run(0); return 0; }4. 进阶可视化技巧4.1 路径追踪增强在基础距离显示外增加路径记录功能vectorint parent(V, -1); // 在距离更新处添加 if (dist[v] dist[u] graph[u][v]) { dist[v] dist[u] graph[u][v]; parent[v] u; // 记录前驱节点 } // 打印路径的函数 void printPath(const vectorint parent, int j) { if (parent[j] -1) return; printPath(parent, parent[j]); cout → j; }4.2 彩色控制台输出使用ANSI颜色代码提升可读性void printColoredState(...) { cout \033[1;34m当前节点: \033[0m current endl; cout \033[1;32m距离数组: \033[0m[; // ... 彩色输出逻辑 }4.3 交互式单步执行添加用户控制按步执行void interactiveRun(int src) { // ... 初始化 char input; while (true) { cout 按Enter继续 (q退出)...; input getchar(); if (input q) break; // 单步执行逻辑 } }5. 教学案例分步解析算法执行让我们通过一个具体例子观察算法的完整执行流程。考虑以下图结构节点关系: 0 -1 (4) 0 -2 (5) 1 -2 (1) 1 -4 (10) 2 -3 (2) 3 -4 (6)5.1 初始化阶段├─当前节点: 初始化 ├─距离数组: [0, ∞, ∞, ∞, ∞] └─访问状态: [×, ×, ×, ×, ×]5.2 第一轮选择选择节点0距离最小更新邻居1和2├─当前节点: 0 ├─距离数组: [0, 4, 5, ∞, ∞] └─访问状态: [✓, ×, ×, ×, ×]5.3 第二轮选择选择节点1距离4最小更新邻居2和4├─当前节点: 1 ├─距离数组: [0, 4, 5, ∞, 14] └─访问状态: [✓, ✓, ×, ×, ×]5.4 第三轮选择选择节点2距离5最小更新邻居3├─当前节点: 2 ├─距离数组: [0, 4, 5, 7, 14] └─访问状态: [✓, ✓, ✓, ×, ×]5.5 最终结果最短路径: 0 → 1 → 2 → 3 → 4 总距离: 13

更多文章