来自Robert Sedwick的算法书中的快速排序部分的文字。
通过从数组的左侧,中间和右侧选择三个元素,我们可以将标记合并到此方案中。对三个元素进行排序,然后在中间用a[r-1]
交换一个元素,然后在a[l+1],...,a[r-2]
上运行分区算法。这种改进被称为三种方法的中位数。
三种方法的中位数有助于以三种方式快速排序。
这使得最糟糕的情况更不可能在任何实际排序中发生。对于要花费O(N^2)
时间的排序,所检查的三个元素中的两个必须是文件中最大或最小元素之一,并且此事件必须始终贯穿大多数分区。
它不需要用于分区的标记密钥,因为此功能由分区前检查的三个元素之一提供。
它将算法的总平均运行时间减少了约5%。
template <class Item>
void exch(Item &A, Item &B)
{ Item t = A; A = B; B = t; }
template <class Item>
void compexch(Item &A, Item &B)
{ if (B < A) exch(A, B); }
static const int M = 10;
template <class Item>
void quicksort(Item a[], int l, int r)
{
if (r-l <= M) return;
exch(a[(l+r)/2], a[r-1]); // line 1
compexch(a[l], a[r-1]); // line 2.
compexch(a[l], a[r]); // line 3.
compexch(a[r-1], a[r]); // line 4.
int i = partition(a, l+1, r-1);
quicksort(a, l, i-1);
quicksort(a, i+1, r);
}
template <class Item>
void hybridsort(Item a[], int l, int r)
{ quicksort(a, l, r); insertion(a, l, r); }
我对上述文字的疑问,任何人都可以用简单的例子来解释
作者的意思是“最坏的情况更不可能在任何实际的排序中出现。对于N平方时间的排序,检查的三个元素中的两个必须是最大的”?
作者的意思是“它不需要用于分区的标记密钥”?
在上面的程序中我们在上面代码中注释的第1,2,3和4行中实现了什么?
感谢您的时间和帮助!
答案 0 :(得分:3)
快速排序算法的优势在于将数据分成两半然后对每一半进行排序并合并结果。这种行为使其具有O(N log N)复杂度。然而,这是基于这样一个事实:当你将数据分成两半时,你实际上把它分成两半。然而,并非总是如此。你不只是划分数组,你将分区分成两部分,但将每个元素与分区元素(比如P)进行比较。如果一个元素小于或等于P,则它进入左子数组,否则进入右子数组。因此子阵列的大小很大程度上取决于分区元素。如果P等于数组中的最大值或最小值,则其中一个子阵列将为空,并且快速排序将从“除法阶段”中获得任何内容。如果每次都继续,那么算法的运行时间变为O(N ^ 2)
“三个中值”方法通过使分区元素成为三个所选元素的中间值元素来防止分区元素成为数组的最大或最小元素。
代码中的四行有效地将三个元素排序到位,并选择中间一个作为新分区。如果您要比较三个元素以确定中位数,您可以同时对它们进行排序。