前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >十大经典排序算法:快速排序debug分析排序过程

十大经典排序算法:快速排序debug分析排序过程

作者头像
冷环渊
发布2022-01-26 08:36:17
2760
发布2022-01-26 08:36:17
举报

前言

★ 这里是小冷的博客 ✓ 优质技术好文见专栏 个人公众号,分享一些技术上的文章,以及遇到的坑 当前系列:数据结构系列 源代码 git 仓库 ‘ 数据结构代码地址 代码Git 仓库地址

目录

快速排序

快速排序法介绍:

快速排序(Quicksort)是对冒泡排序的一种改进。基本思想是:通过一趟排序将要排序的数据分割成独立的两 部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排 序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

思路分析
image-20220125233740379
image-20220125233740379

快速排序的思路由上图所示:

  • 首先是找到一个基准点,这个不一定非要是中位数,也可以是任意一位,可以自主分割,在什么位置都可以,这里我们以中位来学习
  • 根据中位数为基准,将需要排序的数组分为两份,之后分别交换位置,保证比中位数小的都在左边,比中位数的都在右边,此时左右两边虽然无序,但是都保证一定规则
  • 之后按照递归,再次将左边选出中位数,右边选出中位数,递归到不能交换为止
image-20220126003428506
image-20220126003428506
快速排序案例

要求: 对 [-9,78,0,23,-567,70] 进行从小到大的排序,要求使用快速排序法。【测试 8w 和 800w】 说明[验证分析]:

  1. 如果取消左右递归,结果是 -9 -567 0 23 78 70
  2. 如果取消右递归,结果是 -567 -9 0 23 78 70
  3. 如果取消左递归,结果是 -9 -567 0 23 70 78
代码语言:javascript
复制
public static void quickSort(int[] arr, int left, int right) {
        //  left index
        int l = left;
        int r = right;
        //    pivot 中轴值
        int pivot = arr[(left + right) / 2];
        //临时变量
        int temp = 0;
        //    while 循环的目的是比比中轴的pivot值小的放在左边
        //    比pivot 值大的放在右边
        while (l < r) {
            //    在pivot的左边一直寻找 找到大于等于pivot 的值才退出
            while (arr[l] < pivot) {
                l += 1;
            }
            //    在pivot的右边一直寻找 找到小于等于pivot 的值才退出
            while (arr[r] > pivot) {
                r -= 1;
            }
            //    如果 l>=r说明pivot的左右两个值已经按照左边全都是小于等于pivot,右边去哪不是大于等于pivot排列好了
            if (l >= r) {
                break;
            }
            //    交换
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;
            //    如果交换玩发现这个arr[l]==pivot值 相等r--前移
            if (arr[l] == pivot) {
                r -= 1;
            }
            //如果交换玩发现 arr[r] == pivot值 相等l++ 后移
            if (arr[r] == pivot) {
                l += 1;
            }
        }
        //    如果l==r 必须是 l++ r-- 否则会出现栈溢出
        if (l == r) {
            l += 1;
            r -= 1;
        }
        //向左递归
        if (left < r) {
            quickSort(arr, left, r);
        }
        //向右递归
        if (right > l) {
            quickSort(arr, l, right);
        }
    }
排序过程断点调试

int arr[] = {-9, 78, 0, 23, -567};

我们的测试数组是一个五位数的数组,

image-20220126004245905
image-20220126004245905

进入循环,此时我们看到,中位数和左右两边的索引,0和4

这里我们可以看第一组数据,

下标0 arr[l] =- 9, -9小于0于是 左边下标后移继续寻找,找到78,此时l = 1 是78对应的数组下标 此时的78 比中位 0 要大,进入右侧比对

image-20220126004606466
image-20220126004606466

显然 arr[r] = -567 比中位数小,不需要改变下标,跳出循环,

此时我们对比因为我们之后需要重复的递归,这里就是我们递归的跳出条件,如果左边大于右边了,代表左边已经没有大于中位数的数了,反之右边也一定没有小于中位数的

image-20220126004743992
image-20220126004743992

此时,交换两边不符合条件的数字,将比0大的七十八交换到右边吗,将比0小的-567交换到左边

image-20220126005002346
image-20220126005002346

交换完成之后,判断左右两边此时小标的数字是否与中位数相等,如果相等就后移,不需要重复比对

此时我们的第一次循环就结束了,可以看到,数组已经被交换到了,我们的思路第一步的样子,

比中位数0 小的都在左边,比中位数0大的都在右边,之后我们需要重复递归,一直到交换不了为止

image-20220126005253580
image-20220126005253580

此时 r 与l相等,就代表都到中位数了,左右两边都递归有序了,此时我们需要将l后一位,r前移一位,防止栈溢出,并且再继续向下,再最后一次递归之前会结束,

image-20220126005555036
image-20220126005555036

后面的递归就是重复的分组重复的交换,一直到左索引小于又索引,代表还可以继续分组排序,直到左边递归完毕

右索引大于左索引代表可以继续向右边递归,一直到右边递归完毕

image-20220126010021201
image-20220126010021201
快速排序测速

八十万长度存放0-80w的随机数

image-20220126010205710
image-20220126010205710

可以看到,效率是十分的快速

image-20220126010443742
image-20220126010443742

有兴趣的小伙伴可以自己试试写一个冒泡排序测试一下,再拿小冷的快速排序测试一下,算法的精妙之处一下就能感受到了

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-01-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
    • 目录
      • 思路分析
      • 快速排序案例
      • 排序过程断点调试
      • 快速排序测速
  • 快速排序
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档