快速排序hoare优化

目录

三数取中法选key

优化点

基本思想 

代码实现 

小区间优化

优化点

基本思想

代码实现


由于hoare版快排在一些特殊情况下性能并不优,这里我们进行一些优化。 

三数取中法选key

优化点

  • 当数据有序时,快排就会很吃力,这是为什么呢?

因为有序时,left要找小,right要找大,都找不到,就会一直从头找到尾,时间复杂度就会上升到O(N^2)。在debug版本下,如果数据上万,就会栈溢出。

基本思想 

  • 三数取中:取三个数中的中位数下标,选到合适的数,避免选取到最小的最大的数,对顺序结构的效率优化很好。
  • 取的是下标❗
  • 数值两两比较
  • 对快速排序的单趟的优化,三数取中是走快速排序逻辑(每趟的优化)

代码实现 

int GetMidi(int* a, int begin, int end)
{
	int midi = (begin + end) / 2;
	// begin end midi三个数选中位数
	if (a[begin] < a[midi])
	{
		if (a[midi] < a[end])
			return midi;
		else if (a[begin] > a[end])
			return begin;
		else
			return end;
	}
	else
	{
		if (a[midi] > a[end])
			return midi;
		else if (a[begin] < a[end])
			return begin;
		else
			return end;
	}
}
 
void QuickSort(int* a, int begin, int end)
{
	if (begin >= end)
		return;
 
	int midi = GetMidi(a, begin, end);
	Swap(&a[midi], &a[begin]);
 
	int left = begin, right = end;
	int keyi = begin;
 
	while (left < right)
	{
		// 右边找小
		while (left < right && a[right] >= a[keyi])
		{
			--right;
		}
 
		// 左边找大
		while (left < right && a[left] <= a[keyi])
		{
			++left;
		}
 
		Swap(&a[left], &a[right]);
	}
 
	Swap(&a[left], &a[keyi]);
	keyi = left;
 
	// [begin, keyi-1] keyi [keyi+1, end]
	QuickSort(a, begin, keyi - 1);
	QuickSort(a, keyi+1, end);
}

小区间优化

优化点

  • 当快排递归到小的子区间时,比如就只有7个数据,我们却还需要再递归7次才能返回结果。没有必要。
  • 当数据很少时,用希尔/堆排/快排都很杀鸡用牛刀,这个时候我们只需用直接插入排序即可。

也就是说,当快排递归到小的子区间时,我们考虑使用插入排序,这就是小区间优化。

基本思想

  • 主要优化递归层数的最后3~4层
  • 最后3~4层的递归层数占据了总的递归层数的80%。

  • 区间是[begin,end] ,此区间的数据量是end-begin+1。当数据量end-begin+1<=10的时候,让序列执行直接插入排序
  • 每段数据序列被分割了,起始位置并不都是a,要用a+begin表示

代码实现

int GetMidi(int* a, int begin, int end)
{
	//...
}

void QuickSort(int* a, int begin, int end)
{
	if (begin >= end)
		return;

	if (end - begin + 1 <= 10)
	{
		InsertSort(a + begin, end - begin + 1);
	}
	else
	{
		//三数取中的代码...
	}
}
  • 注意:小区间优化在release版本下,并不会与没优化的快多少,因为release已经优化了很多了。

hoare版本总代码

void InsertSort(int* a, int n)
{
	//[0,end]end+1插入
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (a[end] > tmp)
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;
	}
}

void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

int GetMidi(int* a, int begin, int end)
{
	int midi = (begin + end) / 2;
	// begin midi end 三个数选中位数
	if (a[begin] < a[midi])
	{
		if (a[midi] < a[end])
			return midi;
		else if (a[begin] > a[end])
			return begin;
		else
			return end;
	}
	else // a[begin] > a[midi]
	{
		if (a[midi] > a[end])
			return midi;
		else if (a[begin] < a[end])
			return begin;
		else
			return end;
	}
}

