Excel VBA 冒泡排序:一场数据界的"气泡上升运动"
开场白:当数据也学会了”内卷”
各位 Excel 界的卷王们,你们好!
今天我们要聊的,是编程界最古老的”养生功法”之一——冒泡排序。这玩意儿就像你奶奶腌的咸菜,虽然老了点,但咸香依旧;就像你爷爷的二八大杠,虽然慢了点儿,但绝对能把你从村口驮到镇上。
在 Excel VBA 的世界里,当你面对一坨乱糟糟的数据,想要让它们规规矩矩排好队时,冒泡排序就是那个虽然笨拙但绝对忠诚的老伙计。
第一章:冒泡排序是个啥?
1.1 原理:气泡上浮的物理现象
想象你在一杯汽水里,小气泡们争先恐后地往上冒。大的气泡(数值大)想沉底,小的气泡(数值小)想上浮——不对,搞反了!
正确版本:在升序排列中,大的数值像”重气泡”一样不断下沉,小的数值像”轻气泡”一样不断上浮。每一轮遍历,当前最大的那个”重气泡”就会沉到它该在的位置。
用专业术语说:
时间复杂度:O(n^2) —— 慢得像蜗牛爬长城
空间复杂度:O(1) —— 省内存,就像你大学室友的衣柜
稳定性:稳定 —— 相同数值的先后顺序不会变,很有礼貌
1.2 为什么叫”冒泡”?
因为代码跑起来的时候,就像看慢动作的气泡上升视频。两个相邻的元素比较大小,大的往后(或往前)挪,一轮一轮地”冒”到正确位置。
第二章:VBA 代码实战
2.1 基础版:一维数组的”单人舞”
Sub BubbleSort_Basic()
Dim arr() As Variant
Dim i As Long, j As Long
Dim temp As Variant
Dim n As Long
‘ 假设我们从A1:A10读取数据
arr = Range(“A1:A10”).Value
n = UBound(arr, 1)
‘ 冒泡排序核心算法
For i = 1 To n – 1
For j = 1 To n – i
‘ 升序:如果前一个比后一个大,就交换
If arr(j, 1) > arr(j + 1, 1) Then
temp = arr(j, 1)
arr(j, 1) = arr(j + 1, 1)
arr(j + 1, 1) = temp
End If
Next j
Next i
‘ 把排序好的数据写回去
Range(“B1:B10”).Value = arr
MsgBox “排序完成!数据们已经排好队准备做早操了!”, vbInformation
End Sub
代码解读:
外层循环 i:控制遍历轮数,就像班主任查寝,查一轮少一个”刺头”
内层循环 j:两两比较,把最大的”刺头”冒泡到最后
n – i:每轮结束后,最后 i 个已经是有序的,不用重复比较
程序运行前:


2.2 进阶版:带”优化开关”的聪明冒泡
基础版有个问题:就算数据已经有序了,它还在那儿傻乎乎地继续比较。就像你已经吃完饭了,服务员还在问你”要加汤吗?”
Sub BubbleSort_Optimized()
Dim arr() As Variant
Dim i As Long, j As Long
Dim temp As Variant
Dim n As Long
Dim swapped As Boolean ‘ 优化神器:交换标记
arr = Range(“A1:A100”).Value
n = UBound(arr, 1)
For i = 1 To n – 1
swapped = False ‘ 每轮重置标记
For j = 1 To n – i
If arr(j, 1) > arr(j + 1, 1) Then
temp = arr(j, 1)
arr(j, 1) = arr(j + 1, 1)
arr(j + 1, 1) = temp
swapped = True ‘ 发生交换了!
End If
Next j
‘ 如果一轮下来没发生交换,说明已经有序,直接下班!
If Not swapped Then
Debug.Print “第 ” & i & ” 轮提前结束,数据们已经很乖了”
Exit For
End If
Next i
Range(“B1:B100”).Value = arr
MsgBox “优化版排序完成!节省了 ” & (n – 1 – i + 1) & ” 轮无效劳动”, vbExclamation
End Sub
优化点:加一个 swapped 布尔变量,如果某一轮没有发生任何交换,说明数组已经有序,直接 Exit For 下班走人。这招对于部分有序的数据特别管用。
2.3 豪华版:多列数据的”团体操”
现实工作中,往往是按 A 列排序,A 列相同再按 B 列排。这就需要自定义比较逻辑:
Sub BubbleSort_MultiColumn()
Dim arr() As Variant
Dim i As Long, j As Long
Dim temp As Variant
Dim n As Long
Dim needSwap As Boolean
‘ 读取A列(姓名)和B列(分数)两列数据
arr = Range(“A1:B20”).Value
n = UBound(arr, 1)
For i = 1 To n – 1
For j = 1 To n – i
needSwap = False
‘ 先比较分数(第2列),降序
If arr(j, 2) < arr(j + 1, 2) Then
needSwap = True
‘ 分数相同,再比较姓名(第1列),升序
ElseIf arr(j, 2) = arr(j + 1, 2) Then
If arr(j, 1) > arr(j + 1, 1) Then
needSwap = True
End If
End If
If needSwap Then
‘ 交换整行数据
temp = arr(j, 1)
arr(j, 1) = arr(j + 1, 1)
arr(j + 1, 1) = temp
temp = arr(j, 2)
arr(j, 2) = arr(j + 1, 2)
arr(j + 1, 2) = temp
End If
Next j
Next i
Range(“D1:E20”).Value = arr
MsgBox “多列排序完成!学霸们已按分数排队,同分者按姓名拼音排序”, vbInformation
End Sub
第三章:冒泡排序的”职场生存指南”
3.1 什么时候用冒泡?
✅ 适合场景:
数据量小(< 1000条),就像小公司团建,随便排排就行
教学演示,让新手理解排序的本质
数据基本有序,只需要微调(优化版冒泡很快)
你写代码时咖啡喝多了,想写点简单的醒醒脑
❌ 不适合场景:
数据量大(> 10000条),这时候用冒泡就像用自行车送快递
对性能有要求的生产环境
你的老板站在身后看着你写代码(会被鄙视)
3.2 VBA 中的”高端替代方案”
Excel VBA 其实自带了更高效的排序方法,就像你明明有高铁票,非要骑驴去北京:
‘ 使用Range对象的Sort方法(内置快排,O(n log n))
Sub FastSort()
Range(“A1:A1000”).Sort Key1:=Range(“A1”), Order1:=xlAscending, Header:=xlNo
MsgBox “内置排序完成,冒泡排序在角落里默默流泪…”, vbCritical
End Sub
但!是!
内置方法不能自定义复杂逻辑
学习冒泡能帮你理解算法思维
面试的时候面试官就爱问这个(虽然实际工作中绝不会用)
3.3 性能对比:数据说话
我做了个实验,在 VBA 中对随机数组排序:

