ACM模板 - 排序 - 快速排序(三数取中 + 插排 + 聚集相等元素)

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a);

using namespace std;

typedef long long ll;

const int maxn=3e6+100;

int arr[maxn];

/* 直接插入排序 */
void InsertSort(int low,int high)
{
    int i,j;
    for(i=low+1;i<=high;i++)
    {
        if(arr[i]<arr[i-1])
        {
            arr[0]=arr[i];
            arr[i]=arr[i-1];
            for(j=i-2;arr[0]<arr[j];j--)
                arr[j+1]=arr[j];
            arr[j+1]=arr[0];
        }
    }
}

/* 取待排序序列中low、mid、high三个位置上数据,选取他们中间的那个数据作为枢轴 */
int SelectPivotMedianOfThree(int low,int high)
{
    int mid=low+((high-low)>>1); // >> 优先级低于 + -

    if(arr[mid]>arr[high]) swap(arr[mid],arr[high]);
    if(arr[low]>arr[high]) swap(arr[low],arr[high]);
    if(arr[mid]>arr[low]) swap(arr[mid],arr[low]);

    return arr[low]; // low的位置上保存这三个位置中间的值
}

/* 快排 */
void QSort(int low,int high)
{
    int first,last,left,right,llen,rlen;
    first=left=low, last=right=high, llen=rlen=0;

    if(high-low+1<=10)
    {
        InsertSort(low,high);
        return;
    }

    int key=SelectPivotMedianOfThree(low,high);

    while(low<high)
    {
        while(high>low && arr[high]>=key)
        {
            if(arr[high]==key)
            {
                swap(arr[right],arr[high]);
                right--, rlen++;
            }
            high--;
        }
        arr[low]=arr[high];

        while(high>low && arr[low]<=key)
        {
            if(arr[low]==key)
            {
                swap(arr[left],arr[low]);
                left++, llen++;
            }
            low++;
        }
        arr[high]=arr[low];
    }
    arr[low]=key;

    // 一次快排结束,把与枢轴 key 相同的元素移到枢轴最终位置周围
    int i=low-1, j=first;
    while(j<left && arr[i]!=key)
    {
        swap(arr[i],arr[j]);
        i--, j++;
    }

    i=low+1, j=last;
    while(j>right && arr[i]!=key)
    {
        swap(arr[i],arr[j]);
        i++, j--;
    }

    QSort(first,low-1-llen);
    QSort(low+1+rlen,last);
}

int main()
{
    int n; scanf("%d",&n);

    for(int i=1;i<=n;i++)
        scanf("%d",&arr[i]);

    QSort(1,n);

    for(int i=1;i<=n;i++)
    {
        if(i==1)
            printf("%d",arr[i]);
        else
            printf(" %d",arr[i]);
    }
    puts("");

    return 0;
}

Ps1:三数取中+插排+聚集相等元素,它和STL中的Sort函数效率差不多。

Ps2:尾递归:测试数据分析,其实这种优化编译器会自己优化,相比不使用优化的方法,时间几乎没有减少。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

放羊的牧码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值