摘要:快速排序是一个性能良好的排序算法,目前C++的STL中的sort()内部实现也是依靠快速排序,本文简要介绍快排和代码实现。
关键字:排序算法,快速排序,数据结构
前提说明:整数数组,目标是从左到右为依次递增
步骤
(1)选择一个最接近于整个数组平均数的数,作为pivot,放在数组的第low位置;
(2)从数组的尾部向首部开始搜索,比较,找出比pivot要小的数,放在数组的第low位置;
(3)从数组的首部向尾部开始搜索,比较,找出比pivot要大的数,放在数组的第high位置;
不断重复(2)和(3),知道low和high相遇就停止,此时,pivot处于整个数组比较中间的位置,而pivot位置的左边子数组中所有的数比pivot小,pivot位置的右边子数组中所有的数比pivot大,形成了一个初步有序的状态。然后左边数组和右边数组分别执行(1)(2)(3)的操作,直到整个数组基本有序。
优化
在这里,有4个地方是可以进行优化的。
第一,选择一个怎么样的pivot,这是很重要的,只有当pivot尽可能接近于整个数组的平均数时,效率是最高的。很多书上说是取数组的第一个元素,这是不严谨的。常用的方法有3数取中,即取首中尾3个元素的中间元素作为pivot。
第二,在(2)和(3)中交换元素时,也可以进行优化,这里说的优化主要是指pivot的移动。许多版本的代码中是使用swap(low,high),首先pivot取自于data[low],在尾部指针找到交换的数后,和pivot交换,此时pivot处于high指针这个位置,而下一步,首部指针找到可交换的数时,又把pivot交换到data[low]这里来,由此反反复复,pivot的位置经历了很多次不必要的赋值。因此,这里可以优化为,把交换变为赋值,当尾部指针找到满足条件的数时,直接把high位置的数赋值到low位置,即data[low]=data[high];而当首部指针找到可交换的数时,直接把low位置的数赋值到high位置,即data[high]=data[low];当low和hign相遇后,再把pivot赋值给data[low];
第三,优化小数组的排序。快速排序使用了递归,递归伴随着对栈的操作,这属于额外的性能开销。当数据量很大时,栈的操作相对来说占的比重就比较小,但是数据量不大 时,这个操作的性能消耗占的比重就不小了。因此可以尝试着,当数据量小时,使用直接插入排序,当数据量大时,使用快速排序。当然,这感觉不算是快速排序的范畴里了。
第四,第三点说到,快排使用了递归,也就使用了栈,而栈是属于处理器内部的存储空间,大小十分有限,而快排处理的数据量一般比较大,所以对栈空间大小是有严格要求的。假如出现极端情况,即pivot的划分很不合理,那么就有可能出现pivot两边的数组中,有一个数组的元素个数会接近于n,那么递归的深度也接近于n,这开销确实不容小觑。因此,可以实施尾递归优化。即先对[low,pivot]这部分数组进行递归排序,下一次排序low去pivot+1,然后再重新选取新的pivot,如此进行直到整个数组有序。这就极大的保证了递归的深度和占用栈的空间大小。
代码
#include<iostream>
#define ARRAY_SIZE 10
using namespace std;
void swap(int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
int partion(int v[], int low, int high)
{
// 关键字取左中右三数之中
int pivot, m;
m = low + (high - low) / 2;
if(v[low] > v[high])
swap(v[low], v[high]);
if(v[m] > v[high])
swap(v[m], v[high]);
if(v[m] > v[low])
swap(v[m], v[low]);
pivot = v[low];
while(low < high)
{
while(low < high && v[high] >= pivot)
high--;
//swap(v[low], v[high]);
v[low] = v[high];
while(low < high && v[low] <= pivot)
low++;
//swap(v[low], v[high]);
v[high] = v[low];
}
v[low] = pivot;
return low;
}
void qsort(int v[], int low, int high)
{
int pivot;
while(low < high)
{
pivot = partion(v, low, high);
qsort(v, low, pivot - 1);
low = pivot + 1;
}
}
int main(void)
{
int v[ARRAY_SIZE] = { 7,1,5,6,8,4,2,3,9,0 };
qsort(v, 0, ARRAY_SIZE - 1);
for(int i = 0; i < ARRAY_SIZE; i++)
{
cout << " " << v[i];
}
return 0;
}
参考资料:《大话数据结构》