当前位置: 首页 > article >正文

周周爱学习之快速排序

        快速排序,顾名思义,快速排序是一种速度非常快的一种排序算法

  • 平均时间复杂度为O(nlog_{2}n),最坏时间复杂度为O(n^{^{2}})
  • 数据量较大时,优势非常明显
  • 属于不稳定排序

1.算法描述

  1. 每一轮排序选择一个基准点(pivot)进行分区

    1. 让小于基准点的元素的进入一个分区,大于基准点的元素的进入另一个分区

    2. 当分区完成时,基准点元素的位置就是其最终位置

  2. 在子分区内重复以上过程,直至子分区元素个数少于等于 1,这体现的是分而治之的思想 (divide-and-conquer)

  3. 从以上描述可以看出,一个关键在于分区算法,常见的有洛穆托分区方案、双边循环分区方案、霍尔分区方案

2.单边循环快排(lomuto 洛穆托分区方案)

  1. 选择最右元素作为基准点元素

  2. j 指针负责找到比基准点小的元素,一旦找到则与 i 进行交换

  3. i 指针维护小于基准点元素的边界,也是每次交换的目标索引

  4. 最后基准点与 i 交换,i 即为分区位置

代码实现

    public static void main(String[] args) {
        int[] a = {5, 3, 7, 2, 9, 8, 1, 4};
        System.out.println(Arrays.toString(a));
        quick(a, 0, a.length - 1);
    }

    public static void quick(int[] a, int l, int h) {
        if (l >= h) {
            return;
        }
        int p = partition(a, l, h); // p 索引值
        quick(a, l, p - 1); // 左边分区的范围确定
        quick(a, p + 1, h); // 左边分区的范围确定
    }

    private static int partition(int[] a, int l, int h) {
        int pv = a[h]; // 基准点元素
        int i = l;
        for (int j = l; j < h; j++) {
            if (a[j] < pv) {
                if (i != j) {
                    swap(a, i, j);
                }
                i++;
            }
        }
        if (i != h) {
            swap(a, h, i);
        }
        System.out.println(Arrays.toString(a) + " i=" + i);
        // 返回值代表了基准点元素所在的正确索引,用它确定下一轮分区的边界
        return i;
    }

3.双边循环快排(不完全等价于 hoare 霍尔分区方案)

  1. 选择最左元素作为基准点元素

  2. j 指针负责从右向左找比基准点小的元素,i 指针负责从左向右找比基准点大的元素,一旦找到二者交换,直至 i,j 相交

  3. 最后基准点与 i(此时 i 与 j 相等)交换,i 即为分区位置

要点

  1. 基准点在左边,并且要先 j 后 i

  2. while( i < j && a[j] > pv ) j--

  3. while ( i < j && a[i] <= pv ) i++

代码实现

    public static void main(String[] args) {
        int[] a = {5, 3, 7, 2, 9, 8, 1, 4};
        System.out.println(Arrays.toString(a));
        quick(a, 0, a.length - 1);
    }

    private static void quick(int[] a, int l, int h) {
        if (l >= h) {
            return;
        }
        int p = partition(a, l, h);
        quick(a, l, p - 1);
        quick(a, p + 1, h);
    }

    private static int partition(int[] a, int l, int h) {
        int pv = a[l];
        int i = l;
        int j = h;
        while (i < j) {
            // j 从右找小的
            while (i < j && a[j] > pv) {
                j--;
            }
            // i 从左找大的
            while (i < j && a[i] <= pv) {
                i++;
            }
            swap(a, i, j);
        }
        swap(a, l, j);
        System.out.println(Arrays.toString(a) + " j=" + j);
        return j;
    }


http://www.kler.cn/a/158943.html

相关文章:

  • nuget 管理全局包、缓存和临时文件夹
  • Mac 电池没电关机导致时间不同步
  • 从零入门激光SLAM(二十三)——direct_visual_lidar_calibration全型号激光雷达-相机标定包
  • 时间序列分析——移动平均法、指数平滑法、逐步回归法、趋势外推法等(基于Python实现)
  • java小练习
  • 算法沉淀一:双指针
  • Oracle merge into语句(merge into Statement)
  • java后端自学错误总结
  • 理解数据库事务和回滚:概念、实例与Python脚本实现
  • 罗技鼠标使用接收器和电脑重新配对
  • 亚信安慧AntDB受邀分享核心业务系统全域数据库替换实践
  • linux 僵尸进程 关闭看不见的进程
  • 【如何用批处理文件实现自动编译Keil工程和C# Visual Studio工程】
  • 用C语言实现单链表
  • 数据结构中处理散列冲突的四种方法
  • 控制台电商项目实现
  • 前端食堂技术周刊第 107 期:技术播客节、Deno Cron、FEDAY、XState v5、Electron 2023 生态系统回顾
  • C++ 12.5作业
  • unaipp引入echarts图表,小程序端能正常显示打包
  • 智能优化算法应用:基于堆优化算法无线传感器网络(WSN)覆盖优化 - 附代码
  • CC++内存管理方式
  • 第18章 C++11标准库(STL)
  • Spring Cloud + Vue前后端分离-第3章 SpringBoot项目技术整合
  • 亚马逊云科技AI创新应用下的托管在AWS上的数据可视化工具—— Amazon QuickSight
  • Hadoop学习笔记(HDP)-Part.07 安装MySQL
  • 生产实践:Redis与Mysql的数据强一致性方案