排序算法之快速排序详细解读(附带Java代码解读)

embedded/2024/9/20 9:21:50/ 标签: 算法, 数据结构, 排序算法

快速排序(Quick Sort)是一种高效的排序算法,由 C.A.R. Hoare 在 1960 年提出。它采用分治法的思想,将数组分为两部分,然后分别对这两部分进行排序,最终合并成一个有序数组。快速排序在大多数情况下表现优异,通常被认为是排序算法中最快的之一。

算法思想

  1. 选择基准:从数组中选择一个元素作为基准(pivot)。
  2. 分区:将数组中的元素重新排列,使得比基准小的元素在基准的左边,比基准大的元素在基准的右边。
  3. 递归排序:递归地对基准左边和右边的子数组进行快速排序。

过程示例

假设有一个待排序的数组:[10, 7, 8, 9, 1, 5]

步骤 1: 选择基准

选择数组的最后一个元素 5 作为基准。

步骤 2: 分区

对数组进行分区,使得所有小于基准的元素在左边,大于基准的元素在右边。

  • 初始数组:[10, 7, 8, 9, 1, 5]
  • 比较 10 与 5,10 > 5,移动指针。
  • 比较 7 与 5,7 > 5,移动指针。
  • 比较 8 与 5,8 > 5,移动指针。
  • 比较 9 与 5,9 > 5,移动指针。
  • 比较 1 与 5,1 < 5,将 1 交换到左边。

最终数组变为:[1, 7, 8, 9, 10, 5]

  • 将基准 5 放到它的正确位置,数组变为:[1, 5, 8, 9, 10, 7]
步骤 3: 递归排序

对基准左边的子数组 [1] 和右边的子数组 [8, 9, 10, 7] 进行递归排序。

  • 左边子数组 [1] 已经有序。
  • 右边子数组 [8, 9, 10, 7] 的快速排序过程:
    • 选择基准 7,将其放到合适位置,分区后得到 [7, 8, 9, 10]
    • 左边子数组 [8, 9, 10] 进行快速排序:
      • 选择基准 10,无需交换,最终有序。

最终得到有序数组:[1, 5, 7, 8, 9, 10]

算法复杂度

  • 时间复杂度:

    • 最坏情况: O(n^2)(当选择的基准是数组中的最大或最小元素时)
    • 平均情况: O(n log n)
    • 最佳情况: O(n log n)(当基准每次都能将数组均匀分割时)
  • 空间复杂度: O(log n) 快速排序的空间复杂度取决于递归调用栈的深度,通常为 O(log n)。

优点

  1. 效率高:快速排序在大多数情况下比其他 O(n log n) 算法(如归并排序和堆排序)更快。
  2. 原地排序:不需要额外的存储空间,适合内存有限的情况。
  3. 排序稳定性:虽然标准的快速排序是不稳定的,但可以通过修改算法使其稳定。

缺点

  1. 最坏情况性能差:在最坏情况下,时间复杂度为 O(n^2),例如当数组已经排好序时。
  2. 不稳定排序:标准实现的快速排序是不稳定的,可能会改变相同元素的相对位置。

Java代码解读

public class QuickSort {// 快速排序方法public static void quickSort(int[] arr, int low, int high) {if (low < high) {// 找到基准元素的正确位置int pi = partition(arr, low, high);// 递归排序基准左边和右边的子数组quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}}// 分区方法private static int partition(int[] arr, int low, int high) {int pivot = arr[high];  // 选择基准元素int i = (low - 1);  // 记录较小元素的索引for (int j = low; j < high; j++) {// 如果当前元素小于基准元素if (arr[j] < pivot) {i++;  // 增加较小元素的索引// 交换当前元素与较小元素索引对应的元素int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}// 交换基准元素与较小元素索引下一个元素int temp = arr[i + 1];arr[i + 1] = arr[high];arr[high] = temp;return i + 1;  // 返回基准元素的索引}public static void main(String[] args) {int[] arr = {10, 7, 8, 9, 1, 5};System.out.println("排序前的数组:");for (int num : arr) {System.out.print(num + " ");}System.out.println();quickSort(arr, 0, arr.length - 1);System.out.println("排序后的数组:");for (int num : arr) {System.out.print(num + " ");}}
}