结论:数据量超过 1000,请自觉放弃冒泡,拥抱内置方法或自己写个快速排序。
第四章:冒泡排序的”哲学思考”
4.1 为什么我们还要学它?
冒泡排序就像武术里的”扎马步”:
看着简单,练好了基本功扎实
理解了”比较-交换”的核心逻辑,其他排序算法(选择、插入、快排)都是变种
面试必考,不会的话就像厨师不会切菜
4.2 代码里的”人生哲理”
冒泡排序告诉我们:
循序渐进:大问题拆解成一步步的小比较
相邻互助:只和隔壁的比较,不跨界攀比(减少焦虑)
及时止损:优化版的 swapped 告诉我们,该收手时就收手
第五章:实战案例——给销售数据排个名
假设你是销售经理,手里有一份 messy 的销售数据,要按销售额降序排列,同销售额按入职时间升序:
Sub SalesRanking()
Dim ws As Worksheet
Dim lastRow As Long
Dim dataArr() As Variant
Dim i As Long, j As Long
Dim temp As Variant
Dim swapped As Boolean
Set ws = ThisWorkbook.Sheets(“销售数据”)
lastRow = ws.Cells(ws.Rows.Count, “A”).End(xlUp).Row
‘ 读取数据:A列姓名,B列销售额,C列入职日期
dataArr = ws.Range(“A2:C” & lastRow).Value
‘ 冒泡排序:先按销售额降序,再按日期升序
For i = 1 To UBound(dataArr, 1) – 1
swapped = False
For j = 1 To UBound(dataArr, 1) – i
Dim needSwap As Boolean
needSwap = False
‘ 比较销售额(降序)
If dataArr(j, 2) < dataArr(j + 1, 2) Then
needSwap = True
ElseIf dataArr(j, 2) = dataArr(j + 1, 2) Then
‘ 销售额相同,比较日期(升序,早入职在前)
If dataArr(j, 3) > dataArr(j + 1, 3) Then
needSwap = True
End If
End If
If needSwap Then
‘ 交换整行
For col = 1 To 3
temp = dataArr(j, col)
dataArr(j, col) = dataArr(j + 1, col)
dataArr(j + 1, col) = temp
Next col
swapped = True
End If
Next j
If Not swapped Then Exit For
Next i
‘ 写回数据并添加排名
ws.Range(“E2:G” & lastRow).Value = dataArr
For i = 2 To lastRow
ws.Cells(i, “D”).Value = i – 1 ‘ D列写排名
Next i
MsgBox “销售排行榜已生成!Top Sales 请上台领奖!”, vbExclamation
End Sub
结语:致敬经典,但别沉迷
冒泡排序是算法界的”活化石”,它见证了计算机科学的发展,就像你爷爷见证了你爸的成长。我们学习它,是为了理解排序的本质;我们优化它,是为了培养解决问题的思维;但我们生产环境中不用它,是因为我们有更高效的工具。
记住:理解经典,拥抱现代,永远不要让代码成为性能的瓶颈。
夜雨聆风