【八大排序(五)】快排进阶篇-挖坑法+前后指针法

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:八大排序专栏⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习排序知识
  🔝🔝


在这里插入图片描述

快排进阶篇

  • 1. 前情回顾
  • 2. 思路回顾
  • 3. 单趟快排挖坑法
  • 4. 挖坑法代码实现
  • 5. 单趟快排前后指针法
  • 6. 前后指针法代码实现
  • 7. 总结以及拓展

1. 前情回顾

我们上一章快排初阶 中介绍了
快排的思想和代码实现.
上一期单趟快排
介绍的是hoare版本
今天给大家分享挖坑法和前后指针法

注意:本章介绍的方法均用左边作为基准值

在这里插入图片描述


2. 思路回顾

基本思想: 🆙

  • 从待排序的数组中选取一个基准值.
    (我们把基准值记为key)

  • 再将数组分为两部分:
    1. 左子数组所有元素小于基准值
    2. 右子数组所有元素大于基准值

  • 左右子数组再选基准值重复这个过程

基准值key的选取: 🆙

采用三数取中法,详情见上一节快排初阶


怎么实现左右子序小于大于key: 🆙
有三种版本的方法:

  1. hoare版本(发明快排的人想出的方法)
  2. 挖坑版本(国内大佬想出的)
  3. 前后指针版本

3. 单趟快排挖坑法

基本思路: 🆙

  • 找到基准值,并记录下来
  • 将基准值的位置挖个坑位
  • 右边r先走,找比基准值小的
  • 找到后将这个值扔在坑中
  • 它本身变成新坑.以此类推
  • 当左边和右边相遇时
  • 将记录下来的key放在坑位

我们先定义一个无序数组:

int a[10]={6,1,2,7,9,3,4,5,10,8};

我们把最左边元素作为基准值

画图理解: 🆙

在这里插入图片描述

就这样右找到扔进坑位,左再找扔进坑位
直到左右l 和 r相遇.会发生这种情况:

在这里插入图片描述

走完单趟快排后,基准值6的
左子数组都小于它
右子数组都大于它

这说明: 🆙
6这个值已经来到了最终排好序时
它应该出现的位置

接下来我们只需要不断递归
基准值的左右子序就可以使
整个数组有序


4. 挖坑法代码实现

这里我直接省略掉三数取中函数:
GetMidIndex详情请看快排初阶

这是单趟快排: 🆙

//单趟快排(挖坑版本)
int Partion2(int* a, int left, int right)
{
	//三数取中--面对有序的情况不会栈溢出(key不会选到最大或者最小的数)
	int mini = GetMidIndex(a, left, right);
	swap(&a[left], &a[mini]);
	int key = a[left];
	int pit = left;//坑位起始位置是基准值的位置
	
	while (left < right)
	{
		//右边找小,放在左边的坑位中
		while (a[right] >= key && left < right)
		{
			right--;
		}
		a[pit] = a[right];//将找到的值扔进坑位
		pit = right;//自身变成新坑位
		
		//左边找大,放在右边的坑位中
		while (a[left] <= key && left < right)
		{
			left++;
		}
		a[pit] = a[left];//找到的值扔进坑位
		pit = left;//自己变成新坑位
	}
	a[pit] = key;//最终将相遇时的坑位给上最开始记录的key值
	return pit;//返回基准值(或者叫坑位)的位置,方便递归
}

这是递归调用函数: 🆙

void QuickSort(int* a, int left, int right)
{
	if (left >= right)
	{
		return;
	}
	int key = Partion2(a, left, right);
	QuickSort(a, left, key - 1);//递归左子序列
	QuickSort(a, key + 1, right);//递归右子序列
}

5. 单趟快排前后指针法

基本思路: 🆙

  • 定义两个指针cur和prev
  • cur指向第二个元素
  • prev指向cur前面的元素
  • c找比基准值小的值
  • 找到后停下,p向后走一格
  • 再交换c和p指向的值
  • 最后c走完数组后:
  • 交换key和prev的值

我们还是使用挖坑法的数组:

int a[10]={6,1,2,7,9,3,4,5,10,8};

我们把最左边元素作为基准值

画图理解: 🆙

在这里插入图片描述
和挖坑法一样:

走完单趟快排后,基准值6的
左子数组都小于它
右子数组都大于它

这说明: 🆙
6这个值已经来到了最终排好序时
它应该出现的位置

接下来我们只需要不断递归
基准值的左右子序就可以使
整个数组有序

并且前后指针法和挖坑法

得出的左右子数组顺序不一样

说明它们的底层思想是不同的


6. 前后指针法代码实现

单趟快排: 🆙

