算法-9-快速排序

2023-05-16

目录

1、描述

2、特点

3、代码实现

3.1、切分函数partition()图示

4、性能

5、快速排序优化(小数组插入排序)

6、快排优化(三向切分)


1、描述

快速排序也是基于递归实现的。和归并排序不同的是:归并排序将数组不断的二等分,而快速排序是根据子数组的第一个元素的大小将数组分成两部分的。

第一步:根据数组的第一个元素a[0]=key的大小,将比key小的子数组a中,将比key大的放在子数组b中。

第二步:将子数组a 、子数组b和key合并成一个数组,key放在了中间位置。

第三步:继续将子数组a继续进行第一二步,b也一样。

..................不断递归,这个数组就变得有序了。

{注意:这里的子数组a,b只是抽象的概念,实际的算法为了节省空间消耗,是在原数组身上来对数组进行拆分的。}

                               

2、特点

  • 时间复杂度O(N*lgN)
  • 原地排序(不需要太多额外空间,只需要一个很小的辅助栈)
  • 快速排序的内循环比大多数排序算法都要短小,所以它在理论和实际上都要更快。
  • 主要缺点:非常脆弱,要非常小心才能避免低劣的性能。

3、代码实现

public class Quick {

    public static void sort(double[] a) {
        sort(a, 0, a.length - 1);
    }

    public static void sort(double[] a, int lo, int hi) {
        if (lo >= hi)
            return;
        int mid = partition(a, lo, hi);
        sort(a, lo, mid - 1);
        sort(a, mid + 1, hi);
    }

    private static int partition(double[] a, int lo, int hi) {
        double key = a[lo];
        int left = lo;
        int right = hi + 1;
        while (true) {

            while (key > a[++left])  if (left == hi) break;
            while (key < a[--right]) if (right == lo) break;

            if (left >= right) break;
            exch(a, left, right);
        }

        exch(a, lo, right);
        return right;
    }

    private static void exch(double[] a, int i, int j) {
        double temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

    private static void show(double[] a) {
        System.out.println("\n");
        for (double item : a) {
            System.out.print((int) item + ",");
        }
    }

    public static void main(String[] args) {
        double[] a = { 55, 43, 23, 12, 13, 11, 7, 8, 88, 6, 3, 2, 4, 1, 9, 8, 7, 11, 56, 45, 22, 23,
                45, 66 };
        sort(a);
        show(a);
    }
}

3.1、切分函数partition()图示

                                                 

4、性能

优势:快速排序切分方法的内循环会用一个递增的索引将数组元素和一个定值比较。这种简洁性 也是快速排序的一个优点,很难想象排序算法中还能有比这更短小的内循环了。例如,归并 排序和希尔排序一般都比快速排序慢,其原因就是它们还在内循环中移动数据。

风险:在切分不平衡时这个程序可能会 极为低效。例如,如果第一次从最小的元素切分,第二次从第二小的元素切分,如此这般,每次调用 只会移除一个元素。这会导致一个大子数组需要切分很多次。我们要在快速排序前将数组随机排序的 主要原因就是要避免这种情况。它能够使产生糟糕的切分的可能性降到极低,我们就无需为此担心了。

总结:总的来说,可以肯定的是对于大小为 N 的数组,快速排序 的运行时间在 1.39NlgN 的某个常 数因子的范围之内。归并排序也能做到这一点,但是快速排序一般会更快(尽管它的比较次数多 39%),因为它移动数据的次数更少。

5、快速排序优化(小数组插入排序)

当我们将大的数组递归拆分成小的数组的,数组长度低于7的时候,我们使用插入排序,而不是让它继续递归下去,这样可以加快排序的速度。

                                       

6、快排优化(三向切分)

三向切分是为了解决数组中存在大量重复数据进行的一种优化,原版快速排序是将数组分成 大于key,和小于key两部分,现在将数组分成大于,小于,和等于三部分。

对于存在大量重复元素的数组,这种方式的排序要比标准的快速排序效率高很多。

  public static void sort(double[] a) {
        sort(a, 0, a.length - 1);
    }

    public static void sort(double[] a, int lo, int hi) {
        if (lo >= hi)
            return;

        double key = a[lo];
        int left = lo;
        int right = hi;
        int  i=lo+1;
        while (i<=right) {

            if (a[i]<key)exch(a,i++,left++); //将比key小的放在子数组的前面
            else if (a[i]>key)exch(a,i,right--);//将比key大的放在子数组的后面
            else   i++;//如果等于,就跳过继续下一个
        }

        sort(a, lo, left - 1);// {3,2,1,4,4,4,4,9,8,7}继续递归{3,2,1}的部分
        sort(a, right + 1, hi);// {3,2,1,4,4,4,4,9,8,7}继续递归{9,8,7}的部分
    }

