什么是快速排序?

news2024/11/19 11:19:12

本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注!

作者| 慕课网精英讲师 JdreamZhang

快速排序(Quick Sort),是计算机科学与技术领域中非常经典的一种排序算法,应用分治思想进行排序。

快速排序由于其时间复杂度优于大部分的排序算法,因而命名为快速排序。快速排序实现的核心思想就是在待排序序列中选择一个基准值,然后将小于基准值的数字放在基准值左边,大于基准值的数字放在基准值右边,然后左右两边递归排序,整个排序过程中最关键部分就是寻找基准值在待排序序列中的索引位置。

1. 快速排序过程

今天我们来看一下快速排序的实现步骤具体是什么样的吧。同样地,和之前介绍归并排序时一样,这里我们假设待排序的序列为 [9,2,11,7,12,5],我们按照从小到大的序列进行排序。

1.1 算法描述

快速排序也是应用分治法解决问题,主要分为以下三步:

  1. 步骤 1:

从待排序序列中选择一个元素,称之为基准(pivot),在这里我们选择待排序序列中第一个元素作为基准。

  1. 步骤 2:

对整个待排序序列进行重新排序,小于基准的元素放在基准前面,大于基准的元素放在基准后面,基准放在序列中间,这个步骤一般称之为分区操作(partition)。

Tips: 步骤 2 的执行其实就是给基准元素找到了合适的排序位置。

分区操作的伪代码如下,最重要的就是双指针的应用,将待排序序列基于基准进行分区:

//对数组A进行一次分区操作
int pivot = A[0]
low = 0
high = A.length-1
//进行分区操作,找到基准的位置
while (low < high){
      while(low < high && A[high] >= pivot){
            high = high - 1
      }
      A[low] = A[high]
      while (low < high && A[low] <= pivot){
            low = low + 1
      }
      A[high] = A[low]
}        
//最后赋值基准
A[low] = pivot
代码块1234567891011121314151617
  1. 步骤 3:

递归的将小于基准的子序列和大于基准的子序列进行排序。

其实,上面的排序步骤就是分治法的典型应用,选择基准分拆序列形成子序列,在子序列中重新排序,完成排序之后进行合并,只是因为在这里完成子序列的排序后待排序序列已经完成排序,所以无需进行合并的工作。这里,最需要注意的就是步骤 2 中的分区操作,这里面会用到一种最为经典的双指针操作,前后两个指针分别记录需要交换的元素位置,后面的代码示例中会详细说明。接下来,让我们用上面的待排序数字队列 [9,2,11,7,12,5] 进行整个算法步骤的排序演示工作。

1.2 算法演示

按照排序步骤,首先我们从待排序序列中选择一个基准 pivot,这里默认选择待排序序列中的第一个元素,如下:

[9,2,11,7,12,5]   -->  9   //选择第一个元素9作为基准pivot
代码块1

接着,我们用下图的示例来说明步骤 2 中的分区操作,这里用到了双指针 low 和 high。具体示例如下图:

按照上图的示例,可以很清楚地知道,其实快速排序的本质就是把比基准大的元素都放在基准数的右边,把比基准小的元素放在基准数的左边,这样就找到了基准数据在数组中的正确位置。以后采用递归的方式分别对前半部分和后半部分排序,当前半部分和后半部分均有序时该数组就自然有序了。如前文中说到的快速排序其实最主要的就是双指针的应用,就是体现在分区操作时候的双指针进行分区。

2.Java 代码实现

在说明快速排序的整个过程之后,接下来,我们看看如何用 Java 代码实现快速排序算法。

import java.util.Arrays;

public class QuickSort {

    public static void main(String[] args) {
        //初始化需要排序的数组
        int array[] = {9, 2, 11, 7, 12, 5};
        //快速排序
        quickSort(array,0,array.length-1);
        //打印出排序好的序列
        System.out.println(Arrays.toString(array));
    }

    //快速排序
   private static void quickSort(int[] array,int low, int high){
        if(low < high){
            //找到分区的位置,左边右边分别进行快速排序
            int index = partition(array,low,high);
            quickSort(array,0,index-1);
            quickSort(array,index+1,high);
        }
   }

   //快速排序分区操作
   private static int partition(int[] array, int low, int high){
        //选择基准
        int pivot = array[low];
        //当左指针小于右指针时,重复操作
        while (low < high){
            while(low < high && array[high] >= pivot){
                high = high - 1;
            }
            array[low] = array[high];
            while (low < high && array[low] <= pivot){
                low = low + 1;
            }
            array[high] = array[low];
        }
        //最后赋值基准
        array[low] = pivot;
        //返回基准所在位置,基准位置已经排序好
        return low;
   }


}
代码块12345678910111213141516171819202122232425262728293031323334353637383940414243444546

