快速排序及其优化方式

学过数据结构的小伙伴都知道,快速排序与冒泡排序都是交换排序,且相较于冒泡排序,快速排序应用更广,程序也相对复杂。其平均时间复杂度在O(n*logn),与希尔排序,归并排序,堆排序等“同台竞争”。但在序列有序的情况下,其时间复杂度会退化到O(n^2),甚至比不上冒泡排序。我们先来看看快速排序的代码。

void swap(int* a1, int* a2)
{
    int t = *a1;
    *a1 = *a2;
    *a2 = t;
}

void Qsort(int* arr, int left, int right)
{
    if (left >= right)
    {
        return;
    }//只有一个元素或区域不存在时返回
    //int midi = Getmid(arr, left, right);
    //swap(&arr[left],&arr[midi]);
    int key = left;
    int begin = left;
    int end = right;
    while (begin < end)
    {
        while (begin<end && arr[end]>=arr[key])
        {
            end--;
        }
        while (begin < end && arr[begin] <= arr[key])
        {
            begin++;
        }
        swap(&arr[begin], &arr[end]);
    }
    swap(&arr[key], &arr[begin]);
    Qsort(arr,left,begin-1);
    Qsort(arr, end+1, right);
}

实现的主要逻辑是递归,采取的是一种分而治之的理念。打个比方,一个数组如果在理想的条件下,快速排序每次取出数组中元素的·一半,分出来的层次少。而在有序的情况下,快速排序每次只能拿出1个元素,层次较多。为解决这个问题,我们采用“三数取中”的方式,将最左边,最右边和中间的元素进行比较。将三个数中中间大小的元素当作“轴”,就避免了有序。具体代码如下。

void swap(int* a1, int* a2)
{
    int t = *a1;
    *a1 = *a2;
    *a2 = t;
}
void Qsort(int* arr, int left, int right)
{
    if (left >= right)
    {
        return;
    }//只有一个元素或区域不存在时返回
    int midi = Getmid(arr, left, right);
    swap(&arr[left],&arr[midi]);
    int key = left;
    int begin = left;
    int end = right;
    while (begin < end)
    {
        while (begin<end && arr[end]>=arr[key])
        {
            end--;
        }
        while (begin < end && arr[begin] <= arr[key])
        {
            begin++;
        }
        swap(&arr[begin], &arr[end]);
    }
    swap(&arr[key], &arr[begin]);
    Qsort(arr,left,begin-1);
    Qsort(arr, end+1, right);
}

int Getmid(int* a, int left,int right)
{
    int midi = (left + right) / 2;
    if (a[left]< a[midi])
    {
        if (a[right] < a[left])
        {
            return left;
        }
        else if (a[midi] < a[right])
        {
            return midi;
        }
        else
            return right;
    }
    else//a[left]>=a[midi]
    {
        if (a[midi] > a[right])
        {
            return midi;
        }
        else if (a[left] < a[right])
        {
            return left;
        }
        else
            return right;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值