了解快速排序算法如何在 VBA 中重现
Posted
技术标签:
【中文标题】了解快速排序算法如何在 VBA 中重现【英文标题】:Understanding how a quicksort algorithm recurs in VBA 【发布时间】:2019-05-21 03:59:03 【问题描述】:我最近阅读了这篇文章:VBA array sort function?,看看我是否可以获得一些代码来在 Excel VBA 中实现快速排序算法。
我从帖子中获取以下代码并在 Excel 中实现:
Public Sub QuickSort(vArray As Variant, inLow As Long, inHi As Long)
Dim pivot As Variant
Dim tmpSwap As Variant
Dim tmpLow As Long
Dim tmpHi As Long
tmpLow = inLow
tmpHi = inHi
pivot = vArray((inLow + inHi) \ 2)
While (tmpLow <= tmpHi)
While (vArray(tmpLow) < pivot And tmpLow < inHi)
tmpLow = tmpLow + 1
Wend
While (pivot < vArray(tmpHi) And tmpHi > inLow)
tmpHi = tmpHi - 1
Wend
If (tmpLow <= tmpHi) Then
tmpSwap = vArray(tmpLow)
vArray(tmpLow) = vArray(tmpHi)
vArray(tmpHi) = tmpSwap
tmpLow = tmpLow + 1
tmpHi = tmpHi - 1
End If
Wend
If (inLow < tmpHi) Then QuickSort vArray, inLow, tmpHi
If (tmpLow < inHi) Then QuickSort vArray, tmpLow, inHi
End Sub
然后我使用 F8 键逐行浏览它,令我惊讶的是,它反复突出显示 End Sub 行,因为最后一个 If 语句为假,然后跳回到最后一个 If 语句,其中 tmpLow 和 inHi 的值变了!
我正在使用此网页中的数组值来尝试将第一部分中给出的逐行输出与中间的枢轴相匹配:https://www.bogotobogo.com/Algorithms/quicksort.php
我的实现与网页匹配,直到需要交换 7 和 5。此时变量具有以下值:
inLow = 0
inHi = 2
tmpLow = 2
tmpHi = 0
如您所见,两个 If 语句都不为真,因此该行传递到 End Sub。如果我再按一次 F8,突出显示会跳到最后一个 If 语句,并且变量现在具有值:
inLow = 0
inHi = 4
tmpLow = 3
tmpHi = 2
在算法的完整运行过程中会发生多次。我以前从未见过这种情况,也无法解释代码如何从 End Sub 上升,以及变量值如何在不执行任何明显代码的情况下发生变化。
如果您能帮我解决这个问题,我将不胜感激。
谢谢,
西蒙。
【问题讨论】:
你知道最后两个 if 语句递归调用 Quicksort Sub 吗? 【参考方案1】:以下代码行递归调用Sub
QuickSort
:
If (inLow < tmpHi) Then QuickSort vArray, inLow, tmpHi
If (tmpLow < inHi) Then QuickSort vArray, tmpLow, inHi
这意味着它在完成之前从它自己的代码中调用Sub
QuickSort
。
如果发生这种情况,则构建所谓的调用堆栈。此堆栈包含已调用但尚未完成的程序。它保存了此时变量的值。
您可以使用 Locals window 中的按钮 ... 查看此调用堆栈。
现在,如果当前正在运行的 Sub
QuickSort
已完成,但调用堆栈中有 Sub
的条目,则必须继续这些条目。为此,进程指针会跳转到递归调用Sub
的代码点。这将是If (inLow < tmpHi) Then QuickSort vArray, inLow, tmpHi
行或If (tmpLow < inHi) Then QuickSort vArray, tmpLow, inHi
行。将恢复也放入堆栈的其他所有变量值。然后堆叠的Sub
从那一点继续运行。依此类推,直到堆栈不再包含 Sub
QuickSort
。这就是递归的工作原理。
【讨论】:
非常感谢 Axel,您的回答简洁明了。我知道数学意义上的递归函数,但没有研究过它们如何在代码中工作。我不知道调用堆栈或本地窗口中该按钮的用途。对我来说都是很好的学习。碰巧,出于我不会让您感到厌烦的原因,我希望将算法编写为“在线” - 也就是说,不是作为一个单独的函数被调用,而是作为使用循环来完成排序的内联代码.我显然需要根据你教给我的内容来复习。问候。以上是关于了解快速排序算法如何在 VBA 中重现的主要内容,如果未能解决你的问题,请参考以下文章