快速排序

快速排序是经常用到的一段代码,据说是最有影响力的10大算法(未考证)

说到排序,我们数一下常见的一共有几种:

冒泡、选择、插入、希尔、快排、堆排、索引、桶排其实还有一个中位数的中位数排序(名字记不得了)


时间复杂度:快排在评均的情况下nlog(n),最坏n^2

原理呢:采用分治策略,先选出一个元素,然后以此为基准,比它小的放左边,比它大的放右边,这样把区间划分成左右两部分(跟它一样大的怎么办呢?)。经过一次划分,基准元素就已经被放在正确的位置上了。然后分别对左右两个区间递归进行划分,经过n次划分最终所有元素都会被排好序。

如果每次我们选的基准元素恰好能把数组分成长度相同的2个子区间,则快排的效率是最高的,复杂度nlog(n)。

反之,如果每次总是一个子区间元素最少(0个),一个子区间元素最多(n-1个),此时快排效率最低,复杂度n^2,例如,待排序数组已经基本有序时

此处应该有证明(略)

形象化的图示请参考其他博客


看了网上的一些帖子和一些代码,总结如下:

快速排序实现有不同的版本(for和while版本),但原理一样

如果某人的代码是不完全正确的,他的代码必定忽略了一个问题,对于跟基准元素一样大的怎么处理,放左还是放右?其实就是数组中含有重复元素的情况。

根据快排的原理“比基准小的放左边,比基准大的放右边”,其实隐含着跟基准一样大的不用管!

下面4个版本的代码,v1,v2,v3可以处理重复元素的数组,v4只能对不重复的数组排序。

一定要注意v2与v4的区别

#include <iostream>

using namespace std;

//算法导论版
int partitionV1(int *a,int low,int high)
{
    int pivot=a[high];
    int i=low-1;
    int j,temp;
    for(j=low;j<high;j++)
    {
        if(a[j]<pivot)
        {
            temp=a[++i];
            a[i]=a[j];
            a[j]=temp;
        }
    }
    temp=a[i+1];
    a[i+1]=a[high];
    a[high]=temp;
    return i+1;
}
int partitionV2(int *a,int low,int high)
{
    int key=a[low];
    int i=low,j=high;
    while(i<j)
    {
        while(i<j&&a[j]>=key)j--;
        a[i]=a[j];
        while(i<j&&a[i]<=key)i++;
        a[j]=a[i];
    }
    a[i]=key;
    return i;
}
int partitionV3(int *a,int low,int high)
{
    int key=a[low];
    int i=low,j=high;
    while(i<j)
    {
        while(i<j&&a[j]>=key)j--;
        while(i<j&&a[i]<=key)i++;
        int temp=a[i];
        a[i]=a[j];
        a[j]=temp;
    }
    a[i]=key;
    return i;
}
//V4与2唯一的区别在于内层循环判断条件少了“=”
//实际上它只能对无重复元素的序列进行排序
int partitionV4(int *a,int low,int high)
{
    int key=a[low];
    int i=low,j=high;
    while(i<j)
    {
        while(i<j&&a[j]>key)j--;
        a[i]=a[j];
        while(i<j&&a[i]<key)i++;
        a[j]=a[i];
    }
    a[i]=key;
    return i;
}
void QuickSort1(int *a,int low,int high)
{
    if(low<high)
    {
        int mid=partitionV1(a,low,high);
        QuickSort1(a,low,mid-1);
        QuickSort1(a,mid+1,high);
    }
}
void QuickSort2(int *a,int low,int high)
{
    if(low<high)
    {
        int mid=partitionV2(a,low,high);
        QuickSort2(a,low,mid-1);
        QuickSort2(a,mid+1,high);
    }
}
void QuickSort3(int *a,int low,int high)
{
    if(low<high)
    {
        int mid=partitionV3(a,low,high);
        QuickSort3(a,low,mid-1);
        QuickSort3(a,mid+1,high);
    }
}
void QuickSort4(int *a,int low,int high)
{
    if(low<high)
    {
        int mid=partitionV4(a,low,high);
        QuickSort4(a,low,mid-1);
        QuickSort4(a,mid+1,high);
    }
}
int main()
{
    int a[100],n;
    cout<<"请输入要排序的数的个数:";
    while(cin>>n&&n&&n<=100)
    {
        cout<<"请输入"<<n<<"个数:";
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
        }
        cout << "PartitionV1:我是老大,排序请找我,老二老三都是跟我学的!" << endl;
        QuickSort1(a,0,n);
        for(int i=0;i<n;i++)
        {
            cout<<a[i]<<" ";
        }
        cout<<endl;
        cout << "PartitionV2:我是老二,排序请找我,老大是骗子!" << endl;
        QuickSort2(a,0,n);
        for(int i=0;i<n;i++)
        {
            cout<<a[i]<<" ";
        }
        cout<<endl;
        cout << "PartitionV3:我是老三,排序请找我,老大是骗子,我比老二厉害!" << endl;
        QuickSort3(a,0,n);
        for(int i=0;i<n;i++)
        {
            cout<<a[i]<<" ";
        }
        cout<<endl;
        cout << "PartitionV4:我是老四,学排序的时候偷懒了,功能没有他们全。" << endl;
        cout << "我只能对不重复的序列排序,毕竟比别人少俩‘=’嘛!" << endl;
        cout << "对于包含重复元素的序列,请找我大哥,二哥,或三哥!" << endl;
        cout << "如果我没有输出,那你是个坏蛋,我不理你了(死循环)!" << endl;
        QuickSort4(a,0,n);
        for(int i=0;i<n;i++)
        {
            cout<<a[i]<<" ";
        }
        cout<<endl;
    }

    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值