//单趟快排(前后指针版本)
int Partion3(int* a, int left, int right)
{
	//三数取中--面对有序的情况不会栈溢出(key不会选到最大或者最小的数)
	int mini = GetMidIndex(a, left, right);
	swap(&a[left], &a[mini]);
	int key = left;
	int prev = left;
	int cur = left + 1;
	while (cur <= right)
	{
		while (a[cur] >= a[key] && cur <= right)//cur指针找小于key的
		{
			++cur;
		}
		if (cur <= right)
		{
			swap(&a[++prev], &a[cur]);
			cur++;//交换完后,cur要再往后走一步
		}
	}
	swap(&a[key], &a[prev]);// 最后交换prev和key的值
	return prev;//返回基准值的位置,方便下次递归
}

递归函数: 🆙

//快速排序
void QuickSort(int* a, int left, int right)
{
	if (left >= right)
	{
		return;
	}
	int key = Partion3(a, left, right);
	QuickSort(a, left, key - 1);
	QuickSort(a, key + 1, right);
}

7. 总结以及拓展

总结: 🆙
不管是hoare,挖坑还是指针版本
它们都有一个特性:
递归函数总体是不变的
改变的只是单趟快排实现的方法!

并且,不论是哪种方法实现单趟快排
算法效率也就是时间复杂度都是一样的

快排总归是抽象的
下面有一段快速排序过程
可以帮助你再深刻理解一下这个过程:

快速排序

拓展: 🆙

其实很多高效率的排序都是对
低效率的排序做的优化:

比如:

  • 快速排序实质上
    是对冒泡排序的一种改进

  • 堆排序实质上
    是对选择排序的一种改进

  • 希尔排序实质上
    是对插入排序的一种改进

排序在面试基本是必问的内容
往往面试官不会只问你快排的递归版
而是一层层剖析你的学识,问快排的递归
就会问快排的非递归.
所以非递归版本
将是你和其他面试者
拉开差距的关键一环!

在这里插入图片描述

学编程这一行只能说学无止境
一种方法可以延申出无数种解法


🔎 下期预告:快速排序终极篇 🔍

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java方法

文章目录 一、java方法总结 一、java方法 在前面几个章节中我们经常使用到 System.out.println()&#xff0c;那么它是什么呢&#xff1f; println() 是一个方法。 System 是系统类。 out 是标准输出对象。这句话的用法是调用系统类 System 中的标准输出对象 out 中的方法 pr…

docker部署prometheus+grafana视图监控

效果 一、grafana可视化平台部署 docker run -d \--namegrafana \--restartalways \-p 3000:3000 \grafana/grafanagrafana我也是部署在170.110服务器上&#xff0c;192.168.170.110:3000访问grafana 默认账号密码都是admin 二、部署exportor采集信息 针对各类数据库平台系统…

ch8_1_CPU的结构和功能

1. cpu的结构 1.1CPU 的功能 控制器的功能 控制器的功能具体作用取指令指令控制分析指令操作控制执行指令&#xff0c; 发出各种操作命令控制程序输入与结果的输出时间控制总线管理处理中断处理异常情况和特殊请求数据加工 运算器的功能 实现算术运算 和 逻辑运算&#x…

我的256创作纪念日

机缘 挺开心的&#xff0c;想到自己未曾写过一些非技术类的博客&#xff0c;恰巧今天刚好也是我的256创作纪念日&#xff0c;就乘着这个日子&#xff0c;写一点自己过去的收获、内心的想法和对未来的展望吧。 本人不才&#xff0c;只就读于一所民办本科之中&#xff0c;我挺不想…

【linux】探索Linux命令行中强大的网络工具:netstat

文章目录 前言一、netstat是什么&#xff1f;二、使用方法1.常用参数2.实例演示3.更多功能 总结 前言 在Linux命令行中&#xff0c;有许多实用的工具可帮助我们管理和监控网络连接。其中一个最重要的工具就是netstat&#xff0c;它提供了丰富的网络连接和统计信息&#xff0c;…

在windos中同时使用gitee与github

1.为什么这样做&#xff1f; 原因非常简单&#xff0c;我们遇到自己喜欢的git仓库后&#xff0c;通常会将他们克隆到我们本地电脑上&#xff0c;但这个时候会有一个问题&#xff0c;就是我们喜欢的仓库有可能是gitee仓库&#xff0c;也有可能是github仓库&#xff0c;这个时候…

web性能检测工具lighthouse

About Automated auditing, performance metrics, and best practices for the web. Lighthouse 可以自动检查Web页面的性能。 你可以以多种方式使用它。 浏览器插件 作为浏览器插件&#xff0c;访问chrome网上商店 搜索Lighthouse 插件安装。以两种方式使用。 方式一 安装…

命名管道:FIFO

至此&#xff0c;我们还只能在相关的程序之间传递数据&#xff0c;即这些程序是由一个共同的祖先进程启动的。但如果我们想在不相关的进程之间交换数据&#xff0c;这还不是很方便。 我们可以用FIFO文件来完成这项工作&#xff0c;它通常也被称为命名管道&#xff08;named pip…

分布式重试服务平台 Easy-Retry