运行结果如下:

[2, 5, 7, 9, 11, 12]
代码块1

代码中的第 8 行初始化一个需要排序的数组,后面按照从小到大的排序规则,实现了数组的排序。第 15 行到底 22 行是快速排序的外部结构,应用分治思想递归求解。代码 25 行至 43 行是分区操作,完成基于基准数据的左右分区,并将基准数据放置在排序好的位置,并且返回基准所在的位置,进行后续的分治操作。

3. 小结

本篇文章主要帮大家介绍了快速排序算法,快速排序是一种非常典型的排序算法,在 Java 程序中,JDK 中的 Arrays.sort() 方法的内部实现就是应用到快速排序的思想实现数组的排序工作。

对于算法,其实每种排序算法的实现思路都不相同,对应的算法的时间复杂度和空间复杂度也都不一样,希望大家可以在学习这些基础排序算法的基础上多思考,考虑每种排序算法的具体实现,能够熟练掌握这些基础的排序算法。

欢迎关注「慕课网」,发现更多IT圈优质内容,分享干货知识,帮助你成为更好的程序员!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/135643.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为云工程师HCIA——桌面云解决方案概述

一、桌面云解决方案概述 瘦终端和胖终端 瘦终端&#xff1a;提供屏幕&#xff0c;和很小的计算能力胖终端&#xff1a;提供主要计算能力 桌面云架构VDI与IDV 华为桌面云解决方案逻辑架构 FusionCompute云平台架构 桌面云的优势 二、桌面云组件介绍 接入和访问控制层 WI&…

图像处理(2)——图像特征提取LBP

图像处理&#xff08;2&#xff09;——图像特征提取LBP 其实现在大家都说图像处理&#xff0c;其实计算机是不认识图片的&#xff0c;之所以可以处理图像&#xff0c;其实图像就是一个个矩阵&#xff0c;其实是数字&#xff0c;转而其实都是在处理数字。深度学习在图像上的建…

数字图像处理实验——数字图像处理初步

一、实验目的与要求 1.熟悉及掌握在MATLAB中能够处理哪些格式的图像&#xff1b; 2.熟练掌握在MATLAB中如何读取图像及图像的属性信息&#xff08;大小、颜色、亮度&#xff08;灰度&#xff09;、宽度、高度等&#xff09;&#xff1b; 3.掌握如何在MATLAB中按照指定要求存储一…

Windows 内核安全编程技术实践

《Windows 内核安全编程技术实践》&#xff0c;这是一本Windows 10内核安全开发系列丛书&#xff0c;探索 AntiRootKit 反内核工具核心原理与技术实现细节&#xff0c;揭开ARK工具的神秘面纱&#xff0c;本书以实战角度出发摒弃了大量无用的专业术语&#xff0c;欢迎阅读并提出…

在Qt中设置窗体背景颜色及透明度的方法介绍

本文主要介绍在 Qt 中设置窗体背景颜色及透明度的方法。 说明&#xff1a; 本文中的应用程序是面向 Windows 操作系统的&#xff1b;本文中使用的 Qt Creator 版本号为&#xff1a;7.0.0&#xff1b;本文中使用的 Qt 版本号为&#xff1a;5.14.2。 1 利用样式表&#xff08;S…

Github每日精选(第82期):还在用logging试试loguru

Loguru 如果你还在使用logging&#xff0c;不妨花点时间来看看Loguru&#xff0c;Loguru是一个Python日志记录的库。 您是否曾懒于配置记录器而使用print&#xff08;&#xff09;&#xff1f;。。。 我确实这样做了&#xff0c;但日志记录对于每个应用程序来说都是基本的&a…

Redis集群系列十二 —— 故障转移二

场景 模拟集群中有一个 master 宕机场景。 故障转移自动故障转移和手动故障转移。 自动故障转移 打开日志监控 为了更好折查看效果&#xff0c;通过 watch 命令实时查看集群的动态日志变化&#xff0c;如图&#xff1a; watch redis-cli -p 30001 cluster nodes 注意&#…

用SQL语句进行数据库查询(复杂查询)

前言 &#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏: &#x1f354;&#x1f35f;&#x1f32f; c语言初阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f349;本篇简介:>:上一篇学习了如何使用SQL语句进行简单的数据查询,本篇…

C++ 简单工厂模式 与 工厂模式

