快速排序之C++实现

描述

快速排序是一种常用的排序算法,它的思想是选取一个基准元素,将数组分成左右两部分,使得左边的元素都小于等于基准元素,右边的元素都大于等于基准元素,然后递归地对左右两部分进行快速排序。

实现步骤

  1. 选择一个基准元素,通常可以选择数组的第一个元素。
  2. 定义左指针和右指针,分别指向数组的第一个元素和最后一个元素。
  3. 左指针往右移动,直到找到一个大于基准元素的元素;右指针往左移动,直到找到一个小于基准元素的元素;交换左右指针指向的元素。
  4. 重复步骤3,直到左指针和右指针相遇。
  5. 将基准元素和左指针指向的元素进行交换,此时基准元素的位置就是它最终的位置。
  6. 递归地对左右两部分进行快速排序。

图解

在这里插入图片描述

时间复杂度

快速排序的时间复杂度为O(nlogn)。

在快速排序中,每次划分都将数组分成左右两部分,直到每个部分中只有一个元素或者没有元素为止。每次划分的时间复杂度为O(n),其中n为待排序数组的长度。划分过程中需要比较元素的大小和交换元素的位置,所以时间复杂度为O(n)。

假设待排序数组的长度为n,每次划分后,左右两部分的长度分别为n/2。递归地对左右两部分进行快速排序,时间复杂度可以表示为:
T(n) = 2 * T(n/2) + O(n)

根据主定理(Master Theorem)的第三种情况,即递归式形如T(n) = a * T(n/b) + f(n),其中a>=1,b>1,f(n)为多项式,如果存在常数c<1和常数d>=0,使得f(n) = O(n^d * log^c(n)),那么时间复杂度可以表示为:
T(n) = O(n^d * log^(c+1)(n))

在快速排序中,a=2,b=2,f(n) = O(n),所以d=1,c=0。根据上述公式,可以得到时间复杂度为O(nlogn)。

需要注意的是,这个时间复杂度是平均情况下的时间复杂度。在最坏情况下,即每次划分只能将一个元素移到它的最终位置上,快速排序的时间复杂度为O(n^2)。为了避免最坏情况的发生,可以采用随机选择基准元素或者选择三个元素中的中值作为基准元素。

空间复杂度

快速排序的空间复杂度为O(logn)。

快速排序是一种原地排序算法,即在排序过程中不需要额外的辅助空间,只需要利用原始数组进行元素的交换和移动。因此,快速排序的空间复杂度主要由递归调用所占用的栈空间决定。

在快速排序的实现过程中,每次划分都会将数组分成左右两部分,然后分别对这两部分进行快速排序。递归最多进行logn次,因为每次划分都会将数组的规模减半。在递归的过程中,每层递归都需要保存一些临时变量,包括基准元素的索引、左右指针的位置等,这些变量占用的空间与递归的层数成正比。

因此,快速排序的空间复杂度为O(logn)。

示例

#include <iostream>
using namespace std;void quickSort(int arr[], int left, int right) {if (left >= right) {return;}int pivot = arr[left];int i = left;int j = right;while (i < j) {while (i < j && arr[j] >= pivot) {j--;}while (i < j && arr[i] <= pivot) {i++;}if (i < j) {swap(arr[i], arr[j]);}}swap(arr[left], arr[i]);quickSort(arr, left, i - 1);quickSort(arr, i + 1, right);
}int main() {int arr[] = {5, 2, 8, 9, 1};int n = sizeof(arr) / sizeof(arr[0]);quickSort(arr, 0, n - 1);cout << "quickSort res :" << endl;for (int i = 0; i < n; i++) {cout << arr[i] << " ";}cout << endl;return 0;
}

结果:
在这里插入图片描述

注意事项

快速排序的一个重要技巧是如何选择基准元素。如果选择的基准元素恰好是数组的最大或最小值,那么每次划分都只能将一个元素移到它的最终位置上,这样快速排序的时间复杂度将会退化为O(n^2)。为了避免这种情况,可以随机选择基准元素,或者选择三个元素中的中值作为基准元素。

另外一个需要注意的地方是对于小规模的数组,快速排序的性能可能会比插入排序差,因此可以在递归到一定程度时,切换到插入排序来提高性能。

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

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

相关文章

小白的实验室服务器深度学习环境配置指南

安装nvidia 本文在ubuntu server 22.04上实验成功&#xff0c;其他版本仅供参考 注意&#xff0c;本文仅适用于ubuntu server&#xff0c;不需要图形界面&#xff0c;没有对图形界面进行特殊考虑和验证&#xff01;依赖图形操作界面的读者慎用 查看是否安装了gcc gcc -v若没…

