排序算法可视化

冒泡/快排/归并/堆排动画

408 次访问
SORTING ALGORITHM VISUALIZER

排序算法可视化

冒泡 / 选择 / 插入 / 快排 / 归并 / 堆排序 动画

关于本工具

了解工具定位 · 使用场景 · 对比优势

使用场景

🎓

算法课程教学

计算机专业学生在学习排序算法时,教材上的伪代码和静态图很难直观理解元素交换过程。本工具将冒泡排序、快速排序、归并排序、堆排序的执行过程逐帧动画化,每一步高亮当前比较和交换的元素,配合速度调节和暂停功能,让抽象的分治、递归思想变成可观察的视觉轨迹,帮助学生建立算法直觉。

💼

面试算法复习

准备大厂技术面试的开发者需要快速回顾多种排序算法的时间复杂度、稳定性、适用场景。本工具提供同一组随机数据在四种算法下的动画对比,一眼看出冒泡的 O(n²) 低效与快排的 O(n log n) 优势,同时观察归并排序的额外空间消耗,帮助面试者在手撕代码前建立清晰的算法选择依据。

📊

数据分布可视化

数据分析师或科研人员需要理解不同数据分布(随机、逆序、几乎有序)对排序性能的影响。本工具允许自定义输入数组,切换数据排列方式后分别运行四种算法,动画直观展示:几乎有序时插入排序(若含)为何快于快排,逆序时堆排序为何稳定,为实际业务中的排序策略选择提供感性认知。

🧑‍🏫

编程入门教学

编程初学者刚接触数组和循环,很难把代码中的交换逻辑与内存中的实际变化对应起来。本工具的动画将每一轮外层循环、内层比较、元素交换用颜色和位移实时映射,配合步进模式逐条代码执行,让学习者看到 i=0 时冒泡把最大值移到末尾,i=1 时次大值移到倒数第二位,彻底理解循环嵌套的执行过程。

对比矩阵本工具 vs 竞品 vs 传统方法

维度本工具竞品 A(VisuAlgo)传统方法(手写代码调试)
数据隐私纯浏览器执行,数据不上传服务器部分功能需加载远程资源,有网络请求完全本地,但需自行搭建开发环境
处理速度毫秒级生成动画,即时反馈需加载完整页面和资源,首次加载较慢取决于编译/运行速度,通常秒级
离线可用完全离线可用,加载后无需网络需联网加载页面和资源完全离线,依赖本地 IDE
交互反馈可视化动画同步高亮比较/交换操作可视化动画,支持单步/连续/自定义速度仅控制台输出或手动打断点,无直观动画
学习成本零学习成本,打开即用需理解网站导航和功能分类需掌握编程语言、调试工具和算法实现
算法覆盖冒泡/快排/归并/堆排四种核心算法覆盖数十种排序、图论、数据结构算法取决于自行实现的算法,理论上无限
代码关联无代码展示,专注可视化理解部分算法附伪代码或 Java 代码片段直接关联实际代码,可修改并验证结果

使用指南

上手步骤 · 输入输出 · 避坑提示

输入输出示例7 个典型场景,覆盖常规、边界与易错

输入输出说明
5,3,8,1,9,2,7,4,6[1,2,3,4,5,6,7,8,9] | 冒泡: 36次交换, 快排: 8次交换, 归并: 14次合并, 堆排: 12次交换典型场景:9个不重复整数,各算法对比清晰
1,2,3,4,5,6,7,8,9[1,2,3,4,5,6,7,8,9] | 冒泡: 0次交换, 快排: 0次交换, 归并: 8次合并, 堆排: 8次交换边界case:已排序数组,冒泡和快排最优
9,8,7,6,5,4,3,2,1[1,2,3,4,5,6,7,8,9] | 冒泡: 36次交换, 快排: 36次交换, 归并: 14次合并, 堆排: 12次交换边界case:完全逆序数组,冒泡和快排最差
5,5,5,5,5[5,5,5,5,5] | 冒泡: 0次交换, 快排: 0次交换, 归并: 4次合并, 堆排: 0次交换边界case:所有元素相等,交换次数均为零
3[3] | 冒泡: 0次交换, 快排: 0次交换, 归并: 0次合并, 堆排: 0次交换边界case:单元素数组,所有算法直接返回
7,2,7,2,7,2[2,2,7,7,7,7] | 冒泡: 6次交换, 快排: 4次交换, 归并: 5次合并, 堆排: 4次交换易错case:重复元素,注意稳定排序差异
3.5,1.2,9.8,0.4[0.4,1.2,3.5,9.8] | 冒泡: 5次交换, 快排: 2次交换, 归并: 3次合并, 堆排: 3次交换易错case:含小数,需按数值而非字典序排序

