O(nlogn)快速排序-基础版+详细注释

相关使用的工具类与接口
在这里插入图片描述
运行效率

    /**
     * 这是一个快速排序
     * 数组长度[2000] 值范围[1-2000] 消耗的时间为[1]毫秒
     * 数组长度[4000] 值范围[1-4000] 消耗的时间为[1]毫秒
     * 数组长度[8000] 值范围[1-8000] 消耗的时间为[1]毫秒
     * 数组长度[16000] 值范围[1-16000] 消耗的时间为[1]毫秒
     * 数组长度[32000] 值范围[1-32000] 消耗的时间为[1]毫秒
     * 数组长度[64000] 值范围[1-64000] 消耗的时间为[3]毫秒
     * 数组长度[128000] 值范围[1-128000] 消耗的时间为[6]毫秒
     * 数组长度[256000] 值范围[1-256000] 消耗的时间为[16]毫秒
     * 数组长度[512000] 值范围[1-512000] 消耗的时间为[35]毫秒
     * 数组长度[1024000] 值范围[1-1024000] 消耗的时间为[71]毫秒
     * 数组长度[2048000] 值范围[1-2048000] 消耗的时间为[153]毫秒
     * 数组长度[4096000] 值范围[1-4096000] 消耗的时间为[325]毫秒
     * 数组长度[8192000] 值范围[1-8192000] 消耗的时间为[675]毫秒
     * 数组长度[16384000] 值范围[1-16384000] 消耗的时间为[1397]毫秒
     * 数组长度[32768000] 值范围[1-32768000] 消耗的时间为[2890]毫秒
     * 数组长度[65536000] 值范围[1-65536000] 消耗的时间为[6031]毫秒
     * 数组长度[131072000] 值范围[1-131072000] 消耗的时间为[12727]毫秒
     * 数组长度[262144000] 值范围[1-262144000] 消耗的时间为[25993]毫秒
     * <p>
     * Process finished with exit code 0
     */
    @Test
    public void quickSortTest() {
        ArraysSort arraysSort = new QuickSortMethod();
        SortHelper.arraySort(arraysSort, 2000, 20);
    }

实现代码


    public static final Random RANDOM = new Random();

    @Override
    public String getSortName() {
        return "这是一个快速排序";
    }

    @Override
    public int[] arraySortMethod(int[] ints) {
        sort(ints, 0, ints.length - 1);
        return ints;
    }


    /**
     * 最初的快排算法逻辑
     *
     * @param ints 整个数组
     * @param l    当前最小索引
     * @param r    当前最大索引
     */
    private int quickSort(int[] ints, int l, int r) {
        //这里以每个l记录进行比较
        //但是这里有个问题
        //在快速排序处理近乎有序的数组时 如果默认选取的是最左侧索引节点
        //这样会造成左分块除了l近乎没有,右分块又会出现很多
        //以此循环会造成递归树非常深 递归树的深度可能就无限接近于n长度
        //如果是这样的话 该排序的时间效率就无限接近n^2

        //每次随机选取l-r一个索引 与l 索引进行交换就解决了该问题
        SortHelper.swap(ints, l, RANDOM.nextInt(r - l + 1) + l);
        int v = ints[l];

        //初始化开始记录比v小和比v大的中间索引点
        //j理论上记录的是比v小的最大索引
        int j = l;
        for (int i = l + 1; i <= r; i++) {
            //如果出现比v小的情况
            //就需要做交换 移动j的索引后移一格
            if (ints[i] < v) {
                //每次j+1=比v大一边的第一个索引
                //让大一边第一个索引和当前循环到的这个索引做交换
                //以上交换后j+1=比v小一边的最后一个索引
                //之前比v大一边的第一个索引就跑到i索引下 也是当时大一边的最后一个索引
                SortHelper.swap(ints, ++j, i);
            }
        }
        //到这里j记录的就是比v小一边的最大索引
        //以上循环完成后就可以确定l索引在ints数组中排序的位置
        SortHelper.swap(ints, j, l);
        //返回l在ints中排好序确定的索引位置 并以j分割继续递归排序
        return j;
    }

    /**
     * 最初的快排算法逻辑
     *
     * @param ints
     * @param l
     * @param r
     */
    public void sort(int[] ints, int l, int r) {
        //在出现左索引等于右索引的时候
        //它们都是指向同一索引所以没有相比的必要
        //这里直接返回
//        if (l >= r) {
//            return;
//        }

        //在数据量较小的时候使用插入排序
        //这是因为经过了r-l>15的快速排序后 小一边和大一边的模糊排序后
        //在r-l<=15 的时候之间的最大差已经很小了
        //在最大差越小的情况下顺序可能是越有序的
        //说不定已经近乎有序的了 优化的快速排序对近乎有序的排序效率非常高
        //优化后的插入排序对近乎有序的数组进行效率相对较高
        //插入排序相对归并排序减少了数组交换的过程
        if (r - l <= 15) {
            InsertSortMethod.insertSortMethod(ints, l, r);
            return;
        }

        //个人理解快排核心
        //每次遍历排序对l-r之间的数组进行区分
        //好处1.每次遍历可以定位一个p索引在ints数组中确定的位置
        //好处2.因为每次排序都对l-r之间的数据进行大小划分做了一次模糊的排序
        //保证下次排序l-r排序之间最大差越来越小
        //所以下次遍历都比上次排序更加有序效率相对更快
        int p = quickSort(ints, l, r);
        //以p中心点-1和+1为界限继续递归快速排序
        sort(ints, l, p - 1);
        sort(ints, p + 1, r);
    }
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
时间复杂度为O(nlogn)的排序算法有希尔排序,堆排序快速排序和归并排序。其中归并排序是一种稳定的排序算法,而希尔排序、堆排序快速排序是不稳定的排序算法。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python-归并排序算法.docx](https://download.csdn.net/download/qq_43934844/87893705)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [时间复杂度O(nlogn)的排序算法](https://blog.csdn.net/qq_43533956/article/details/123978524)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [时间复杂度为O(nlogn)的排序算法](https://blog.csdn.net/qq_46130027/article/details/129765856)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值