快速排序(递归方法)

快速排序(递归方法)

基本思想

先找到一个合适的数,作为支点pivot并放在段末尾,然后两个指针在数据段的首位,开始遍历判断,目的是为了让下标为L的位置,左侧均小于支点值(支点本身不小于支点),右侧则大于支点值(不包括数据段末尾的支点),然后L和支点位置互换。代码如下,注解很详细:

// 找到中位数 数组长度要大于3,要求三个数不相同
template<class T>
int findMed(T a[], int &i ,int &j)
{   
    if((j - i ) <  3)
        return i;
    else{    // 中位数一定是 大于一个,小于另外一个
        int k = i+(j-1)/2;
        if ((a[i]-a[k]) * (a[i]-a[j]) < 0)
            return i;
        else if ((a[k]-a[i]) * (a[k]-a[j]) < 0)
            return k;
        else if ((a[j]-a[k]) * (a[j]-a[i]) < 0)
            return j;
        else if  // 这一步感觉没啥用,因为前提条件说了三数不能相等,但是不加,编译器又会警告:control reaches end of non-void function [-Wreturn-type]
        	return i;
        }
}

// 交换函数
template<class T>
void swap(T a[], int i ,int j)
{
    T tmp = a[i];
    a[i] = a[j];
    a[j] = tmp;
}

template<class T>
void quickSort(T a[], int leftEnd, int rightEnd)
{   // 对 a[leftEnd, rightEnd] 进行排序,且a[rightEnd + 1] > a[leftEnd, rightEnd]
    if( leftEnd >= rightEnd) 
        return;

    //找一个合适的支点
    int median = findMed(a, leftEnd, rightEnd); // 尽可能找数值为中间的数
    swap(a, median, rightEnd);  // 把合适的数作为支点,放在段的末尾
    T pivot = a[rightEnd]; // 支点是在末尾

    int L = leftEnd;
    int R = leftEnd;

    // (如6 3 8 4 8,递归一次后,变成6 3 4 8 8,如果< 改为 <=,变为6 3 8 4 8)
    while (R < rightEnd)  //rightEnd 是n-2,也就是数组的倒数第二个元素
    {// 每循环一次,先做if判断,再递增1,L只有当符合条件交换后,才递增1;
    // 这样能够保证L左边放的数据,都是小于支点数据的
        if (a[R]<pivot)
        {
             // 排序操作,
            swap(a, L, R);           
            ++L;
        }
    ++R;
    } 
    //放支点,把支点放在下标为L的位置,L左边的肯定都是小于支点的数,L所指的数据,分三种情况:
        // 极端1:支点左边的都小于支点,那么最后,L=R=rightEnd=n-1,然后自己和自己交换,顺序不变;
        // 极端2:支点左边的都大于支点,那么最后,L=leftEnd, R=rightEnd=n-1,支点放在和段手数据交换,符合条件
        // 一般情况: L所指的数大于pivot,R=n-1,放支点,这样支点左边的小,右边的小;
    swap(a, L, rightEnd); 

    // 递归调用
    quickSort(a, leftEnd, L-1);
    quickSort(a, L+1, rightEnd);
}

template<class T>
void quickSort(T a[], int n)
{   // 对 a[0 : n-1] 快速排序
    if (n <= 1)  return;

    quickSort(a, 0 , n-1);
}

测试主函数:

// 测试
#include<iostream>
int main() {
    using namespace std;
    int ms[] = {6, 11, 3, 5, 2, 8};
    
    cout<< "原数列:";
    int size = 6;
    for(int i = 0;i<size;i++)
    {
        cout<< ms[i] << " ";
    }
    cout<< "\n" << "归并排序后:";
    quickSort(ms, size);
    for(int i = 0;i<size;i++)
    {
        cout<< ms[i] << " ";
    }
    return 0;
}

手写的分析:

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值