代码说明

  1. quickSort方法:

    • lowhigh 分别表示当前排序的子数组的起始和结束索引。
    • 调用 partition 方法找到基准元素的正确位置 pi,然后递归地对基准左边和右边的子数组进行排序。
  2. partition方法:

    • 选择数组的最后一个元素作为基准。
    • 遍历数组,将小于基准的元素移到基准的左边,大于基准的元素留在右边。
    • 将基准元素放到正确的位置,返回基准的索引。
  3. main方法:

    • 创建一个待排序的数组 arr
    • 调用 quickSort 方法对数组进行排序。
    • 输出排序前和排序后的数组。

http://www.ppmy.cn/embedded/102056.html

相关文章

鸿蒙后台运行,鸿蒙播放音乐后台

1、权限&#xff1a; 1.1、在entry > src > main > module.json5中配置&#xff1a; "requestPermissions": [{"name": "ohos.permission.KEEP_BACKGROUND_RUNNING"}], 1.2、在ability中配置backgroundModes&#xff08;也是module.js…

C\C++ Sqlite3使用详解

C\C++ Sqlite3使用详解 一、源码下载二、sqlite3接口说明C++2.1 项目创建以及sqlite3使用2.1 连接数据库2.2 sqlite创建表2.2.1 示例代码2.2.2 注意事项2.3 sqlite插入数据2.3.1 示例代码2.3.2 注意事项2.4 sqlite数据删除2.5 sqlite数据查询一、源码下载 下载地址: https://…

大模型面试:LLM+向量库的文档对话系统

面试题 1.1 为什么大模型需要外挂(向量)知识库&#xff1f;如何将外部知识注入大模型&#xff0c;最直接的方法&#xff1a;利用外部知识对大模型进行微调 回答 大模型需要外挂(向量)知识库的原因&#xff1a; 知识更新频率&#xff1a;大模型在训练时使用的知识是静态的&a…

【大模型LLMs】文本分块Chunking调研LangChain实战

【大模型LLMs】文本分块Chunking调研&LangChain实战 Chunking策略类型1. 基于规则的文本分块2. 基于语义Embedding分块3. 基于端到端模型的分块4. 基于大模型的分块 Chunking工具使用&#xff08;LangChain&#xff09;1. 固定大小分块&#xff08;字符&token&#xff…

Python--迭代器、生成器和装饰器

在 Python 中&#xff0c;迭代器和生成器是处理可迭代对象的两个核心概念&#xff0c;它们可以帮助我们高效地遍历数据。装饰器则是 Python 中的一种高级功能&#xff0c;用于修改函数或类的行为。接下来详细阐述并扩展这些概念。 1. 迭代器 迭代器的定义 迭代器是一个实现了…

react state 状态数据

props 和 state props 特点是只读&#xff0c;即修改不会让视图同步更新&#xff0c;想要更新必须再次调用 render() 渲染函数 state 特点是可读可写&#xff0c;在使用 this.setState({属性名: 属性值}) 修改时会同步更新视图state 创建和使用 state 必须在类组件的 construct…

计算机三级网络技术总结 第二章中小型网络系统总体规划与设计

采用RAID&#xff08;磁盘阵列技术&#xff09;在一定程度上可以提高磁盘存储容量集群系统&#xff08;cluster&#xff09;当一台主机出现故障&#xff0c;虽然不会使整个网络无法工作&#xff0c;但会影响性能系统高可用性&#xff1a;MTBF/&#xff08;MTBFMTBR&#xff09;…

电动汽车充电负荷预测!基于动态交通信息的电动汽车充电负荷时空分布预测程序代码!

前言 随着世界能源产业结构的调整和人们对环境问题的不断重视&#xff0c;促进了新能源汽车的发展与应用。而电动汽车(Electric Vehicle, EV)可以有效降低化石燃料的依赖和温室气体排放&#xff0c;满足未来能源需求以及电网系统与交通系统可持续发展的要求。然而&#xff0c;…

朋友圈个人IP打造技巧

1、不要设置三天可见 新加一个好友&#xff0c;我们都会下意识地去看看他的朋友圈&#xff0c;想看看他平时在做什么、喜欢什么、关注什么&#xff0c;了解一下他的爱好、职业、性格、甚至人品等等。千万不要逆人性行事&#xff0c;不要拒绝别人的好奇心。 记住&#xff1a;信…

