快速排序(分析与模板)

文章介绍了三种快速排序的方法:1)两指针法,通过调整指针找到分界元素并递归排序;2)开辟额外空间,通过创建新数组分别存储小于和大于分界元素的数;3)挖坑法,从后往前找到小于分界元素的数填坑并交换。文章强调了边界问题对正确实现的影响。
摘要由CSDN通过智能技术生成

快速排序

1.Acwing,两指针

思路:

①找分界元素 left right (left+right)/2 随机值

②调整区间,使得前指针前面的元素都>=index;后指针后面的元素都<=index

③递归左右两个区间,得到有序数组

​ 用两个指针分别指向数组的首元素外一元素,和末元素外一元素,首先自加指向数组边界元素,分别进行比较,前指针前面的元素一定会<=index,后指针后面的元素一定>=index,最后两指针相等或者交错退出循环(如果两个指针分别指向首元素和末元素,先比较在交换两个元素的时候再加减,将会导致例如数组49 59 88 37 98 97 68 54 31 3在最后排序97 98 88时,在交换97 88 之后同时指向98,在进行判断时不满足前指针小于后指针,导致提前退出,98无法放到正确的位置上)

//错误代码
void quick_sort(int num[],int left,int right){
    if(left>=right) return;
    int begin=left;
    int end=right;
    int index=num[left];
    while(begin<end){
        while(num[begin]<index) begin++;
        while(num[end]>index) end--;
        if(begin<end){
            int temp=num[begin];
            num[begin]=num[end];
            num[end]=temp;
        }
    }
    quick_sort(num,left,end);
    quick_sort(num,end+1,right);
}


//正确代码
#include <stdio.h>
void quick_sort(int num[],int left,int right){
    if(left>=right) return;
    int begin=left-1;
    int end=right+1;
    int index=num[left];//left---end,end+1;right----begin-1,begin;(left+right+1)/2,注意边界问题
    while(begin<end){
        do begin++; while(num[begin]<index);
        do end--; while(num[end]>index);
        if(begin<end){
            int temp=num[begin];
            num[begin]=num[end];
            num[end]=temp;
        }
    }
    quick_sort(num,left,end);
    quick_sort(num,end+1,right);
}
/*
为什么只使用了一个end呢?(边界问题)
①同时使用end,begin
如果数组元素为1 2
第一次1不小于1,2大于1此时两个指针分别指向1,退出循环传给第二次的参数为 0,0另一个为0,1;而我们注意到0,1与第一次传入的参数是一样的,所以会发生死循环
如果end与begin交错了,无法真正的去确定要传出的参数是什么
②如果在left情况下使用begin,第一次1不小于1,2大于1此时两个指针分别指向1,退出循环传给第二次的参数为 0,0另一个为0,1;而我们注意到0,1与第一次传入的参数是一样的,所以会发生死循环
*/

2.开辟额外空间

void quick_sort(int num[].int l,int r){
    if(l>=r) return;
    int index=num[l];
    int a[100010],b[100010];
    int m=0,n=0;
    for(int i=0;i<=r;i++){
        if(num[i]<=index){
            a[m++]=num[i];
        }else{
            b[n++]=num[i];
        }
    }
    for(int i=0;i<m;i++){
        num[l++]=a[i];
    }
    for(int i=0;i<n;i++){
        num[l++]=b[i];
    }
}

3.挖坑法

思路:
首先取出分界元素,留下一个坑位,从后往前查找小于Index的元素,将元素放到坑位中,此元素的位置变成一个坑位,最后必定是i==j的时候退出循环,将index放到这个位置,此时index前面的元素必定<=index,而后面的元素必定>=index

void quick_sort(int num[].int l,int r){
    if(l>=r) return;
    int i=l;
    int j=r;
    int index=num[index];//分界元素
    while(i<j){
        while(num[end]>=index&&i<j) end--;
        //从后向前找,找到不满足条件的元素
        num[begin]=num[end];
        //将小于index的元素放到左侧
        while(num[begin]<=index&&i<j) begin++;
        //从前往后找,找到不满足条件的元素
        num[end]=num[begin];
        //将大于index的元素放到右侧
    }
    num[end]=index;
    quick_sort(num,l,end-1);
    quick_sort(num,begin+1,r);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值