快速排序是一种分而治之的方法吗? [关闭]
Posted
技术标签:
【中文标题】快速排序是一种分而治之的方法吗? [关闭]【英文标题】:Is Quick Sort a Divide & Conquer approach? [closed] 【发布时间】:2017-05-12 09:38:45 【问题描述】:我认为归并排序是分而治之的,因为,
划分 - 数组按字面意思划分为子数组不做任何处理(比较/交换),问题大小减半/四分/....
征服 - merge()
通过处理(比较/交换)
代码给人的印象是分而治之,
if(hi <= lo) return;
int mid = lo + (hi-lo)/2; //No (compare/swap) on elements before divide
sort(a, aux, lo, mid); // Problem is halved(Divide)
sort(a, aux, mid+1, hi);
merge(a, aux, lo, mid); // (Compare/swap) happens here during Merge - Conquer
Merge sort trace 说,这个问题被细化然后处理,
但在快速排序中,
首先,使用分区元素(pivot)处理(比较/交换)完整数组并固定枢轴的最终位置,然后问题大小减半/ Quartered/.... 用于重新分区,
代码不会给人一种分而治之的印象,
if(hi <= lo) return;
int j = partition(a, lo, hi); // Do you call this divide phase?
sort(a, lo, j-1); // This looks like divide phase, because problem is halved
sort(a, j+1, hi);
快速排序跟踪,显示处理是在完整数组上开始的,然后达到粒度级别,
问题:
我对划分阶段的理解意味着,减少(一半)问题规模。在快速排序中,您是否将使用枢轴处理(比较/交换)数组和分区作为划分阶段?
我对征服阶段的理解意味着,收集/合并回来。在快速排序中,征服阶段是什么意思?
Note: Am a beginner, in sorting algorithms
【问题讨论】:
也许添加language-agnostic
标签??
@JosephWood 我添加了 C 语法
Wiki 在divide and conquer algorithms 的部分列表中包含快速排序,但正如您所指出的,在快速排序的情况下,在除法发生之前对当前数组或子数组完成了一些工作.在除法产生两个大小为 1 的子数组之前,纯归并排序不会进行任何合并。自下而上的归并排序跳过递归并开始将大小为 n 的数组划分为大小为 1 的 n 个子数组。这是一个问题术语。
如果你认为划分的过程必须是零成本,那么快速排序并不是零成本进行划分,也不是分而治之。但是,AFAIK,除法并非总是期望为零成本,我认为快速排序是一种分而治之的算法。
@JonathanLeffler 我对 divide 的理解是,问题大小减半,仅此而已(无比较/交换)。处理或不处理问题减半,是不太严重的一点。在给定的语法中,partition(a, lo, hi)
与 Mergesort 中的 sort(a, aux, lo, mid);
不同,在快速排序中问题的一半
【参考方案1】:
分治算法有 3 个阶段:
-
除,
征服,
结合,
对于合并排序(http://www.cs.umd.edu/~meesh/351/mount/lectures/lect6-divide-conquer-mergesort.pdf):
-
除法:将数组拆分为2个子数组,
征服:合并对结果子数组进行递归排序,
合并:将两个排序的子数组合并到一个排序列表中。
用于快速排序 (https://www.cs.rochester.edu/~gildea/csc282/slides/C07-quicksort.pdf):
-
除法:先重新排列再将数组拆分成2个子数组,
征服:快速对生成的子数组进行递归排序,
组合:无。
注意:感谢罗切斯特大学和马里兰大学计算机系。
【讨论】:
如果您看到代码,那么快速排序不会先将数组拆分为 2。首先,partition(a, lo, hi);
使用给定的枢轴对元素进行分区。接下来,将数组拆分为 2 稍后由 sort(a, lo, j-1);
完成
分区操作为拆分操作。快速排序的“组合”操作可以被认为是在快速排序的一个有效实现中附加两个数组,但对于“就地”排序则不适用。以上是关于快速排序是一种分而治之的方法吗? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章