    private static void exch(double[] a, int i, int j) {
        double temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

算法-9-快速排序 的相关文章

随机推荐

  • 知识点2:Swift REPL

    关于REPL简介 REPL xff1a 英文缩写 xff08 Read Eval Print Loop xff09 即读取 执行 输出 循环的意思 Xcode 6 1 引入了另一种以交互式的方式体验Sw ift的方法 主要特点 xff1a
  • iOS 关于UIAlertController常见使用方法

    Step 1 警告框 1 代码 1 创建提示窗口 参数1 xff1b Title xff1a 标题 参数1 xff1b message xff1a 提示内容 参数1 xff1b Style 风格 UIAlertControllerStyle
  • 2023年最新版kali linux安装教程

    一 前期准备 前排提醒 xff0c 文末有绿色版安装包免费领取 xff01 二 VMware虚拟机配置 1 打开vmware xff0c 点击创建新的虚拟机 2 选择自定义 高级 选项 xff0c 点击下一步 3 继续下一步 4 选择 稍后
  • CentOS7.1下 安装vncserver和删除vnc占有的端口

    今天给两台新服务器装CentOs7 1系统 xff0c 然后装VNCServer的时候感觉网上的教程要么复杂多此一举 xff0c 要么不清楚 xff0c 关于 list端口的部分都没讲 所以这里整理一下 xff0c 按着下面的顺序来就可以了
  • mac使用虚拟机(VirtualBox+centos7)搭建kubernetes(K8S)集群

    文章目录 说明一 环境准备1 配置主机网络2 配置磁盘空间3 安装虚拟机配置网络4 设置Linux环境 三台均需要设置 二 安装docker kubeadm kubelet kubectl 三台均需要设置 1 安装docker环境2 kub
  • .NET6入门:1.Windows开发环境搭建

    作为 NET的最新版本 NET6长期支持版已经发布 xff0c NET6宣称是迄今为止最快的 NET 那当然不能落下时代的潮流 xff0c 就让我们跟着文章进入 NET6的世界吧 1 NET6SDK下载 Download NET Linux
  • 音视频编解码原理(一) 封装格式和编码方式简介

    一 封装格式 要了解音视频编解码原理 xff0c 首先需要知道什么是封装格式 xff1f 所谓封装格式 xff0c 就是将已经编码压缩好的视频轨和音频轨按照一定的格式封装到一个文件中 xff0c 一般情况下 xff0c 不同的封装格式对应不
  • VS调试方法总结(二)

    通过结构化异常定位崩溃程序 程序崩溃时 xff0c 生成文本文件 xff0c 记录崩溃得堆栈信息 直接上代码 已经编译通过 xff0c 拷贝直接可用 h include lt Windows h gt include lt stdarg h
  • QT(C++) + OpenCV + Python库打包发布可执行EXE

    QT xff08 C 43 43 xff09 43 OpenCV 43 Python库打包发布可执行EXE 背景 最近写了一个操作界面 xff0c 不仅用到了OpenCV的函数 xff0c 还调用了一个python脚本 xff0c 所以这里
  • Linux 内存管理 页回收和swap机制

    页高速缓存和页写回机制 页是物理内存或虚拟内存中一组连续的线性地址 xff0c Linux内核以页为单位处理内存 xff0c 页的大小通常是4KB 当一个进程请求一定量的页面时 xff0c 如果有可用的页面 xff0c 内核会直接把这些页面
  • docker 创建 network,出现异常问题及解决

    最近在使用 docker 创建 network 时 xff0c 出现错误 xff1a Error response from daemon could not find plugin bridge in v1 plugin registry
  • 工作进度所占总进度的比例

    如果实现的功能模块全部完成为 或者说 工作进度 xff1a 100 那么 xff1a 1 产品原型全部完成 包括文档的整理 xff1a 15 2 UI设计全部完成 xff1a 10 3 后台全部完成 xff1a 25 4 前台全部完成 xf
  • Docx4J替换内容时,内容换行失败问题解决

    WordprocessingMLPackage wordMLPackage 61 WordprocessingMLPackage load new java io File templatePath MainDocumentPart doc
  • C语言经典例题-用4×4矩阵显示从1到16的所有整数,并计算每行、每列和每条对角线上的和

    编写一个程序 xff0c 要求用户 按任意次序 xff09 输入从1到16的所有整数 xff0c 然后用4 4矩阵的形式将它们显示出来 再计算出每行 每列和每条对角线上的和 include lt stdio h gt int main in
  • java中Map.hashCode()函数说明

    在java中 xff0c Map hashCode 函数是在具有一定工作积累后 xff0c 为了更好的成长不可避免需要研究的内容 首先 xff0c 我们先看下原始代码 xff1a static final int hash Object k
  • 不支持的特性: getMetaData,问题解决

    最近使用springboot 43 mybatis 时遇到 xff1a 不支持的特性 getMetaData 的异常 使用 xff1a 64 Options useGeneratedKeys 61 false 解决的该问题 xff1b 官方
  • jsp四种范围

    page代表是与一个页面相关的对象和属性 request代表是与 Web 客户机发出一个请求相关的对象和属性 session代表是与用于某个 Web 客户机的一个用户体验相关的对象和属性 application代表是与整个 Web 应用程序
  • Kotlin-17-等号比较(== 、===)

    目录 1 Java中的 61 61 2 Java中的 equals 3 两者的区别 3 对于基本数据类型的 61 61 比较 4 Kotlin中的 61 61 与 61 61 61 1 Java中的 61 61 Java中的 61 61 直
  • Kotlin-30-继承多个父类

    目录 1 Java中的继承 2 Kotlin中的继承 1 Java中的继承 Java中的类只能继承一个父类 xff0c 是无法实现继承多个父类 xff0c 但是一个类可以实现多个接口 Java中的接口是无法给函数添加函数体的 abstrac
  • 算法-9-快速排序

    目录 1 描述 2 特点 3 代码实现 3 1 切分函数partition 图示 4 性能 5 快速排序优化 xff08 小数组插入排序 xff09 6 快排优化 xff08 三向切分 xff09 1 描述 快速排序也是基于递归实现的 和归