数据结构自学Day13 -- 快速排序--“分而治之”

🔶 一、快速排序(Quick Sort)

📌 基本思想:

分而治之

        每次从数组中选一个“基准”(pivot),把比它小的放左边,大的放右边。

  • 对左右子数组递归排序。

🧠 排序过程:

  1. 选择一个基准(如第一个或最后一个元素)。

  2. 使用双指针或 Lomuto/Hoare 分区法将数组分为左右两部分。

  3. 对左右子数组递归调用快速排序。

⏱️ 时间复杂度:

情况

时间复杂度

最好情况

O(n log n)

平均情况

O(n log n)

最坏情况

O(n²)(当数组几乎有序或元素都相同时)

♻️ 稳定性:

不稳定排序

✅ 优点:

  • 速度快:在大多数实际情况下性能极佳。

  • 原地排序:不需要额外内存。

  • 几乎是排序算法中的性能王者(除非你特别追求稳定性)。

❌ 缺点:

  • 最坏情况下可能退化为 O(n²)。当我们选择的基准为最大元素或者最小元素

  • 递归层数深时可能栈溢出(需优化)。

  • 算法思维:

  • 选择基准值,利用双指针遍历数组,将比基准值小的放置左边,比基准值大的放置右边。

  • 思维导图:

代码实现:


​int PartSort(int* arr,int left,int right){assert(arr);int key_index = right;int begin = left;int end = right;while (begin< end){ while(begin < end && arr[begin] <= arr[key_index]){begin++;}while(begin < end && arr[end] >= arr[key_index]){end--;}Swap(&arr[begin],&arr[end]);}Swap(&arr[key_index],&arr[begin]);return begin;
}
void QuickSort(int* arr,int left,int right){assert(arr);if(left<right){int div = PartSort(arr,left,right);QuickSort(arr,left,div-1);QuickSort(arr,div+1,right);}
}

注意⚠️:

        快速排序如果选择的基准值(key)如果为序列中的最大最小元素时,需要开辟非常多的栈,非常容易导致栈溢出,以及时间复杂度也会更高,最高为O(N^2)。所以为此要避免选取最大元素或者最小元素,比如有序序列时。

快速排序改进方法:

        “三数取中”:保证不要选到最小或者最大,让有序时最为优;

思维导图:

  代码实现:

//三数取中优化
int get_midindex(int*arr,int left,int right){assert(arr);int mid = left+(right-left)/2;if(arr[left]>= arr[mid] && arr[left]<=arr[right] || arr[left]<= arr[mid] && arr[left]>=arr[right]){return left;}else if(arr[mid]>= arr[left] && arr[mid]<=arr[right] || arr[mid]<= arr[left] && arr[mid]>=arr[right]){return mid;}else{return right;}}

快速排序总结:

  • 对于升序排序:begin找>= key的数,end找<= key的数。

  • 对于降序排序:begin找<= key的数,end找>= key的数。

  • 快速排序中的begin和end是寻找左右错位元素进行交换的关键。

  • 最后交换基准值和begin所指的元素,完成一次划分。

  • 对于有序序列,我们需要利用一个“三数取中”规避选取最大或者最小元素作为基准值,增加复杂度和额外的栈的开辟。

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

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

相关文章

Linux 进程与服务管理~进程基础、进程查看、进程控制、服务管理、开机启动​​

在 Linux 系统中,进程与服务管理是运维和开发的核心技能之一。进程是程序运行的实例,服务是长期运行的后台进程(守护进程)。掌握进程与服务的管理方法,能有效排查系统问题、优化资源使用。以下从 ​​进程基础、进程查看、进程控制、服务管理、开机启动​​ 五大模块详细讲…

论文笔记 | Beyond Pick-and-Place: Tackling Robotic Stacking of Diverse Shapes

论文地址&#xff1a;Beyond Pick-and-Place: Tackling Robotic Stacking of Diverse Shapes 概述&#xff1a;本文提出 RGB-Stacking 基准测试&#xff0c;研究如何仅凭 RGB 摄像头视觉和本体感知&#xff0c;实现机器人对 复杂几何物体的高效堆叠。通过结合仿真专家训练、交互…

React 英语打地鼠游戏——一个寓教于乐的英语学习游戏

&#x1f3af; 英语打地鼠游戏 一个寓教于乐的英语学习游戏&#xff0c;通过经典的打地鼠玩法帮助用户学习英语单词。 ✨ 项目特色 &#x1f3ae; 游戏化学习 经典打地鼠玩法&#xff1a;6 个洞穴&#xff0c;听英文选单词即时反馈&#xff1a;答对/答错立即语音提示计分系…

Qt--Widget类对象的构造函数分析

Widget类对象的构造函数分析&#xff0c;用更直观的方式解释这段代码的作用和工作原理&#xff1a;代码&#xff1a;Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }代码解析 Widget::Widget(QWidget *parent) // 构造函数定…

使用pytorch创建模型时,nn.BatchNorm1d(128)的作用是什么?

在PyTorch中&#xff0c;nn.BatchNorm1d(128) 的作用是对 一维输入数据&#xff08;如全连接层的输出或时间序列数据&#xff09;进行批标准化&#xff08;Batch Normalization&#xff09;&#xff0c;具体功能与实现原理如下&#xff1a; 1. 核心作用 标准话数据分布 对每个批…