文章目录 [toc] 1.简介1.1[爱组搭官网](http://aizuda.com/)1.2介绍1.3 相关地址 2.架构2.1系统架构图2.2 客户端与服务端数据交互图 3.业内成熟重试组件对比4.快速开始4.1 服务端项目部署4.1.0 初始化脚本4.1.1 源码部署4.1.2 Docker部署 4.2 客户端集成配置4.2.1 添加依赖4.2…

青岛科技大学|物联网工程|物联网定位技术(第三讲)|15:40

目录 物联网定位技术&#xff08;第三讲&#xff09; 1. 试简述C/A码的作用、构成 请画出C/A码生成电路简图并给予原理性的说明 2. 试简述 P码的作用、构成 请画出P码生成电路简图&#xff0c;并给予原理性的说明 3. GPS信号是如何进行伪码扩频与解扩 请画图给予说明 4…

被抄袭声明

我&#xff08;受害者&#xff09;的博客主页&#xff1a; ChuckieZhu的博客_CSDN博客-MATLAB,Python,Django领域博主 抄袭者&#xff08;施害者&#xff09;博客主页&#xff1a; 洋洋菜鸟的博客_CSDN博客-python实例,数学建模,python基础领域博主 问题说明&#xff1a; …

vue结合elementui表格el-table实现弹窗checkbox自定义列显示隐藏,刷新保持上次勾选不丢失,附完整代码

el-table实现自定义列显示隐藏 有时候表格太多列&#xff0c;要是默认全都显示就会很拥挤&#xff0c;又不能固定只显示某些列&#xff0c;这时候我们可以让用户自定义要显示隐藏哪些列。 网上很多教程都是用的v-if&#xff0c;但是v-if非常麻烦&#xff0c;每一列都要写判断条…

Volo.Abp升级小记(二)创建全新微服务模块

文章目录 创建模块领域层应用层数据库和仓储控制器配置微服务 测试微服务微服务注册添加资源配置配置网关 运行项目 假设有一个按照 官方sample搭建的微服务项目&#xff0c;并安装好了abp-cli。 需要创建一个名为GDMK.CAH.Common的模块&#xff0c;并在模块中创建标签管理功能…

Centos环境 使用docker 部署MySQL 8.X详细版本

文章目录 安装docker配置docker 阿里镜像加速阿里云容器镜像服务ACR配置镜像源 安装部署MySQL拉取MySQL镜像创建挂载文件测试部署部署MySQL进入容器将它的mysql配置同步给宿主机删除test1测试容器 正式部署MySQL查看正式部署的容器状态配置远程连接字符集以及关闭跳过密码验证等…

基于STM32C8T6的智能小车项目时钟配置

一、时钟树简介 HSE 是高速的外部时钟信号&#xff0c;可以由有源晶振或者无源晶振提供&#xff0c;频率从 3-25MHZ 不等。当使用有源晶振时&#xff0c;时钟从 OSC_IN 引脚进入&#xff0c;OSC_OUT 引脚悬空&#xff0c;当选用无源 晶振时&#xff0c;时钟从 OSC_IN 和 OSC_OU…

【工作中遇到的性能优化问题】

项目场景&#xff1a; 页面左侧有一列表数据&#xff0c;点击列表项会查对应的表格数据和表单信息&#xff08;表单是根据数据配置生成的&#xff09;&#xff0c;并在右侧展示。如果数据量大&#xff0c;则非常卡。 需要对此页面进行优化。 问题描述 问题一、加载左侧数据时…

spring boot+easyui粮油质量管控防伪溯源系统源码

基于物联网技术、RFID技术和RSA、PGP加密算法开发的粮油质量追溯系统 粮油安全关系千千万万消费者的健康问题。近年来&#xff0c;许多食品行业安全事故频频涌现&#xff0c;成为社会关注焦点。粮油生产加工质量管控防伪溯源系统为粮油提供从种植、生产、加工、销售等各环节的…

L9110S电机驱动模块demo

0.资料 项目工程文件夹 分文件原理 1.认识L9110S 1、概述&#xff1a; 一个L9110S驱动可以控制一个电机&#xff0c;图中左右两个黑色芯片就是L9110S驱动。当然如果会硬件也可以直接把它们设计到单片机开发板上。 一个电机由两个针脚控制&#xff0c;我们用杜邦线让L9110S…

Modbus通信介绍 网络高级工具使用

目录 Modbus简介 ModbusTCP协议格式 》1.报文头&#xff08;共7字节&#xff09; 》2.功能码 》3.数据 练习&#xff1a;读传感器数据&#xff0c;读1个寄存器数据&#xff0c;写出主从数据收发协议。 练习&#xff1a;写出控制IO设备开关的协议数据&#xff0c;操作1个…

【2】Midjourney注册

随着AI技术的问世&#xff0c;2023年可以说是AI爆炸性成长的一年&#xff0c;近期最广为人知的AI服务除了chatgpt外&#xff0c;就是从去年五月就已经问世的AI绘画工具mid journey了。 ▲几个AI工具也代表了人工智能的热门阶段 只要输入一段文字&#xff0c;AI就会根据语意计算…