快速排序(Quicksort)是一种高效的排序算法,它在计算机科学的标准算法课程中占有重要地位。快速排序算法以其分治策略(divide-and-conquer)著称,通过递归的方式优雅地表达算法逻辑。为了帮助理解算法的执行过程,教育者通常会展示算法在特定输入上执行的跟踪过程。这种跟踪通常显示了输入数组的内容以及执行过程中的关键参数。
在JavaScript中实现快速排序算法,可以通过动画方式生动地展示算法的执行过程。动画快速排序算法可以从这里运行。界面提供了两种视图(显示列表框)。在“收缩”视图中,算法的每次调用都会显示数组,同时显示lo、hi和mid参数的值。当前数组的行显示会随着每次交换动态变化。在“扩展”视图中,每次元素交换都会在单独的行上显示数组,并且交换的元素会用不同的颜色突出显示。在两种视图中,从lo到hi的元素会用灰色背景显示,而其他元素则用白色背景显示。枢轴元素用红色前景颜色标识。
动画实现的方法与作者在“汉诺塔”文章中介绍的技术相同。作者指出,直接在要动画化的程序中放置setInterval()调用会导致混乱。一个有效的替代方法是在运行正常的未动画化程序的同时,使用栈来保存感兴趣的参数。然后处理栈,并利用JavaScript的setInterval()函数和一些视觉元素来展示算法的进度。
快速排序算法的工作原理可以通过以下JavaScript函数表示:
function Quicksort(A, lo, hi) {
if (lo < hi) {
var mid = Partition(A, lo, hi);
Quicksort(A, lo, mid - 1);
Quicksort(A, mid + 1, hi);
}
}
函数的输入是一个待排序的数组A。参数lo和hi分别表示数组中未排序部分的最低索引和最高索引。对于上述函数的初始调用,lo和hi参数分别由调用者设置为数组的第一个(最左边)和最后一个(最右边)索引。
快速排序使用分治策略,将输入数组分成两部分(部分),然后递归地对每个部分进行排序。快速排序使用一个辅助程序来执行输入的就地分区(就地意味着不使用额外的工作数组)。Partition程序的工作方式如下:它选择一个元素P,并将元素排列,使得小于等于P的元素移动到序列的左侧,大于P的元素移动到右侧。用于分区的元素P被称为枢轴元素。枢轴可以是待分区输入序列中的任何元素;然而,通常选择第一个(最左边)元素作为枢轴。
一个简单的分区输入数组的算法由前面的Partition()函数给出。注意:该函数在三处进行了修改(加粗的行),使用paramStack.push()来保存lo和hi值以及正在交换的数组元素的位置。这使用了两个指针(left和right),分别设置为要分区的数组的开始和结束。left指针向右移动,跳过小于等于枢轴的元素,而right指针向左移动,跳过大于枢轴的元素,但当left和right指针停止且left < right时,相应的元素被交换。当left和right指针相遇或相互通过时,过程结束。然后执行涉及枢轴元素和right指针指向的元素的最终交换,将枢轴放入其正确的排序位置。