【数据结构】二叉树的链式结构--用C语言实现

1.二叉树的链式结构 此前&#xff0c;我们通过数组&#xff08;顺序表&#xff09;完成了二叉树的顺序存储&#xff0c;并实现了二叉树的基础功能 那么&#xff0c;二叉树还有没有其他存储方式呢&#xff1f; 前面我们学习了链表&#xff0c;它是一种线性结构&#xff0c;而二…

java设计模式 -【适配器模式】

适配器模式的定义 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;用于解决接口不兼容问题。通过将一个类的接口转换成客户端期望的另一个接口&#xff0c;使原本因接口不匹配而无法工作的类能够协同工作。 核心角色 目标接口&#xff08;…

前端,demo操作,增删改查,to do list小项目

demo操作&#xff0c;html<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title>&l…

Spring AI 项目实战(十九):Spring Boot + AI + Vue3 + OSS + DashScope 构建多模态视觉理解平台(附完整源码)

系列文章 序号 文章名称 1 Spring AI 项目实战(一):Spring AI 核心模块入门 2 Spring AI 项目实战(二):Spring Boot + AI + DeepSeek 深度实战(附完整源码) 3 Spring AI 项目实战(三):Spring Boot + AI + DeepSeek 打造智能客服系统(附完整源码) 4

在 Ubuntu 20.04.5 LTS 系统上安装 Docker CE 26.1.4 完整指南

在 Ubuntu 20.04.5 LTS 系统上安装 Docker CE 26.1.4 完整指南版本选择说明 为什么选择 Docker CE 26.1.4&#xff1f; 1. 版本稳定性和成熟度 Docker CE 26.1.4 是 2024 年 5 月发布的稳定版本&#xff0c;经过了充分的测试和验证相比最新的 28.x 版本&#xff0c;26.1.4 在生…

避坑指南:Windows 11中 Docker 数据卷的存放位置

在 PowerShell 中使用 docker volume inspect 命令&#xff0c;输出如下&#xff1a; [{"CreatedAt": "2025-07-23T01:00:45Z","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/…

Hadoop大数据集群架构全解析

技术概述Hadoop的定义及其在大数据领域的地位Hadoop是由Apache基金会开发的开源分布式计算框架&#xff0c;基于Google的MapReduce和GFS论文思想实现&#xff0c;已成为大数据处理的事实标准。它通过分布式存储和计算解决了传统数据库无法处理的海量数据存储和分析问题&#xf…

【自动化测试】Selenium Python UI自动化测试实用教程

一、引言:Selenium与UI自动化测试基础 1.1 Selenium简介 Selenium是一个开源的Web应用自动化测试框架,支持多浏览器(Chrome、Firefox、Edge等)和多编程语言(Python、Java、JavaScript等),核心组件包括: WebDriver:通过浏览器原生API控制浏览器,模拟用户操作(点击、…

基于VSCode的nRF52840开发环境搭建

nRF52840是Nordic Semiconductor推出的一款功能强大的多协议SoC&#xff0c;广泛应用于物联网设备、可穿戴设备和低功耗蓝牙产品开发。本篇文章将详细介绍如何在VSCode中搭建完整的nRF52840开发环境&#xff0c;让您能够高效地进行嵌入式开发。 一、准备工作 VSCode&#xff1a…

GStreamer开发笔记(九):gst-rtcp-server安装和部署实现简单的rtsp-server服务器推流Demo

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://blog.csdn.net/qq21497936/article/details/149054288 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、O…

C++ namespace机制以及同时使用多个namespace可能存在的问题

在一个 .cpp 文件中使用了多个 using namespace 会怎么样&#xff1f; 核心答案是&#xff1a;可能会导致“命名冲突&#xff08;Name Collision&#xff09;”和“二义性&#xff08;Ambiguity&#xff09;”&#xff0c;从而引发编译错误。 当你使用 using namespace SomeNam…

基于R语言的分位数回归技术应用

回归是科研中最常见的统计学研究方法之一&#xff0c;在研究变量间关系方面有着极其广泛的应用。由于其基本假设的限制&#xff0c;包括线性回归及广义线性回归在内的各种常见的回归方法都有三个重大缺陷&#xff1a;(1)对于异常值非常敏感&#xff0c;极少量的异常值可能导致结…

网络I/O模型详解-一次了解全部(面试经常会问到相关知识)

前言 网络I/O模型的五种类型&#xff0c;其实在我们开发程序、设计程序、实现程序的方方面面都一直存在着&#xff0c;本文从实现原理、使用场景、优缺点、详细的流程图等方面进行深入的解释&#xff0c;帮助大家更好的理解常用的五种网络io模型&#xff0c;助力大家在工作、面…

面试150 合并K个升序链表

思路 对链表元素进行获取&#xff0c;然后进行sort()排序&#xff0c;最后通过空节点建立链表法重新建立一个有序的链表&#xff0c;返回头节点即可。 # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val …

BitDistiller:通过自蒸馏释放 Sub-4-Bit 大语言模型的潜力

温馨提示&#xff1a; 本篇文章已同步至"AI专题精讲" BitDistiller&#xff1a;通过自蒸馏释放 Sub-4-Bit 大语言模型的潜力 摘要 大语言模型&#xff08;LLMs&#xff09;的规模不断扩大&#xff0c;在自然语言处理方面取得了令人瞩目的进展&#xff0c;但这也带来…