听GPT 讲Rust源代码--src/tools(26)

File: rust/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs 在Rust源代码中&#xff0c;iter_out_of_bounds.rs文件是Clippy lints库的一部分&#xff0c;该库用于静态代码分析&#xff0c;用于检测Rust代码中的潜在问题和错误。iter_out_of_bounds.rs文件中…

外卖系统开发:构建高效、安全的外卖平台

在当今数字化时代&#xff0c;外卖系统成为了餐饮行业不可或缺的一部分。本文将介绍如何使用一些主流的技术和代码片段来开发一个简单而功能强大的外卖系统。 1. 技术选择 在开始外卖系统的开发之前&#xff0c;首先需要选择合适的技术栈。以下是一个常见的技术栈&#xff1…

shell 循环遍历的详细用法

简介 在 shell 脚本中&#xff0c;循环结构用于重复执行一组代码块&#xff0c;包括 for 循环、while 循环&#xff0c;可以用于遍历数字、字符串、数组、文件等。这篇文章会详细介绍这两种遍历方式&#xff0c;以及各种实例场景。 文章目录结构如下 1. 循环遍历的特点 2. 循…

直排轮滑教程8

弧线滑行收腿练习 1&#xff0c;不同于直线&#xff0c;弧线滑行收腿&#xff0c;右腿要越过左脚&#xff0c;左腿收回要靠近右脚。 2&#xff0c;它是个越过动作&#xff0c;是个交叉动作。收腿当中&#xff0c;左右脚是不一样的。 3&#xff0c;收腿的基本理论就是&#x…

分包zip压缩,解压报错:invalid zip file with overlapped components (possible zip bomb)

背景 在生产环境中&#xff0c;需要把安装包从本地传到服务器上&#xff0c;传输过程中网络抖动的原因造成大文传输失败。可以将文件分包压缩成200M或500M大小的文件&#xff0c;然后分批传输到服务器。最近生产环境传输了starrocks的安装包&#xff0c;分包压缩之后上传服务器…

树莓派Pi4B简介

树莓派是什么&#xff1f;Raspberry Pi(中文名为“树莓派”,简写为RPi&#xff0c;或者RasPi/RPi)是为学生计算机编程教育而设计&#xff0c;只有信用卡大小的卡片式电脑&#xff0c;其系统基于Linux。 树莓派4B与树莓派3B/3B参数对比&#xff1a; 具体的实物图如下&#xff1a…

学Java的第二天

一、常量 1.值不可以变化的量。 2. 分类&#xff1a; 字符串常量 用双引号括起来的多个字符&#xff0c;可以包含 0、1 或多个&#xff0c;例如 "a" 、 "abc" 、 " 中国 " 整数常量&#xff0c;例如&#xff1a; -10 、 0 、 88 小数常量&…

数据仓库【4】:最佳实践

数据仓库【4】&#xff1a;最佳实践 1、表的分类1.1、事实表1.2、维度表1.3、事务事实表1.4、周期快照事实表1.5、累积快照事实表1.6、拉链表 2、ETL策略2.1、全量同步2.2、增量同步 3、任务调度3.1、为什么需要任务调度&#xff1f;3.2、常见任务类型3.3、常见调度工具 1、表的…

适合引流源码声音鉴定神器网站源码,轻松吸引用户关注

源码介绍 声鉴卡HTML5网页源码&#xff0c;完整可运转&#xff0c;调用wx录音&#xff0c;自动判断声音属性&#xff0c;输出结果 安装教程 只需要把源码上传至主机空间就可以 支持上传二级目录访问&#xff01;提示一下&#xff1a;wxvx打开效果是最佳的源码里面生成二维码…

深入了解队列:探索FIFO数据结构及队列

之前介绍了栈&#xff1a;探索栈数据结构&#xff1a;深入了解其实用与实现&#xff08;c语言实现栈&#xff09; 那就快马加鞭来进行队列内容的梳理。队列和栈有着截然不同的工作方式&#xff0c;队列遵循先进先出&#xff08;FIFO&#xff09;的原则&#xff0c;在许多场景下…

工具系列:TensorFlow决策森林_(5)使用文本和神经网络特征

文章目录 设置使用原始文本作为特征使用预训练的文本嵌入同时训练决策树和神经网络构建模型训练和评估模型 欢迎来到 TensorFlow决策森林&#xff08; TF-DF&#xff09;的 中级教程。 在本文中&#xff0c;您将学习有关 TF-DF的一些更高级的功能&#xff0c;包括如何处理自…