快速排序(递归实现)

快速排序是排序很厉害的排序之一

8f996bf1516745ddbd5814a6677f9215.GIF

 

下面介绍一下快排

53b45af7ed3c4781a77f029531ceb157.GIF

 297fd12c328444c882bd842392be0986.GIF

 

源码在最后面!!!

(hoare版本)首先看一下快速排序的单趟排序

5680a2e680b04f379615da560ae46d68.png

这个是(hoare版本的单趟排序) 

下面是双指针法

ea8401d34fa4459ca837ae120c8b83be.png

单趟,双指针法比较简单(推荐) 

下面是如何递归实现

8950a2e9b75b40b597e92eb286bf7e65.png

这就是递归实现

可以结合起来看一看

b9c437f40fe34f20a0ee016a69045152.png

 

06ee31860a0740cabe10897705337aed.png 

 上面的这两个是函数测试用的

通过主函数调用

1399575d3d764ce5ab150943c4d827ed.png

给展示一下成果

1845040c855644efaa363e7447b69f1b.png 

afb98b052ced4d7583152767e431a5dd.png 

其中这两个测试用例可以测试快排的性能(数据量有点小,如果想要测试的话多放一些数据),其中快排的缺点是对于有顺序呢数据递归实现的话会多次调用函数,最终可能会StackOverflow。

如果对于有序的数据,快排的缺点也是特别明显,可能每次都会取到最大或者最小的数据,导致每次都需要交换数据,所以需要写一个三数取中

下面是三数取中

8bd4cea08605455db473a9cbd1433a09.png

可以结合上面的代码一块看

有了三数取中就可以让有序的数据也可以快速排序了。

下面是源码

 //快排

//三数取中 

//三数取中目的:面对有序最坏情况,变成选中位数做key,变成最好情况

int GetMidIndex(int* a, int left, int right)

{

 //int mid = (left + right) / 2;

 int mid = left + (right - left) / 2;

 if (a[left] < a[mid])

 {

  if (a[mid] < a[right])

  {

   return mid;

  }

  else if (a[left] > a[right])

  {

   return left;

  }

  else

  {

   return right;

  }

 }

 else //a[left] >= a[mid]

 {

  if (a[mid] > a[right])

  {

   return mid;

  }

  else if (a[left] < a[right])

  {

   return left;

  }

  else

  {

   return right;

  }

 }

}

 -----------------------------------

//hoare版本
//单趟排序
int Partion(int* a, int left, int right)
{
    //三数取中
    int mid = GetMidIndex(a, left, right);
    Swap(&a[mid], &a[left]);

    int keyi = left;//left,right是两个边界位置
    while (left < right)
    {
        //左边做keyi,右边先走
        while ((left<right) && (a[right]>= a[keyi]))//找小
        {
            --right;
        }
        while ((left < right) && a[left] <= a[keyi])//找大
        {
            ++left;
        }
        Swap(&a[left], &a[right]);
    }
    //出来后需要交换最后一个值
    Swap(&a[left], &a[keyi]);
    return left;
}

------------------------------------

//快排 挖坑法

int Partion2(int* a, int left, int right)

{

 //三数取中

 int mid = GetMidIndex(a, left, right);

 Swap(&a[mid], &a[left]);

 

 int key = a[left];

 int pivot = left;

 while (left < right)

 {

  // 右边找小, 放在坑里

  while ((left < right) && (a[right] >= key))

  {

   --right;

  }

  a[pivot] = a[right];

  pivot = right;

  // 在走左边,左边找大,放在坑里

  while ((left < right) && (a[left] < key))

  {

   ++left;

  }

  a[pivot] = a[left];

  pivot = left;

 }

 a[pivot] = key;

 return pivot;

}

------------------------------------

 

//双指针 简化

//推荐这种

int Partion3(int* a, int left, int right)

{

 //三数取中

 int mid = GetMidIndex(a, left, right);

 Swap(&a[mid], &a[left]);

 

 int keyi = left;//选择左边做keyi

 int prev = left;

 int cur = prev + 1;

 //prev指向left;

 //cur指向left+1;

 

 //先走cur,找比a[keyi]小的,找到后++prev,在交换a[prev]和a[cur];

 while (cur <= right)

 {

  if (a[cur] < a[keyi] && ++prev != cur)

  {

   Swap(&a[prev], &a[cur]);

  }

 

  ++cur;

 }

 Swap(&a[keyi], &a[prev]);

 return prev;

}

 

 ------------------------------------

 

//快速排序

//时间复杂度:O(N*logN)

void QuickSort(int* a, int left, int right)

{

 if (left >= right)

 {

  return;

 }

 // 小区间优化, 当分割到小区间时, 不在用递归思想让这段区间有序

 // 对于递归快排减少递归次数

 if (right - left+1 < 10)

 {

  InsertSort(a + left, right - left + 1);

 }

 else

 {

  int keyi = Partion3(a, left, right);

  //[left,keyi-1] keyi [keyi+1,right]

  QuickSort(a, left, keyi - 1);

  QuickSort(a, keyi + 1, right);

 }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Naxx Crazy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值