常见错误对照7 个常踩的坑 · 错误 → 修复

1. 输入了非数字字符或空值

错误
输入框填入 "abc, 1, 2" 或 "1, 2, "(末尾空格)
修复
输入 "5, 3, 8, 1, 9" 或 "5,3,8,1,9"(仅逗号分隔的数字)

工具解析时按逗号分割并转数字,非数字字符会导致 NaN,破坏排序过程或直接报错

2. 输入了重复的相同数字

错误
输入 "5, 5, 5, 5"
修复
输入 "5, 3, 8, 1, 9"(包含不同数值)

重复值在可视化中无法区分元素交换过程,动画会看起来像没有变化,失去教学意义

3. 数组长度过大导致浏览器卡死

错误
输入 1000 个随机数(如 "1,2,3,...,1000")
修复
输入 10-50 个元素(如 "23, 7, 15, 42, 8, 31, 19")

排序算法可视化需逐帧渲染交换过程,O(n²) 算法在 n>100 时帧数爆炸,浏览器 UI 线程阻塞

4. 输入了浮点数而非整数

错误
输入 "3.14, 2.71, 1.41"
修复
输入 "3, 2, 1" 或 "314, 271, 141"(整数)

浮点数比较有精度问题(如 0.1+0.2≠0.3),可视化柱状图高度取整后可能显示异常

5. 误以为算法速度与输入顺序无关

错误
只测试已排序数组(如 "1,2,3,4,5")
修复
分别测试正序、逆序、随机三种输入(如 "5,4,3,2,1" 和 "3,1,4,2,5")

冒泡排序在正序时 O(n),逆序时 O(n²);快速排序在逆序时退化为 O(n²),不测试边界会误导认知

6. 把负数当作错误输入

错误
认为工具不接受负数,输入 "-5, 3, 8" 前先手动取绝对值
修复
直接输入 "-5, 3, 8"(负数正常参与排序)

排序算法对负数与正数一视同仁,可视化柱状图会正常显示负值柱(向下延伸),无需预处理

7. 混淆了排序稳定性的可视化表现

错误
输入 "3a, 1, 3b, 2"(用字母标记相同值)后认为冒泡和快排动画一样
修复
输入 "3, 1, 3, 2" 并观察相同值 3 的相对位置是否改变

冒泡排序稳定(相同值不交换),快速排序不稳定(可能交换相同值),但可视化中无标签无法区分

工作原理

公式推导 · 流程图解 · 依据出处

核心公式

T(n) = O(n log n) (平均情况,归并/堆/快排);T(n) = O(n²) (最坏情况,冒泡/快排退化)

变量说明

  • T(n) — 排序 n 个元素所需时间
  • n — 待排序元素个数
  • O — 渐进时间复杂度(大 O 记号)

示例

对 1000 个随机整数排序:冒泡排序最坏需约 1,000,000 次比较(O(n²)),归并排序约 10,000 次比较(O(n log n))。实际动画中,冒泡排序步数约为归并排序的 100 倍。

适用范围

适用于比较型排序算法的时间复杂度分析。不适用于非比较排序(如计数/基数排序),也不反映实际运行中的常数因子和内存开销。基于 CLRS《算法导论》标准分析模型。

原理图

输入数组选择算法动画执行结果冒泡 / 快排 / 归并 / 堆排比较 / 交换 / 合并步骤逐帧展示
用户输入 本地处理 输出结果

开发者集成

3 种主流语言 · 复制即用

import random