浅析STM32外部中断易死机解决

本案例stm32死机或程序跑飞是实际产品中出现的&#xff0c;初步怀疑是外部中断口&#xff0c;有极强的干扰所致&#xff0c;于是拿着信号发生器实测&#xff0c;当信号发生器产生300KHz的信号&#xff0c;甚至到12MHz的信号时&#xff0c;期间&#xff0c;程序跑飞或死机。看门…

云原生系列 - Nginx(高级篇)

前言 学习视频&#xff1a;尚硅谷Nginx教程&#xff08;亿级流量nginx架构设计&#xff09;本内容仅用于个人学习笔记&#xff0c;如有侵扰&#xff0c;联系删学习文档&#xff1a; 云原生系列 - Nginx(基础篇)云原生系列 - Nginx(高级篇) 一、扩容 通过扩容提升整体吞吐量…

虚幻引擎UE5入坑记

前言 Unreal Engine 和Unity Engine作为目前主流的游戏引擎&#xff0c;各有优缺点。而我目前的工作还是以Unity开发为主&#xff0c;在使用Unity的过程中&#xff0c;总避免不了听到或看到过UE相关的东西&#xff0c;从开始的好奇到后面想要去学习它&#xff0c;但是&#xf…

c语言每日学习8.24

void reverse_string(char* str) 为什么不用传递数组的长度&#xff1f; 在C语言中&#xff0c;字符串通常是以空字符\0结尾的字符数组。因此&#xff0c;当你传递一个字符串&#xff08;即字符数组的指针&#xff09;给函数时&#xff0c;函数可以通过遍历字符串直到遇到空字…

Docker 部署 Kafka 可视化 Kafka-UI

前言 本文部署的Kafka-UI 是基于Docker Compose 部署 Kafka的KRaft模式&#xff0c;如有需要可访问下文链接 Docker Compose 部署 Kafka的KRaft模式 不用依赖 Zookeeper 此部署也适用于不是docker部署的kafka集群 1.启动 Kafka-UI 服务 1.1 kafka 来自docker安装 docker r…

在Linux中杀死占用某个端口的进程

以9997端口为例&#xff1a; 在 Linux 中可以通过以下步骤查看端口为 9997 的进程并杀死它&#xff1a; 一、查看占用端口 9997 的进程 使用 netstat 命令&#xff1a; netstat -tunlp | grep 9997这个命令会列出所有正在监听的 TCP 和 UDP 端口以及对应的进程信息&#xff0c…

掌握Nginx负载均衡中的请求重定向:技术指南与实践

引言 Nginx 是一款高性能的 HTTP 服务器和反向代理&#xff0c;广泛用于提供负载均衡服务。在复杂的网络架构中&#xff0c;根据业务需求&#xff0c;有时需要对客户端的请求进行重定向。这可以通过 Nginx 的配置实现&#xff0c;以确保流量被正确地引导到不同的URL或域名。本…

[图论]游戏

题目描述 B B B 经常与 A A A 一起玩游戏。今天&#xff0c;他们在一棵树上玩游戏。 A A A 有 m 1 m1 m1 块石子&#xff0c; B B B 有 m 2 m2 m2 块石子&#xff0c;游戏一开始&#xff0c;所有石头放在树的节点处&#xff0c;除了树根。 A A A 先移动石子。然后两人轮流移…

阿里云发送短信功能(Java)

&#xff08;1&#xff09;注册用户&#xff0c;并且开通短信套餐 &#xff08;2&#xff09; 点击快速学习&#xff0c;然后绑定测试的手机号码。 选用专用测试签名&#xff08;自定义的话阿里可能会验证什么什么的比较麻烦&#xff09; 然后在选取调用API &#xff08;3&…

大数据-100 Spark 集群 Spark Streaming DStream转换 黑名单过滤的三种实现方式

喜大普奔&#xff01;破百了&#xff01; 点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&a…

了解ROS Nodes(节点/结点)

1.相关概念 Nodes:A node is an executable that uses ROS to communicate with other nodes.Messages: ROS data type used when subscribing or publishing to a topic.Topics: Nodes canpublishmessagesto a topic as well assubscribetoa topic to receive messages.Master…