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

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

使用EasyPoi快速导出Word文档功能的实现步骤

《使用EasyPoi快速导出Word文档功能的实现步骤》EasyPoi是一个基于ApachePOI的开源Java工具库,旨在简化Excel和Word文档的操作,本文将详细介绍如何使用EasyPoi快速... 目录一、准备工作1、引入依赖二、准备好一个word模版文件三、编写导出方法的工具类四、在Export

Python中isinstance()函数原理解释及详细用法示例

《Python中isinstance()函数原理解释及详细用法示例》isinstance()是Python内置的一个非常有用的函数,用于检查一个对象是否属于指定的类型或类型元组中的某一个类型,它是Py... 目录python中isinstance()函数原理解释及详细用法指南一、isinstance()函数

Python的pandas库基础知识超详细教程

《Python的pandas库基础知识超详细教程》Pandas是Python数据处理核心库,提供Series和DataFrame结构,支持CSV/Excel/SQL等数据源导入及清洗、合并、统计等功能... 目录一、配置环境二、序列和数据表2.1 初始化2.2  获取数值2.3 获取索引2.4 索引取内容2

uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)

《uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)》在uni-app开发中,文件上传和图片处理是很常见的需求,但也经常会遇到各种问题,下面:本文主要介绍uni-app小程序项目中实... 目录方式一:使用<canvas>实现图片压缩(推荐,兼容性好)示例代码(小程序平台):方式二:使用uni

Python屏幕抓取和录制的详细代码示例

《Python屏幕抓取和录制的详细代码示例》随着现代计算机性能的提高和网络速度的加快,越来越多的用户需要对他们的屏幕进行录制,:本文主要介绍Python屏幕抓取和录制的相关资料,需要的朋友可以参考... 目录一、常用 python 屏幕抓取库二、pyautogui 截屏示例三、mss 高性能截图四、Pill

C++读写word文档(.docx)DuckX库的使用详解

《C++读写word文档(.docx)DuckX库的使用详解》DuckX是C++库,用于创建/编辑.docx文件,支持读取文档、添加段落/片段、编辑表格,解决中文乱码需更改编码方案,进阶功能含文本替换... 目录一、基本用法1. 读取文档3. 添加段落4. 添加片段3. 编辑表格二、进阶用法1. 文本替换2

C++中处理文本数据char与string的终极对比指南

《C++中处理文本数据char与string的终极对比指南》在C++编程中char和string是两种用于处理字符数据的类型,但它们在使用方式和功能上有显著的不同,:本文主要介绍C++中处理文本数... 目录1. 基本定义与本质2. 内存管理3. 操作与功能4. 性能特点5. 使用场景6. 相互转换核心区别

java时区时间转为UTC的代码示例和详细解释

《java时区时间转为UTC的代码示例和详细解释》作为一名经验丰富的开发者,我经常被问到如何将Java中的时间转换为UTC时间,:本文主要介绍java时区时间转为UTC的代码示例和详细解释,文中通... 目录前言步骤一:导入必要的Java包步骤二:获取指定时区的时间步骤三:将指定时区的时间转换为UTC时间步