# 怎样让快速排序（quick sort）更快？

• 划分的过程
• 划分的基准

	template <typename Item>
int partition(Item a[], int left, int right) {
int i = left-1, j = right;
Item v = a[right];
for (;;) {
while (a[++i] < v) {}
while (a[--j] > v)
if (j == left)
break;
if (i >= j)
break;
exchange(a[i], a[j]);
}
exchange(a[i], a[right]);
return i;
}

	template <typename Item>
void exchange(Item &a, Item &b) {
Item temp = a;
a = b;
b = temp;
}

template <typename Item>
void quick_sort(Item a[], int left, int right) {
if (right-left < M)
return;
exchange(a[(left+right)/2], a[right-1]);
compare_exchange(a[left], a[right-1]);
compare_exchange(a[left], a[right]);
compare_exchange(a[right-1], a[right]);
int i = partition(a, left+1, right-1);
quick_sort2(a, left, i-1);
quick_sort2(a, i+1, right);
}

compare_exchange()比较-交换的一个封装：

	template <typename Item>
void compare_exchange(Item &a, Item &b) {
if (a > b)
exchange(a, b);
}

	template <typename Item>
void quick_sort(Item a[], int left, int right) {
if (right <= left)
return;
int i = partition(a, left, right);
quick_sort(a, left, i-1);
quick_sort(a, i+1, right);
}

	template <typename Item>
void insertion_sort(Item a[], int left, int right) {
int min, i;
for (i = left, min = 0; i <= right; ++i)
if (a[min] > a[i])
min = i;
exchange(a[min], a[left]);
if (right-left < 2)  return;
for (i = left+2; i <= right; ++i) {
Item t = a[i];
int j = i;
while (a[j-1] > t)
a[j] = a[--j];
a[j] = t;
}
}

	const int M = 16;

template <typename Item>
void quick_sort(Item a[], int left, int right) {
if (right-left < M)
return;
exchange(a[(left+right)/2], a[right-1]);
compare_exchange(a[left], a[right-1]);
compare_exchange(a[left], a[right]);
compare_exchange(a[right-1], a[right]);
int i = partition(a, left+1, right-1);
quick_sort(a, left, i-1);
quick_sort(a, i+1, right);
}

template <typename Item>
void sort(Item a[], int left, int right) {
quick_sort(a, left, right);
insertion_sort(a, left, right);
}

template <typename Item>
void quick_sort(Item a[], int left, int right) {
if (right-left < M) // prevent little array recursion
return;
// median-of-three
compare_exchange(a[left], a[(left+right)/2]);
compare_exchange(a[left], a[right]);
compare_exchange(a[right], a[(left+right)/2]);
// three-way-partition
Item v = a[right];
int i = left-1, p = left-1, j = right, q = right;
for (;;) {
while (a[++i] < v) {}
while (a[--j] > v)
if (j == left)
break;
if (i >= j)
break;
exchange(a[i], a[j]);
if (a[i] == v)
exchange(a[++p], a[i]);
if (a[j] == v)
exchange(a[--q], a[j]);
}
exchange(a[i], a[right]);
// move equal elements to middle of array
j = i-1;
i = i+1;
int k;
for (k = left; k <= p && j > p; ++k, --j)
exchange(a[k], a[j]);
j -= p-k+1;
for (k = right-1; k >= q && i < q; --k, ++i)
exchange(a[k], a[i]);
i += k-q+1;
quick_sort(a, left, j);
quick_sort(a, i, right);
}

1) 由库函数rand()生成的1000000个随机数

2) 1000000...0的逆序数

3) 100000049的重复值

 原始快速排序 改进边际效应 终极快速排序 随机数 287.05 251.67 247.71 逆序数 overflow... 163.96 90.52 重复值 172.40 150.70 35.73

对小数组改用插入排序的改进带来了约16%的性能提升，如果数据量更大，这个优化的效果应该更明显。三值取中的划分也大大加速了对特殊数据（已有序或部分有序）的排序，同时防止了划分不当导致过度递归而栈溢出的情况。

另外，终极排序做了更多的比较-交换操作却比只改进边际效应的排序还要快，原因应该是终极排序把partition放进了排序函数的内部，减少了函数调用的开销所致。最后，三路划分使得终极快排在包含大量重复值的情况下仍然很有效率，由于这个实验太特殊（所有值都相等），所以对速度的提升极其明显。

——TT

• 本文已收录于以下专栏：

举报原因： 您举报文章：怎样让快速排序（quick sort）更快？ 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)