简单工厂模式&#xff1a; 一个工厂&#xff0c;多个产品。产品需要有一个虚基类。通过传入参数&#xff0c;生成具体产品对象&#xff0c;并利用基类指针指向此对象。通过工厂获取此虚基类指针&#xff0c;通过运行时多态&#xff0c;调用子类实现。 注意&#xff1a;简单工厂…

S32K144—autoMBD是什么?

基于模型的设计&#xff08;Model-Based Design&#xff0c;MBD&#xff09;是一项非常具有发展潜力的技术&#xff0c;autoMBD 致力于分享和传播 MBD 相关技术&#xff0c;让更多人可以快速、高效地在项目开发中使用 MBD。 MBD能做什么&#xff1f; 从大的范围来说&#xff…

14 Python 办公自动化

目录 1、普通文件自动化管理 1.1 文件的复制 1.2 文件内容的复制 1.3 文件的裁剪 1.4 文件的删除 1.5 文件的压缩与解压缩 1.6 文件的查找 1.7 查找含有指定内容的文件 1.8 清理重复的文件 1.9 批量修改目录中的文件名称 2、文件夹的自动化管理 2.1 文件夹的复制 …

机器学习中的数学原理——线性可分问题

这个专栏主要是用来分享一下我在机器学习中的学习笔记及一些感悟&#xff0c;也希望对你的学习有帮助哦&#xff01;感兴趣的小伙伴欢迎私信或者评论区留言&#xff01;这一篇就更新一下《白话机器学习中的数学——线性可分问题》&#xff01; 一、什么是线性可分问题 线性可分…

kibana和elasticsearch-head安装手册

kibana和elasticsearch-head安装手册 0 安装包下载 组件安装包下载地址kibanakibana-8.5.2-linux-x86_64.tar.gzelastic官网&#xff1a;https://www.elastic.co/cn/downloads/past-releases#kibana elastic中文社区&#xff1a;https://elasticsearch.cn/download/nodenode-…

关键字:static

文章目录一、static关键字的使用static修饰属性实例变量静态变量&#xff08;类变量&#xff09;内存解析static修饰方法static注意点如何确定什么时候使用static&#xff1f;方法属性单例设计模式饿汉式懒汉式区分饿汉式和懒汉式一、static关键字的使用 1、可以用来修饰&…

回首满是自豪

写在前面hi朋友&#xff0c;我是几何心凉&#xff0c;感谢你能够点开这篇文章&#xff0c;看到这里我觉得我们是有缘分的&#xff0c;因着这份缘分&#xff0c;我希望你能够看完我的分享&#xff0c;因为下面的分享就是要汇报给你听的&#xff0c;这篇文章是在 2022 年 12 月 3…

【柔性数组与局部性原理】

柔性数组概念 柔性数组特点 局部性原理 柔性数组概念 对于柔性数组&#xff0c;也许你之前从未听说过&#xff0c;柔性数组&#xff0c;顾名思义&#xff0c;就是数组&#xff0c;它的柔性柔在元素个数可以动态变化&#xff0c; 即柔性数组是未知大小的&#xff0c;数组大小…

Elasticsearch:使用 Node.js 将实时数据提取到 Elasticsearch 中(二)

在我的上一篇文章 “Elasticsearch&#xff1a;使用 Node.js 将实时数据提取到 Elasticsearch 中&#xff08;一&#xff09;”&#xff0c;我详细描述了如何如何使用 Node.js 来采集地震数据。在今天的文章中&#xff0c;我们来详细描述如何对数据可视化。我们还将创建一个 we…

推荐七个Python效率工具!让你事半功倍

为了提高效率&#xff0c;我们在平时工作中常会用到一些Python的效率工具&#xff0c;Python作为比较老的编程语言&#xff0c;它可以实现日常工作的各种自动化。为了更便利的开发项目&#xff0c;这里给大家推荐几个Python的效率工具。 1、Pandas-用于数据分析 Pandas是一个强…

UEditorPlus v2.8.0发布 颜色自定义,文档功能完善

UEditor是由百度开发的所见即所得的开源富文本编辑器&#xff0c;基于MIT开源协议&#xff0c;该富文本编辑器帮助不少网站开发者解决富文本编辑器的难点。 UEditorPlus 是有 ModStart 团队基于 UEditor 二次开发的富文本编辑器&#xff0c;主要做了样式的定制&#xff0c;更符…

vim使用教程图文教程(超详细)

1. 三种模式 vim编辑器有三种模式&#xff1a;命令模式、编辑模式、末行模式。 「命令模式」&#xff1a;可以进行删除、复制、粘贴等快捷操作。「编辑模式」&#xff1a;可以编辑文件内容。「末行模式」&#xff1a;可以通过命令操作文件&#xff0c;比如搜索、保存、退出等…