快速排序:深入解析其原理、实现与性能特性
快速排序,以其名字所示,是一种追求速度的高效排序算法。作为分治法在排序问题上的典型应用,快速排序凭借其平均情况下近乎理想的O(n log n)时间复杂度和简洁的实现逻辑,在实际编程与数据处理中占据着重要地位。本篇博客将详细解析快速排序的原理、实现步骤,探讨其性能特性,并概述其在不同场景下的适用性。
一、快速排序原理
快速排序的基本思想是分而治之与递归。它通过一趟排序将待排序序列划分为两个部分,使得其中一部分的所有元素都比另一部分的所有元素要小,然后再分别对这两部分继续进行快速排序,整个过程递归进行,直到序列中的元素只剩下一个,即达到完全有序的状态。
这个划分过程的关键在于选取一个基准元素(pivot),并围绕它进行分区操作。分区操作确保基准元素最终会处于其最终排序位置上,同时将小于基准的元素置于其左侧,大于基准的元素置于其右侧。这样的分区操作实现了序列的“相对有序”,为后续递归排序奠定了基础。
二、快速排序实现步骤
以下是快速排序的具体实现步骤:
1. 选择基准元素 从待排序序列中选择一个元素作为基准。常见的选择方法有随机选取、首元素、中位数法等。
2. 分区操作 从待排序序列两端开始,分别向中间扫描。左指针找到大于基准的元素,右指针找到小于基准的元素。当左指针小于右指针时,交换这两个元素的位置。如此反复,直到左指针与右指针相遇。此时,将基准元素与左指针所在位置的元素交换,完成分区。
3. 递归排序 对基准元素左边和右边的子序列分别进行快速排序,直至子序列长度为1(已经有序)。
以下是快速排序算法的代码:
Python
def quick_sort(arr): if len(arr) <= 1: return arr pivot = arr[len(arr) // 2] # 选择中间元素作为基准值 left = [x for x in arr if x < pivot] middle = [x for x in arr if x == pivot] right = [x for x in arr if x > pivot] return quick_sort(left) + middle + quick_sort(right) # 示例
arr = [3,6,8,10,1,2,1]
print("原始数组:", arr)
sorted_arr = quick_sort(arr)
print("快速排序后的数组:", sorted_arr)def partition(arr, low, high): i = low - 1 # 指向小于基准值的最后一个元素的索引 pivot = arr[high] # 选择最右边的元素作为基准值 for j in range(low, high): # 如果当前元素小于或等于基准值 if arr[j] <= pivot: i = i + 1 # 增加小于基准值的元素的计数 arr[i], arr[j] = arr[j], arr[i] # 交换元素 arr[i + 1], arr[high] = arr[high], arr[i + 1] # 将基准值放到正确的位置 return i + 1 def quick_sort_inplace(arr, low, high): if low < high: # pi 是分区索引,arr[pi] 现在在正确的位置 pi = partition(arr, low, high) # 递归地对左半部分和右半部分进行排序 quick_sort_inplace(arr, low, pi - 1) quick_sort_inplace(arr, pi + 1, high) # 示例
arr = [3,6,8,10,1,2,1]
n = len(arr)
quick_sort_inplace(arr, 0, n - 1)
print("快速排序后的数组:", arr)
三、快速排序的时间复杂度与空间复杂度
时间复杂度: 在最理想的情况下,每次分区都能均匀划分,快速排序的时间复杂度为O(n log n)。在最坏情况下(输入序列已经完全有序或逆序),每次只能将序列划分为一个元素和剩余元素两部分,时间复杂度退化为O(n²)。然而,通过合理的基准选择策略(如随机选取),实际应用中快速排序的平均时间复杂度接近最佳情况。
空间复杂度: 快速排序的递归实现需要栈空间存储递归调用的信息。在最坏情况下,递归深度为n,空间复杂度为O(n)。但通过采用尾递归优化或迭代实现,可将空间复杂度降至O(log n)。
四、快速排序的特点与优缺点
特点:
- 不稳定性:快速排序是一种不稳定的排序算法,即相等元素的相对顺序在排序过程中可能会改变。
- 原地排序:通过合理实现,快速排序可以做到在原地进行排序,无需额外存储空间。
优点:
- 效率高:平均时间复杂度为O(n log n),在处理大规模数据时表现出色。
- 原地排序:对内存资源需求较低,尤其适合内存受限的场景。
缺点:
- 最坏情况性能差:当输入序列极度有序时,性能退化至O(n²)。但可通过随机化选择基准元素来避免这种情况。
- 不稳定:对于需要保持相等元素相对顺序的场景,快速排序可能不适用。
五、快速排序的应用场景
1. 大规模数据排序 快速排序在处理大规模数据时,其平均时间复杂度为O(n log n),在实践中往往能提供高效排序能力,常用于数据库、数据分析等领域。
2. 内存敏感场景 快速排序的原地排序特性使其在内存资源有限或对内存消耗敏感的环境中具有优势。
3. 随机性较强的输入 当输入数据的分布较为随机时,快速排序的性能更接近其平均情况,表现优异。
综上所述,快速排序凭借其高效的平均时间复杂度、简洁的实现逻辑以及原地排序的特性,在众多实际应用中展现出强大的竞争力。虽然在特定场景下存在稳定性问题和最坏情况性能退化的风险,但通过合理选择基准元素和优化实现,快速排序仍不失为一种广泛应用的高效排序算法。理解并掌握快速排序,无疑将提升您在数据处理任务中的算法实践能力。
相关文章:
快速排序:深入解析其原理、实现与性能特性
快速排序,以其名字所示,是一种追求速度的高效排序算法。作为分治法在排序问题上的典型应用,快速排序凭借其平均情况下近乎理想的O(n log n)时间复杂度和简洁的实现逻辑,在实际编程与数据处理中占据着重要地位。本篇博客将详细解析…...

一文看懂Mac地址
一、Mac地址是什么? 虽然IP地址已经成为一个家喻户晓的术语,但还有一个同样重要的数字标识符值得我们关注——MAC地址。在本文中,我们旨在阐明网络中这个经常被忽视的方面。加入我们,深入研究 MAC 地址的世界,了解它们…...
2024.4.10作业
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); } Widget::~Widget() { delete ui; } //显示时间 void Widget::timerEvent(QTimerEvent *e) { QT…...
python - Django创建项目
项目运行命令 根目录下运行命令: python manage.py runserver win环境创建项目 直接使用 Pycharm 创建项目 在 cmd 或 Linux 命令行环境下创建 Django 项目 django-admin startproject mysite 这样就会在当前目录下创建一个叫做 mysite 的Django项目。 可以看到Djang…...
WPF —— 动画缩放变换
ScaleTransform:在二维x-y坐标系统内缩放对象; 在故事板中依赖的属性为RenderTransform.ScaleX或RenderTransform.ScaleY,这要根据你要沿哪个轴进行缩放,X代表x轴,Y代表y轴; key属性当我们使用静态资源访问时候--> <!--TargetType"{x:Type Button} 直接应用…...

