您的位置:首页 > 其它

快速排序

2013-01-30 11:29 190 查看
快速排序算法被列为20世纪十大算法之一,由Tony Hoare设计。在c++的STL、Java SDK和.net framework中都有各自的实现版本,可见其应用非常广泛。

基本思想

通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。所以快速排序的基本步骤如下:


1. 从数列中挑出一个元素,称为 "基准"(pivot)。

2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。

3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。


实现代码

void qsort_z(int sdata[], int low, int high)
{
int pivot = 0;

if (low < high)
{
pivot = partition_z(sdata, low, high);
qsort_z(sdata, low, pivot-1);
qsort_z(sdata, pivot+1, high);
}
}

int partition_z(int data[], int low, int high)
{
int pivotkey = 0;

pivotkey = data[low];
while (low < high)
{
while(low < high && data[high] >= pivotkey)
high--;
swap_z(data, low, high);
while(low < high && data[low] <= pivotkey)
low++;
swap_z(data, low, high);
}

return low;
}

void swap_z(int data[], int i, int j)
{
if (i == j) return;

int temp = data[i];
data[i] = data[j];
data[j] = temp;
}


实现代码分析

代码的核心部分是partition_z函数,它的主要作用是选取一个关键字,然后想办法将它放到一个位置,使得它左边的值都比它小,它右边的值都比它大。这个关键字称之为枢轴(pivot)。

时间复杂度

最好情况:O(nlog2n);最坏情况O(n2);平均情况:O(nlog2n)。

优化

1. 优化选取枢轴

如果所选的枢轴正好处于待排序列的中间位置,那正好可以将整个序列分成一个小数集合和一个大数集合,这样快排算法就可以达到最优性能。所以枢轴的选取尤为重要,上面的实现程序中,只是简单的将整个序列最左边的元素作为枢轴,实际上可以通过一些优化方案,使我们选择的枢轴尽可能的是整个序列的中间数。

对于小数组可能会采用三数取中median-of-three)法,即取三个关键字先进行排序,然后将中间数作为枢轴。由于整个待排序列处于无序状态,所以随机选取其中的三个数,和直接选取左中右三个数是一回事,而且取随机数还要带来时间开销,所以通常这三个关键字选取为序列的左端、中间、右端三个值。

对于非常大的待排序列,可能会使用所谓的九数取中median-of-nine)法,先从序列中分三次取样,每次取三个数,三个样品各取中数,再将这三个中数中的中数作为枢轴。

2. 优化小数组时的排序方案

如果数组非常小,使用直接插入排序会比使用快速排序算法性能更好,直接插入排序是简单排序中性能最好的。因为快排使用递归操作,如果是对于大数组,这点性能影响相对于它的整体算法优势而言可以忽略不计,但如果数组非常小,就成了大炮打蚊子。所以可以在排序算法中增加一个判断,当high-low不大于某个常数时(有资料认为7比较合适,也有人认为50比较合理),就用直接插入排序,如:

#define MAX_LENGTH_INSERT_SORT 7

void qsort_z(int sdata[], int low, int high)
{
int pivot = 0;
if ((high - low) > MAX_LENGTH_INSERT_SORT)
{
pivot = partition_z(sdata, low, high);
qsort_z(sdata, low, pivot-1);
qsort_z(sdata, pivot+1, high);
}
else
InsertSort();
}


【大话数据结构 – 读书笔记】
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: