If you're seeing this message, it means we're having trouble loading external resources on our website.

如果你被网页过滤器挡住,请确保域名*.kastatic.org*.kasandbox.org 没有被阻止.

主要内容

线性时间分区

快速排序的真正工作发生在划分步骤中,该步骤将子数组序列[p..r]分布在从子数组选择的枢轴周围。 虽然我们可以选择子数组中的任何元素作为枢轴,但如果我们选择子数组的最右边元素A[r]作为枢轴,则很容易实现分区。
选择了一个枢后,我们通过从左到右遍历它来对子数组进行分区,将每个元素与枢进行比较。 我们在子数组中保留了两个索引qj,将其分为四组。 我们使用变量名称q,因为该索引最终将指向我们的枢。 我们使用j是因为它是一个常见的计数器变量名,一旦我们完成,变量就会被丢弃掉。
  • array[p..q-1]中的元素是 “L组",由小于或等于枢的元素组成。
  • array[q..j-1]中的元素是“G组”,由大于枢的元素组成。
  • array[j..r-1]中的元素是“U组“,由与枢轴的关系为未知的元素组成,因为它们尚未被比较。
  • 最后,array[r] 是“P组”, 轴(pivot)。
最初,qj都等于p。 在每一步,我们将组A中最左边的元素A[j]与枢轴进行比较。 如果A[j]大于枢轴,那么我们只增加j,这样分组G和U的向右边滑动一位:
这是对一个子数组进行分区的一个步骤图表。子数组从索引p开始,L组有4个项,G组有索引q和6个项,U组有索引j和五个项,最后,索引r。整个步骤下来,其子数组几乎是一样的,但是G组有7个项,U组有4个项,索引j指向U组的第一个项。
如果A[j]小于或等于枢轴,那么我们将A[j]A[q](组G中最左边的元素)交换,增加j,并增加q,从而将分割组L和组G的分割线,分割组G和组U的分割线都向右滑动一个位置:
这是对一个子数组进行分区的一个步骤图表。子数组从索引p开始,L组有4组数值,G组有索引q和6个项,U组有索引j和五个项,最后,索引r。整个步骤下来,子数组在L组中有5个项 (最后一个项保存在位于索引j的项的前一个值),U组有4个项。
一旦到了枢轴,U组是空的。我们就会用G组最左侧的元素来交换枢轴:用 A[r] 交换 A[q]。这种交换把枢轴放在了L组和G组之间,即使L组和G组是空的,它也是正确的。
实现了这个想法的 分区 也回到了它最终放置枢轴的索引 q,这样一来,快速排序 就可以直接调用它,并且知道如何划分。
在子数组 array[4..9] 里,[12, 7, 14, 9, 10, 11] 的分区步骤如下:
使用n元素对子数组进行分区需要Θ(n) 时间。 每个元素A[j]与枢轴进行一次比较。 A [j]可以与A[q]交换,也可以不交换,q可以增加也可以不增加,并且j总是递增。 每个子阵列元素执行的总行数是常数。 由于子数组有n个元素,因此分区的时间是Θ(n):线性时间分区。

本内容是 达特茅斯计算机科学 教授 Thomas CormenDevin Balkcom,与可汗学院的计算课程团队合作完成。内容获得许可 CC-BY-NC-SA

想加入讨论吗?

尚无帖子。
你会英语吗?单击此处查看更多可汗学院英文版的讨论.