SQL注入---盲注
文章目录 目录 一.盲注概述 布尔盲注: 时间盲注: 一.盲注概述 注是一种SQL注入攻击的形式,在这种攻击中,攻击者向目标应用程序发送恶意注入代码,然后通过观察应用程序的响应来推断出数据库中的信息。与常规的SQL注入…...

PlanUML和Mermaid哪个好?
引言 在当今信息化快速发展的时代,数据可视化和图表工具不仅对于程序员,也对于非技术背景的人士至关重要。绘图工具可以帮助我们更好地理解和表达复杂的概念或数据流。PlantUML和Mermaid是两款被广泛使用的绘图语言,它们都能够通过简洁的文本…...

leetcode 343. 整数拆分
题目 给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k > 2 ),并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 1 1。 示例 2: 输入: n 10 输出: 36 解释: 1…...

【MATLAB源码-第180期】基于matlab的PTS,SLM,CPFilter三种降低OFDM系统的PAPR仿真。
操作环境: MATLAB 2022a 1、算法描述 1. 限幅和滤波(Clipping and Filtering) 原理简介 限幅和滤波是一种基础且直观的方法,用于降低OFDM信号的PAPR。在限幅阶段,信号的幅度在达到设定阈值时会被削减,…...

学透Spring Boot — 004. Spring Boot Starter机制和自动配置机制
如果你项目中一直用的是 Spring Boot,那么恭喜你没有经历过用 Spring 手动集成其它框架的痛苦。 都说 Spring Boot 大大简化了 Spring 框架开发 Web 应用的难度,这里我们通过配置 Hibernate 的两种方式来深刻体会这一点: 使用 Spring 框架集…...

