快速排序

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值