int PartSort1(int* a, int begin, int end)
{
	int midi = GetMidi(a, begin, end);
	Swap(&a[midi], &a[begin]);

	int left = begin, right = end;
	int keyi = begin;

	while (left < right)
	{
		// 右边找小
		while (left < right && a[right] >= a[keyi])
		{
			--right;
		}

		// 左边找大
		while (left < right && a[left] <= a[keyi])
		{
			++left;
		}

		Swap(&a[left], &a[right]);
	}

	Swap(&a[left], &a[keyi]);

	keyi = left;
	return keyi;
}

void QuickSort(int* a, int begin, int end)
{
	if (begin >= end)
		return;

    //<10个数字走插入逻辑 
	if (end - begin + 1 <= 10)
	{
		InsertSort(a + begin, end - begin + 1);
	}
    else
    {
	    int keyi = PartSort1(a, begin, end);
	    QuickSort(a, begin, keyi - 1);
	    QuickSort(a, keyi+1, end);
    }
}

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

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

相关文章

OpenJDK 目前主要发展方向

Loom&#xff1a;得赶紧解决 synchronized pin 线程的问题&#xff08;据说 Java 23 会解决&#xff0c;现在有预览版&#xff09;。各个 Java 库需要改造原来使用 ThreadLocal 的方式&#xff1a;如果是为了穿参数&#xff0c;则可以使用 ScopedLocal&#xff1b;如果是对象池…

如何解决新版的anaconda notebook 打不开浏览器

1 安装nodejs 先安装nodejs&#xff0c;里面有很多需要用node来启动服务 2 一片空白 安装jupyter以后启动&#xff0c; 结果就得到了如下&#xff0c;在chrome里面打开以后&#xff0c;一片空白 3 列出环境 conda create --name pytorch python3.9 conda env list cond…

【数学建模】Topsis法python代码

昨天学习了Topsis法的基本概念&#xff0c;今天就来一起实践一下&#xff0c;用python实现topsis法 代码分块解释 1、引入numpy库 numpy as np 2、输入参评与指标数目 # 用户输入参评数目和指标数目&#xff0c;将输入的字符串转换为数值 print("请输入参评数目&#…

在DeepLn环境中安装VLLM与ChatGLM3

DeepLn | 智慧算力触手可及是一个挺便宜的算力租用平台&#xff0c;里面有大量的显卡可以租用。唯一美中不足的是&#xff0c;提供的pytorch版本低&#xff0c;只支持到2.01&#xff0c;为了匹配vllm&#xff0c;需要手动安装指定版本的pytorch。 vllm介绍 总体而言&#xff0…

AHU 数据库 实验四

【实验名称】 实验4 数据库的嵌套查询和集合查询 【实验目的】 1. 理解并掌握子查询的概念和作用&#xff1b; 2. 掌握DBMS 实现嵌套查询的基本方法和应用&#xff1b; 3. 掌握DBMS 实现集合查询的基本方法和应用&#xff1b; 4. 学习、掌握并熟练…

Spring Boot 面试题及答案整理,最新面试题

Spring Boot中的自动配置是如何工作的&#xff1f; Spring Boot的自动配置是其核心特性之一&#xff0c;它通过以下方式工作&#xff1a; 1、EnableAutoConfiguration注解&#xff1a; 这个注解告诉Spring Boot开始查找添加了Configuration注解的类&#xff0c;并自动配置它们…

Python中random模块:随机数生成与应用

random模块介绍 随机数在计算机编程中扮演着重要的角色&#xff0c;它们被广泛应用于游戏开发、密码生成、仿真等众多领域。 Python提供了丰富而强大的random模块&#xff0c;旨在方便开发者生成高质量的随机数&#xff0c;随机选择和操作数据。 本文将介绍Python中random模…

OB_GINS学习

OB_GINS学习 组合导航中的杆臂测量加速度计的零偏单位转换受到经纬度以及高程影响的正常重力位的计算公式大地坐标系&#xff08;LBH&#xff09;向空间直角坐标系&#xff08;XYZ&#xff09;的转换及其逆转换导航坐标系&#xff08;n系&#xff09;到地心地固坐标系&#xff…

记录一个编译的LLVM 含clang 和 PTX 来支持 HIPIFY 的构建配置

