C++快速排序超详细讲解

2025-03-18 01:50
文章标签 c++ 讲解 快速 排序 详细

本文主要是介绍C++快速排序超详细讲解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《C++快速排序超详细讲解》快速排序是一种高效的排序算法,通过分治法将数组划分为两部分,递归排序,直到整个数组有序,通过代码解析和示例,详细解释了快速排序的工作原理和实现过程,需要的朋友可以参考下...

一、快速排序原理

快速排序(QuickjlrDBSort)是一种基于分治法的高效排序算法。它的基本思想是通过一个称为“基准”(pivot)的元素将数组划分为两部分,一部分的所有元素都比基准小,另一部分所有元素都比基准大,然后递归地对这两部分进行同样的操作,直到整个数组有序。 

二、快速排序标准代码

void quick_sort(int q[], int l, int r)
{
	if (l >= r) return; //递归停止条件
	int i = l - 1, j = r + 1, x = q[l + r >> 1]; //设定指针,基准
	while (i < j)
	{
		do i++; while (q[i] < x); //q[i]大于等于基准时,指针i停止
		do j--; while (q[j] > x); //q[j]小于等于基准时,指针j停止
		if (i < j) swap(q[i], q[j]); //判断是否i<j,交换i,j对应的数组元素
	} // 结束时数组被分为 >=x,<=x 的两部分
	quick_sort(q, l, j); //继jlrDB续分直到分到一到两个元素此时数组有序
	quick_sort(q, j + 1, r);
}

三、代码解析

我们以一个简单的例子帮助我们了解快速排序

53412

1.排序的数组以及需要排序元素的范围,无返回值

void quick_sort(int q[], int l, int r)

 2.递归结束的条件:元素剩一个或空

if (l >= r) return;

3.设定变量,其中 i, j 为两个指针分别减 1 加 1 是为了下一步的 do while 循环,x 即为“基准”(pivot) 用来将列表分为 <=x 和 >=x 的两部分,x 是随机的,这里取了数组中间的一个元素,l + r >> 1相当于 (l + r)/2 (pivot:q[2] = 4)向下取整(提高了效率)

int i = l - 1, j = r + 1, x = q[l + r >> 1];
53412
C++快速排序超详细讲解01234C++快速排序超详细讲解 j

4.while循环实现了遍历、比较、交换的功能,先使 i 指针递增直到 i 所对应的元素 >=x 停止,接下来使 j 指针递减直到其对应的元素 <=x 停止

while (i < j)
{
	do i++; while (q[i] < x);
	do j--; while (q[j] > x);
	if (i < j) swap(q[i], q[j]);
}
53412
i(>=4停止)j(<=4停止)

交换之后开启下一次循环

23415
<4<4i(>=4停止)j(<=4停止)>4

满足 i<j 交换

23145
<4<4j(<=4停止)i(>=4停止)

>4

不满足 i<j 不交换,此时整个 while 循环结束,注意此时 j(包含)往左为 <=4 部分,j + 1 及其往右为 >=4部分 

5.接下来就是递归了,每次运行分将数组为左<=右的两部分,我们只需将左右两部分分别执行函数程序得到直到剩两个或一个元素,此时数组便有序了

quick_sort(q, 0, 2); 
23145
<4<4j(<=4停止)i(>=4停止)

>4

x(pivot)=3

231
<3i(>=3停止)j(<=3停止)
213
<3j(<=3停止)i(>=3停止)
quick_sort(q, 0, 1); 

x(pivot)=2

2

1
i(>=2停止)j(<=2停止)

1

2
j(<=2停止)i(>=2停止)

剩一个元素时,执行递归停止程序:

if (l >= r) return;

 数组中最初的“左”部分就变为

123

而最初的“右”部分:x(pivot)=4

45
i(>=4停止)j(<=4停止)>5
if (i < j) swap(q[i], q[j]);

不满足 if 条件jlrDB以及 while 条件,while 循环停止,依旧选择了 j 为分界点分到一个元素时结束递归

此时代码全部有序

12345
quick_sort(q, l, j); 
quick_sort(q, j + 1, r);

6.总结

快速排序利用两个指针对数组的元素进行比较交换进行部分排序,再利用递归整体排序

四、使用while循环的快速排序

1.代码

代码1.由快排代码等价转化而来

void quick_sort(int q[], int l, int r)
{
    if (l >= r) return;
    int i = l, j = r, x = q[l + r >> 1];
    while (i < j)
    {
        while (q[i] < x) i++;
        while (q[j] > x) j--;
        if (i < j)
        {
            swap(q[i], q[j]);
            if (i + 1 < j - 1)
            {
                i++;
                j--;
            }
            else
            {
                i++;
                j--;
                while (q[i] < x) i++;
                while (q[j] > x) j--;
                break;
            }
        }
    }
    quickjs_sort(q, l, j);
    quick_sort(q, j + 1, r);
}

代码2.效率提高版

void quick_sort(int q[], int l, int r) {
	if (l >= r) return;
	int x = q[l + r >> 1];
	int i = l, j = r;
	while (i <= j) { // 注意:这里应该是 i <China编程= j 而不是 i < j
		while (q[i] < x) i++;
		while (q[j] > x) j--;
		if (i <= j) {
			swap(q[i], q[j]);
			i++;
			j--;
		}
	}
	quick_sort(q, l, j);   
	quick_sort(q, i, r);   
}

