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++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

Python与MySQL实现数据库实时同步的详细步骤

《Python与MySQL实现数据库实时同步的详细步骤》在日常开发中,数据同步是一项常见的需求,本篇文章将使用Python和MySQL来实现数据库实时同步,我们将围绕数据变更捕获、数据处理和数据写入这... 目录前言摘要概述:数据同步方案1. 基本思路2. mysql Binlog 简介实现步骤与代码示例1

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

Java中HashMap的用法详细介绍

《Java中HashMap的用法详细介绍》JavaHashMap是一种高效的数据结构,用于存储键值对,它是基于哈希表实现的,提供快速的插入、删除和查找操作,:本文主要介绍Java中HashMap... 目录一.HashMap1.基本概念2.底层数据结构:3.HashCode和equals方法为什么重写Has

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Java使用正则提取字符串中的内容的详细步骤

《Java使用正则提取字符串中的内容的详细步骤》:本文主要介绍Java中使用正则表达式提取字符串内容的方法,通过Pattern和Matcher类实现,涵盖编译正则、查找匹配、分组捕获、数字与邮箱提... 目录1. 基础流程2. 关键方法说明3. 常见场景示例场景1:提取所有数字场景2:提取邮箱地址4. 高级

Python多线程实现大文件快速下载的代码实现

《Python多线程实现大文件快速下载的代码实现》在互联网时代,文件下载是日常操作之一,尤其是大文件,然而,网络条件不稳定或带宽有限时,下载速度会变得很慢,本文将介绍如何使用Python实现多线程下载... 目录引言一、多线程下载原理二、python实现多线程下载代码说明:三、实战案例四、注意事项五、总结引

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数

Springboot项目构建时各种依赖详细介绍与依赖关系说明详解

《Springboot项目构建时各种依赖详细介绍与依赖关系说明详解》SpringBoot通过spring-boot-dependencies统一依赖版本管理,spring-boot-starter-w... 目录一、spring-boot-dependencies1.简介2. 内容概览3.核心内容结构4.