llvm 18 debug 版本 build llvmorg-18.1rc4 debug $ cd llvm-project $ git checkout llvmorg-18.1.0-rc4 $ mkdir build_d $ cd build_d $ mkdir -p ../../local_d cmake \ -DCMAKE_INSTALL_PREFIX../../local_d \ -DLLVM_SOURCE_DIR../llvm \ -DLLVM_ENABLE_PROJECTS&…

深入理解Hive:探索不同的表类型及其应用场景

文章目录 1. 引言2. Hive表类型概览2.1 按照数据存储位置2.2 按照数据管理方式2.3 按照查询优化2.4 按照数据的临时性和持久性 3. 写在最后 1. 引言 在大数据时代&#xff0c;Hive作为一种数据仓库工具&#xff0c;为我们提供了强大的数据存储和查询能力。了解Hive的不同表类型…

Mybatis-plus连接多数据源操作(SQLServer、MySQL数据库)

Mybatis-plus连接多数据源操作&#xff08;SQLServer、MySQL数据库&#xff09; 一、依赖二、yml配置文件三、业务类四、测试 一、依赖 <!--mybatis多数据源--><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spri…

springboot260火锅店管理系统

火锅店管理系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装火锅店管理系统软件来发挥其高效…

上海雷卯湿敏元器件存储及使用规范

湿敏等级是指材料或产品对湿度变化的敏感程度。它用于评估材料或产品在湿度变化条件下的稳定性和可靠性。 湿敏等级通常通过数字表示&#xff08;如MSL- Moisture Sensitivity Level&#xff09;&#xff0c;从1到6级不等&#xff0c;每个级别代表不同的湿敏程度。较低的级别表…

方程式工具包远程溢出漏洞图形界面版V0.3(内置永恒之蓝、永恒冠军、永恒浪漫等)

Part1 前言 大家好&#xff0c;我是ABC_123。我从年前到现在&#xff0c;一直在整理曾经写过的红队工具&#xff0c;逐步把自己认为比较好用的原创工具发出来给大家用一用&#xff0c;方便大家在日常的攻防比赛、红队评估项目中解放双手&#xff0c;节省时间精力和体力。本期给…

前端WebRTC局域网1V1视频通话

基本概念 WebRTC&#xff08;Web Real-Time Communications&#xff09; 网络实时通讯&#xff0c;它允许网络应用或者站点&#xff0c;在不借助中间媒介的情况下&#xff0c;建立点对点&#xff08;Peer-to-Peer&#xff09;的连接&#xff0c;实现视频流和音频流或者其他任…

机器学习中的经典算法总结

经典算法 有监督算法逻辑回归支持向量机SVM决策树朴素贝叶斯K近邻&#xff08;KNN&#xff09; 无监督算法K-meansPCA主成分分析预留模版 有监督算法 逻辑回归 简介 逻辑回归是机器学习中一种经典的分类算法&#xff0c;通常用于二分类任务&#xff0c;基本思想是构建一个线性…

力扣---简化路径

给你一个字符串 path &#xff0c;表示指向某一文件或目录的 Unix 风格 绝对路径 &#xff08;以 / 开头&#xff09;&#xff0c;请你将其转化为更加简洁的规范路径。 在 Unix 风格的文件系统中&#xff0c;一个点&#xff08;.&#xff09;表示当前目录本身&#xff1b;此外…

ZigBee技术与实践教程(无线传感网技术第三天)

1.MAC层规范 在IEEE802系列标准中&#xff0c;OSI参考模型的数据链路层进一步划分为逻辑链路控制子层和介子访问子层两个子层。MAC子层使用物理层提供的服务实现设备之间的数据帧传输&#xff0c;而LLC在MAC 层的基础上&#xff0c;在设备之间提供面向连接和非连接的服务&…

中国大学生计算机设计大赛--智慧物流挑战赛基础

文章目录 一、Ubuntu基础1.1 基本操作1.2 文本编辑 二、ROS基础介绍2.1 概念与特点2.2 基本结构2.3 创建工程2.4 节点和节点管理器2.5 启动文件 三、ROS通信机制3.1 话题3.2 服务3.3 动作3.4 参数服务器 四、ROS可视化工具4.1 rviz4.2 rqt4.3 tf 五、Python实现简单的ROS节点程…

Vue.js计算属性:实现数据驱动的利器

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…