快速排序

来源:互联网 发布:php显示图片缩略图 编辑:程序博客网 时间:2024/06/05 10:59

摘要:快速排序是一个性能良好的排序算法,目前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 10using 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;}

参考资料:《大话数据结构》

0 0
原创粉丝点击