返回博客列表
项目复盘算法可视化Next.jsReactWeb Worker个人项目

我做了一个算法调试器,把 70 多个算法都变成了可以单步回放的动画

2026年05月🇨🇳 中文

我一直觉得,学算法最难的部分,不是背概念,也不是记模板。

真正难的是:你看着一段代码,能不能在脑子里把它一步一步跑完。

比如快速排序的 partition,到底为什么这一轮先交换这里?Dijkstra 在某一步为什么一定要弹出这个点?DP 表某个格子到底是怎么推出来的?

这些东西你平时都“知道”,但真要自己盯着代码讲清楚,很多时候还是会卡。

也正因为这个,我后来做了 Algorithm Visualizer

现有工具,差在哪里

市面上其实已经有不少优秀的算法可视化工具,我也用过很多。VisuAlgo 覆盖面很广,Sorting.at 的动画很流畅,LeetCode 自带的调试器也足够实用。

所以一开始我并不是想“做一个更好的替代品”。这些工具本身已经做得很好了,也很难真正去超越。

我更真实的动机其实很简单:有些算法我看别人演示能看懂,但一到自己写、自己复盘的时候,还是会卡。

动画确实能帮助理解,但很多时候它更像是在“看别人跑完一遍”。你能看到元素在移动,却不一定能马上反应过来这一刻为什么会这样移动,当前比较的是哪几个变量,递归到底走到了哪一层,上一步和下一步之间到底发生了什么。

对我来说,真正有帮助的不是“看过”,而是自己一点点把过程走下来。因为一旦是自己动手去推、去停、去回看,理解会深很多,很多原本抽象的东西也会立刻变具体。

尤其是在比较不同算法的时候,这种感觉会更明显。比如快速排序和归并排序,教科书上都会写它们平均时间复杂度是 O(n log n),但真正执行起来,过程上的差异其实非常大。只看两个分开播放的动画,很难把这种差异真正建立成直觉。

这也是我后来想做 Algorithm Visualizer 的原因:不是因为现有工具不够好,而是因为我想做一个更适合自己反复琢磨算法过程的工具。

Algorithm Visualizer 首页界面


核心思路:把算法工具做成调试器

做这个工具之前,我一直在想一件事:每次真正把一段陌生代码看明白,靠的到底是什么?

对我来说,最有效的方式其实一直都是:打断点,单步调试,看变量变化。

IDE 调试器之所以好用,不是因为它把代码高亮了,而是因为它让你能「控制时间」——暂停、往前一步、往后一步,在任意时刻观察程序的完整状态。

所以我后来把这个思路搬进了算法可视化里。

当然,它和真正成熟的 IDE 调试器相比还有很大差距,我也没打算把两者放在同一个层面上比较;我更想借用的,是那种把执行过程一点点看清楚的体验。

Algorithm Visualizer 做的事情,本质上就是:把算法执行变成一个可控的时间轴。

你可以:

  • 点击「下一步」逐帧推进
  • 随时暂停,观察当前状态
  • 往回退,重新看刚才那一步
  • 在某个关键位置打上断点,让算法自动跑到那里停下
  • 调节播放速度,把容易卡住的地方放慢,把已经看明白的部分直接快进

与此同时,界面上始终显示当前变量的值、调用栈的层级结构、已执行的代码高亮到哪一行。这样你看到的就不只是“元素在动”,而是这一步到底发生了什么。

如果只看静态截图,这种感觉其实还不够明显。真正用起来时,更接近下面这种状态:动画在走,代码在同步高亮,变量和日志也会跟着一起变化。

Algorithm Visualizer 动态演示


最满意的一个设计:并排对比模式

我一直觉得「快速排序不稳定」这个概念很抽象。你知道 partition 会打乱相等元素的相对顺序,但如果只是停留在定义上,其实很难真正形成直觉。

打开并排对比模式,左边跑快速排序,右边跑归并排序,输入同一组数据,同步执行——你会清楚地看到,在处理相等元素时,两种算法的行为差异。

这种「同屏对比」的体验,是单独看任何一个动画都给不了你的。

比较有代表性的对比组合:

  • 快速排序 vs 归并排序(稳定性、分治方式对比)
  • BFS vs DFS(图遍历策略对比)
  • Prim vs Kruskal(最小生成树对比)

Algorithm Visualizer 并排对比模式

聊几个技术实现细节

Web Worker 预计算

最直接的实现方式是用户每点一次「下一步」,就执行一步算法逻辑,更新状态,重新渲染。但对于复杂算法,在主线程跑会导致界面卡顿甚至冻结。

所以我后来把整段算法执行搬到了 Web Worker 里,先在后台一次性生成完整的步骤快照数组。用户看到的播放器,本质上只是在这个数组上滑动索引,所以播放、暂停、回退都会很顺。

渲染性能降级

用 React 渲染 20 个柱子没问题,渲染 200 个就开始掉帧了。后来的做法是加一层自动降级:元素数量不大时,直接走 React + Motion 这一套;元素很多时,切到 Canvas 分支去画,避免页面掉帧。

技术栈:Next.js 15 + React 19,全站 TypeScript,动画主要用 Motion,复杂计算放到 Web Worker,部署在 Vercel。

为了把这套东西理顺,我后来还专门画了一张架构图。核心其实不是“把动画做出来”,而是把算法执行和界面回放拆开:算法模块负责生成步骤快照,前端只负责按时间轴把这些步骤解释出来。

Algorithm Visualizer 架构图


覆盖了哪些算法

目前实现了 70+ 个算法,分 11 大类:

排序(冒泡、快排、归并、堆排等)、图算法(BFS、DFS、Dijkstra、拓扑排序等)、树(BST、AVL、红黑树、B 树等)、动态规划(背包、LCS、编辑距离等)、回溯(N 皇后、汉诺塔、全排列等)、字符串(KMP、Rabin-Karp 等)、密码学(RSA、Caesar、Vigenère 等)、机器学习(KNN、K-Means、线性回归等)……

每个算法都有完整的逐步执行、变量监控、代码高亮,以及复杂度说明。


我不认为这个工具能替代思考,你终究还是要自己把那些递推关系、边界条件想清楚。

但我希望它至少能把这个过程变得更具体一点:让那些原本只能在脑子里硬想的执行过程,变成可以停下来、回过去、反复看的东西。

后面如果继续往下做,我还挺想补上的一个方向是多语言代码对照。现在主要还是 JavaScript,但我一直觉得,如果能把同一个算法在不同语言里的实现并排对应起来,理解和切换起来会顺很多。

如果觉得有用,欢迎 Star,也欢迎评论聊聊你学算法时遇到的困难。