乐于分享
好东西不私藏

Excel VBA 冒泡排序:一场数据界的"气泡上升运动"

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

结语:致敬经典,但别沉迷

冒泡排序是算法界的”活化石”,它见证了计算机科学的发展,就像你爷爷见证了你爸的成长。我们学习它,是为了理解排序的本质;我们优化它,是为了培养解决问题的思维;但我们生产环境中不用它,是因为我们有更高效的工具。

记住:理解经典,拥抱现代,永远不要让代码成为性能的瓶颈。