快速排序及三向切分快速排序


author: i.sshe
email: i.sshe@foxmail.com
github: https://github.com/isshe


1.快速排序

  是一种分治的排序算法。切分元素的选择关系到算法的性能,因此在排序前,应先把数据打乱。

2.快速排序的过程:

  1). 选择切分元素(一般选择切分区域第一个位置 k )。
  2). i 指向第二个元素(第一个 k ),j指向最后一个元素。
  3). i 向右移动,遇到大于等于切分元素 k 的元素时,停下。
  4). j 向左移动,遇到小于等于 k 的元素时,停下。
  5). 如果i < j,交换 i 和 j 两个位置的值。
  6). 循环2-5过程,直到 i >= j.
  7). 交换 k 位置和 i/j 位置的值。(i和j的选择,和先从左开始扫描 或 先从右开始扫描有关系)

3.1 概观:

这里写图片描述

3.2 排序过程示意图:

这里写图片描述

3.3 代码:

//这份代码是先从左边开始扫描
void quick_sort(int *array, int left, int right)
{
     int    i = 0;
     int    j = 0;
     int    select = 0;
     int    temp = 0;

     if (left >= right)
     {
         return;
     }

     i = left;      //or left+1
     j = right;
     select = array[left];

     while(1)
     {
         while(array[i] <= select)
         {
              i++;
              if (i == right) break;
         }
         while(array[j] >= select)
         {
             j--;
             if (j == left) break;
         }

         if (i >= j)
         {
              break;
         }

         temp = array[i];
         array[i] = array[j];
         array[j] = temp;
     }

     temp = array[j];
     array[j] = array[left];
     array[left] = temp;

     quick_sort(array, left, j-1);
     quick_sort(array, j+1, right);
}

4. 需要注意的细节:

  1). 原地切分:不要使用辅助数组,【更不要在递归的切分方法中创建空数组(不是很理解)】。
  2). 别越界: 主要是切分元素是最大或最小的情况.
  3). 保持随机性: 在排序前把数据打乱.
  4). 终止循环: 同时注意越界问题.
  5). 有元素和切分元素相同的情况: 左扫描时,>=; 右扫描时,<=;(等于是关键)
  6). 终止递归: 常见错误是没有把切分元素放在正确位置.

5. 快速排序优点:

  1). 内循环简洁;
  2). 比较的次数少.

6.算法改进:

  1). 切换到插入排序.(if (hi <= lo + M) {InsertSort(); return }), 这里的M一般取5~15, 最佳值和系统有关.
  2). 三取样切分: 选择数组中一小部分元素的中位数来切分数组.(一小部分一般取3!)[代价是需要计算中位数]
  3). 熵最优的排序: 实际应用中,一般都有大量重复元素, 这时候采用三向切分能提高性能.
  4). 三向切分: 把数据分三部分,左边小于切分元素,中间等于,右边大于. (lt标记小于部分,i标记等于,gt标记大于)

7. 三向切分

三向切分概观:
  这里写图片描述
三向切分排序过程示意图:
  这里写图片描述
三向切分代码:

void quick_sort3way(int *array, int left, int right)
{
    int lt = 0;
    int i = 0;
    int gt = 0;
    int v = 0;

    if (left >= right)
    {
         return ;
    }

    v = array[left];        //选择的元素
    lt = left;
    i = left + 1;
    gt = right;

    while (i <= gt)
    {
         if (array[i] < v)
         {
             exchange(array, lt, i);
             lt++;
             i++;
         }
         else if (array[i] > v)  //注意这里,i不用++
         {
              exchange(array, i, gt);
              gt--;
//              i++;
         }
         else
         {
              i++;
         }
    }

    quick_sort3way(array, left, lt - 1);
    quick_sort3way(array, gt + 1, right);
}

参考资料:

  1. <<算法 第四版>>
  • 2
    点赞
  • 5
    收藏
  • 打赏
    打赏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

i丶scream

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值