快速排序

快速排序是冒泡排序的升级版,都是通过不断交换数据来进行排序。快速排序的基本思想是:选出一个关键字,通过一次遍历,把比关键字小的数据都放到关键字左边,把比关键字大的数据都放到关键字的右边。然后在对左右两边依次进行快速排序。

由此可以看出,第一步关键字的选择很大程度上决定了快速排序的性能,如果关键字刚好选到了在中间左右的数据,那么经过一次排序后会把整段数据分成两段基本相等的数据,在进行下去效率就比较高;若果一不小心选择了最大或者最小的数据,那么一次排序下来相当于只排好了一个数据,相当不划算。为了提高性能,通常使用三数取中的方法来选取关键字,由于数据是随机排列的,可以分别在数组的左端、右端、和中间各取一个数,然后把最大的和最小的去掉,留下中间的值作为关键字,三个数同时都取得较大或者较小的概率比较小,因此可以接受。在部分情况下,还会用到九数取中的方法,就是分别取三组三个数,把三组的中数再作比较留下中间的值。

快速排序是一种不稳定的排序,其时间复杂度为O(nlogn)空间复杂度为O(logn)~O(n)

//快速排序函数
//L[]为待排序序列,low为最低位的下标,high为最高位的下标
void QuickSort(int L[], int low, int high)
{
    int middle = 0;                   //middle为关键字返回的下标
    while (low < high) {
        middle = Partition(L,low,high);  //把关键字排好位置返回其下标
        QuickSort(L, low, middle - 1);       //对关键字左边的部分进行递归快速排序
        low = middle + 1;              //对关键字右边的部分进行递归快速排序
        
    }
}

//将关键字排好顺序,这是快速排序中最重要的步骤
//L[]为待排序序列,low为最低位的下标,high为最高位的下标
int Partition(int L[],int low, int high)
{
    int middlekey = 0;
    
    //首先通过三数取中算法得到比较中值得关键字
    int m = low + (high - low) / 2;      //计算数组中间元素下标
    if(L[low] > L[high])
    {
        swap(L, low, high);       //保证高位得数比低位的大
    }
    
    if(L[m] > L[high])
    {
        swap(L, m, high);         //保证高位得数比中间的的大
    }
    
    if (L[low] < L[m])
    {
        swap(L, low, m);          //把三个数的中间值放在L[low]的位置上
    }
    
    middlekey = L[low];
    L[0] = middlekey;             //把选出来的中值备份到L[0]的位置上
    while (low < high && L[high] >= middlekey)    //当后面的值一直比中值打,则不用交换,high向前移动
    {
        high--;
    }
    
    //如果跳出while循环则代表高位的值比中值小,把高位的值覆盖到低位
    L[low] = L[high];             //此函数返回的是中值的下标,因此数据替换掉没有关系
   
    
    //对低位的处理和高位一样
    while (low < high && L[low] <= middlekey)
    {
        low++;
    }
    L[high] = L[low];
    L[low] = L[0];
    return low;
    
}

快速排序的时间复杂度:

最坏的情况:所选的关键字每次都是最大值或者最小值,这样的话快速排序就成了冒泡排序,时间复杂度为O(n^2)

最优/平均情况:第一次调用partition将整个数组扫描一遍,做n次比较。递归logn次,所以时间复杂度为O(nlogn)


空间复杂度:

最坏情况:进行n - 1次递归调用,其空间复杂度为O(n)

平均情况:O(logn)


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值