2.代码2解析

1.因为没有 do 过程,所以指针起始位置直接设在了 0 和 -1 的位置,

if (l >= r) return;
int x = q[l + r >> 1];
int i = l, j = r;
53412
iC++快速排序超详细讲解C++快速排序超详细讲解j

2. while 循环中的 while 循环先判断是否满足条件,满足的话指针加/减 1,这样停止时依旧是对应元素 >=x 或 <=x 时的指针,

while (i <= j) 
{ 
	while (q[i] < x) i++;
	while (q[j] > x) j--;
	if (i <= j)
    {
		swap(q[i], q[j]);
		i++;
		j--;
	}
}
53412
i(停)j(停)

换过之后+=或--

23415
<4i(停)j(停)

交换,++/--

23145
ji

不满足 i<=j while 循环结束.

关于 i<=j 的条件判断,我们给出新的案例

321
i(停)j(停)

交换之后 ++/--

123
i(停) j(停)

注意此时并没有返回(return),

递归代码:分别以 j 和 i 作为分界点

quick_sort(q, l, j);   
quick_sort(q, i, r);   

而如果条件判断为 < 的话 i=j 时就会造成下一次递归多了一个元素,

而标准代码的运行过程到此处后结束,以 j 和 j+1 为分界点不会造成此问题.

因此再进行一次循环

123
ji

而此时元素 2 的位置是 i,j同时停过的位置即为基准 x,而i,j也会再下一次++/--后停止,所以我们可以直接将元素 2 所对应的数组位置固定不动,将元素 2 左右的数组递归处理. 

quick_sort(q, l, j);   
quick_sort(q, i, r);   

五、总结

使用 while 循环会比 do while 多一层内层循环,所以 do while 循环效率更高,建议只用 do while 循环.

到此这篇关于C++快速排序的文章就介绍到这了,更多相关C++快速排序内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于C++快速排序超详细讲解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153803

相关文章

Python包管理工具核心指令uvx举例详细解析

《Python包管理工具核心指令uvx举例详细解析》:本文主要介绍Python包管理工具核心指令uvx的相关资料,uvx是uv工具链中用于临时运行Python命令行工具的高效执行器,依托Rust实... 目录一、uvx 的定位与核心功能二、uvx 的典型应用场景三、uvx 与传统工具对比四、uvx 的技术实

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

canal实现mysql数据同步的详细过程

《canal实现mysql数据同步的详细过程》:本文主要介绍canal实现mysql数据同步的详细过程,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的... 目录1、canal下载2、mysql同步用户创建和授权3、canal admin安装和启动4、canal

SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程

《SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程》LiteFlow是一款专注于逻辑驱动流程编排的轻量级框架,它以组件化方式快速构建和执行业务流程,有效解耦复杂业务逻辑,下面给大... 目录一、基础概念1.1 组件(Component)1.2 规则(Rule)1.3 上下文(Conte

Springboot3+将ID转为JSON字符串的详细配置方案

《Springboot3+将ID转为JSON字符串的详细配置方案》:本文主要介绍纯后端实现Long/BigIntegerID转为JSON字符串的详细配置方案,s基于SpringBoot3+和Spr... 目录1. 添加依赖2. 全局 Jackson 配置3. 精准控制(可选)4. OpenAPI (Spri

C++作用域和标识符查找规则详解

《C++作用域和标识符查找规则详解》在C++中,作用域(Scope)和标识符查找(IdentifierLookup)是理解代码行为的重要概念,本文将详细介绍这些规则,并通过实例来说明它们的工作原理,需... 目录作用域标识符查找规则1. 普通查找(Ordinary Lookup)2. 限定查找(Qualif

MySQL复杂SQL之多表联查/子查询详细介绍(最新整理)

《MySQL复杂SQL之多表联查/子查询详细介绍(最新整理)》掌握多表联查(INNERJOIN,LEFTJOIN,RIGHTJOIN,FULLJOIN)和子查询(标量、列、行、表子查询、相关/非相关、... 目录第一部分:多表联查 (JOIN Operations)1. 连接的类型 (JOIN Types)

SpringBoot整合Apache Flink的详细指南

《SpringBoot整合ApacheFlink的详细指南》这篇文章主要为大家详细介绍了SpringBoot整合ApacheFlink的详细过程,涵盖环境准备,依赖配置,代码实现及运行步骤,感兴趣的... 目录1. 背景与目标2. 环境准备2.1 开发工具2.2 技术版本3. 创建 Spring Boot

使用Python实现base64字符串与图片互转的详细步骤

《使用Python实现base64字符串与图片互转的详细步骤》要将一个Base64编码的字符串转换为图片文件并保存下来,可以使用Python的base64模块来实现,这一过程包括解码Base64字符串... 目录1. 图片编码为 Base64 字符串2. Base64 字符串解码为图片文件3. 示例使用注意

Linux使用scp进行远程目录文件复制的详细步骤和示例

《Linux使用scp进行远程目录文件复制的详细步骤和示例》在Linux系统中,scp(安全复制协议)是一个使用SSH(安全外壳协议)进行文件和目录安全传输的命令,它允许在远程主机之间复制文件和目录,... 目录1. 什么是scp?2. 语法3. 示例示例 1: 复制本地目录到远程主机示例 2: 复制远程主