面试算法-170-二叉树的最大深度
题目 给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:3 解 class Solution {public int maxDepth(TreeNod…...

【数据结构】哈希
文章目录 1. 哈希概念2. 哈希冲突3. 哈希函数4. 哈希冲突解决4.1 闭散列4.2 开散列 unordered 系列的关联式容器之所以效率比较高,是因为其底层使用了哈希结构。 1. 哈希概念 顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系ÿ…...

Kubernetes(k8s)监控与报警(qq邮箱+钉钉):Prometheus + Grafana + Alertmanager(超详细)
Kubernetes(k8s)监控与报警(qq邮箱钉钉):Prometheus Grafana Alertmanager(超详细) 1、部署环境2、基本概念简介2.1、Prometheus简介2.2、Grafana简介2.3、Alertmanager简介2.4、Prometheus …...

STM32-04基于HAL库(CubeMX+MDK+Proteus)中断案例(按键中断扫描)
文章目录 一、功能需求分析二、Proteus绘制电路原理图三、STMCubeMX 配置引脚及模式,生成代码四、MDK打开生成项目,编写HAL库的按键检测代码五、运行仿真程序,调试代码 一、功能需求分析 在完成GPIO输入输出案例之后,开始新的功能…...

第十五篇:Mybatis
文章目录 一、什么是MyBatis二、Mybatis入门案例三、配置SQL提示四、数据库连接池四、lombok五、mybatis基础操作5.1 根据id删除5.2 预编译SQL5.3 新增员工5.4 更新员工5.5 查询员工(用于页面回显)5.6 条件查询 七、XML映射文件八、动态SQL8.1 if语句8.2…...

【MacBook系统homebrew镜像记录】
安装 使用Homebrew 国内源安装脚本,贼方便: /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"切换至清华大学镜像源: 命令合并: 分别切换了 brew.git、 homebrew-core.git、 homebrew-…...

深拷贝总结
JSON.parse(JSON.stringify(obj)) 这行代码的运行过程,就是利用 JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象;序列化的作用是存储和传输。(…...
RabbitMQ在云原生环境中部署和应用实践
一、RabbitMQ和云原生技术的关系 RabbitMQ是一种开源的、实现了先进的消息队列协议(AMQP)的消息队列软件。而云原生技术就是为在公共云、私有云以及其他各种云环境提供应用的一种方法。RabbitMQ和云原生技术在分布式系统和微服务架构中都起到了关键作用…...
flask 后端 + 微信小程序和网页两种前端:调用硬件(相机和录音)和上传至服务器
选择 flask 作为后端,因为后续还需要深度学习模型,python 语言最适配;而 flask 框架轻、学习成本低,所以选 flask 作为后端框架。 微信小程序封装了调用手机硬件的 api,通过它来调用手机的摄像头、录音机,…...

蓝桥杯嵌入式(G431)备赛笔记——ADC+LCD
目录 题目要求(真题): cubeMX配置: 小试牛刀: Keil代码: 效果演示: 题目要求(真题): 使用第十一届第二场真题,练习ADC波部分的代码 cubeMX配…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...

android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...