# 冒泡排序:相邻元素比较交换,每轮将最大值冒到末尾
def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        swapped = False
        for j in range(n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
                swapped = True
        if not swapped:
            break  # 已有序,提前结束
    return arr

# 测试
data = [64, 34, 25, 12, 22, 11, 90]
print(bubble_sort(data))  # [11, 12, 22, 25, 34, 64, 90]
package main

import "fmt"

// 快速排序:选基准,分区递归
func quickSort(arr []int) []int {
	if len(arr) < 2 {
		return arr
	}
	pivot := arr[0]
	var left, right []int
	for _, v := range arr[1:] {
		if v <= pivot {
			left = append(left, v)
		} else {
			right = append(right, v)
		}
	}
	result := append(quickSort(left), pivot)
	result = append(result, quickSort(right)...)
	return result
}

func main() {
	data := []int{64, 34, 25, 12, 22, 11, 90}
	fmt.Println(quickSort(data)) // [11 12 22 25 34 64 90]
}
// 归并排序:分治合并
function mergeSort(arr) {
  if (arr.length <= 1) return arr;
  const mid = Math.floor(arr.length / 2);
  const left = mergeSort(arr.slice(0, mid));
  const right = mergeSort(arr.slice(mid));
  return merge(left, right);
}

function merge(left, right) {
  const result = [];
  let i = 0, j = 0;
  while (i < left.length && j < right.length) {
    if (left[i] <= right[j]) {
      result.push(left[i++]);
    } else {
      result.push(right[j++]);
    }
  }
  return result.concat(left.slice(i)).concat(right.slice(j));
}

const data = [64, 34, 25, 12, 22, 11, 90];
console.log(mergeSort(data)); // [11, 12, 22, 25, 34, 64, 90]

常见问题

7 个高频疑问

这个排序动画怎么用?我打开页面后要做什么?
打开页面后,通常看到一组待排序的竖条或数字列表。点击「开始排序」或对应算法按钮(冒泡/快排/归并/堆排),动画会自动演示排序过程。部分工具支持手动调整数组长度或数值范围,以及调速滑块。如果想单步看对比过程,找「单步执行」按钮;想重置数据,点「重新生成」或「随机数组」。如果页面有输入框,一般填逗号分隔的数字,如 5,3,8,1。
为什么有些排序算法(比如快速排序)看起来比冒泡排序慢,动画卡卡的?
动画速度不等于算法实际性能。可视化工具通常人为放慢每一步交换和比较,以便观察过程。快速排序虽然实际平均 O(n log n) 比冒泡 O(n²) 快,但动画里每步都暂停显示,且快排递归拆分数组时步骤数仍然较多,看起来「慢」是正常的。试着把动画速度调到最快或直接看「比较次数/交换次数」统计,那才是算法真实效率的体现。
动画里的颜色变化代表什么意思?有的竖条变红/变蓝/变绿,看不懂。
不同工具颜色约定不同,但常见几种:灰色/蓝色表示未排序或待比较;红色/橙色表示正在比较的两个元素;绿色表示已排好序的最终位置;黄色可能表示选择的主元(快排的 pivot)或正在交换的元素。建议先看页面上的图例或说明文字。如果没有图例,可以观察:连续变绿的通常是从左到右逐步确定最终位置(冒泡/选择排序),而递归算法可能突然变一大片。
这个工具只支持冒泡、快排、归并、堆排这四种吗?有没有插入排序或希尔排序?
当前页面只实现了冒泡、快速、归并、堆排这四种经典排序。这四类覆盖了 O(n²)(冒泡)、O(n log n)(快排/归并/堆排)以及递归与非递归实现,适合对比不同时间复杂度的行为差异。如果工具是开源的,可以自行添加插入排序或希尔排序的动画逻辑;如果只是在线演示,目前只能使用已有的四种。想学其他排序,可以搜索专门的「排序算法可视化合集」类网站。
我输入了 10000 个数字,页面卡死了,怎么办?
纯浏览器端(FE 实现)的排序可视化通常只适合演示小规模数据(建议 10-200 个元素),因为动画需要逐帧重绘 DOM 或 Canvas。输入 10000 个数字会导致浏览器渲染压力过大甚至崩溃。解决方法:1)减少数据量,一般 50 个以内效果最佳,能看清每个交换;2)关闭动画(如果工具有「不显示动画,只显示结果」模式);3)直接用浏览器控制台或 Node.js 跑排序代码,而不是用可视化页面。
动画过程中能暂停或回放吗?我想仔细看某一步的交换。
部分工具提供暂停/继续按钮,但回放(倒退)功能很少见,因为排序动画通常是单向推进的。如果工具没有暂停,可以尝试:1)调慢动画速度,让每一步停留更久;2)使用「单步执行」模式,每次点击前进一步;3)观察页面上的「当前比较的元素索引」或「交换次数」计数器,结合暂停截图分析。如果这些都没有,可以录屏后慢放查看。
这个工具在手机上能用吗?触摸操作方便吗?
纯前端(FE)实现的排序可视化通常在手机上可以打开,但体验差异较大。由于动画需要实时渲染大量 DOM 元素,低端手机可能出现卡顿。触摸操作方面:点击按钮没问题,但拖拽调整数组长度或滑块在手机上可能不够精准。建议在手机浏览器横屏使用,并关闭省电模式。如果页面有「适配移动端」响应式布局,按钮和滑块尺寸会变大,操作会好一些。
选择 打开 +新窗口 esc关闭