快速排序(三路划分)解决大量重复元素

排序算法之三路划分的快速排序 当待排序元素序列中有大量的重复排序码时,简单的快速排序算法的效率将会降到非常之低。一种直接的想法就是将待排序列分成三个子序列:一部分是排序码比基准元素排序码小的;一部分是与基准元素排序码等值的;一部分是比基准元素排序码大的,如下图所示: 但是,如果我们直接据此思想去编写实现算法的话,会让我们面临很大的困难。与基准元素等值的元素到底有多少?以及如何最快速有效地确定划分的边界?所以,完成这样的三路 阅读详情

#include<iostream>
#include<cstdlib>
#include<ctime>
#define M 20

using namespace std;
static int count_insert = 0;
static int count_partion = 0;

typedef struct index
{
 	  int left;
 	  int right;
}index;

void swap(int& small, int& big)
{
	int temp = small;
	small = big;
	big = temp;
}
/*
|简述下插入排序:
|
|cur = 1 ->  right 为待排序部分,pre代表已排序部分。
|
|先把当先位置元素arr[cur]存入tmp,然后比较arr[pre]和arr[cur],
|如果待排序部分arr[cur] < arr[pre],则arr[pre + 1] = arr[pre]移位
|移位的目的是把较小的元素,这里是arr[cur]放入到已排序部分适当的位置
|这样每次arr[cur]都会被arr[pre]所覆盖,这也就是为什么刚开始tmp = arr[cur]的原因
|然后把tmp放置到arr[pre]位置处
*/
void insert_sort( int arr[], int left, int right)
{
	int tmp, cur , pre;
	for (cur = 1; cur < right; cur++)
	{
		pre = cur - 1;
		tmp = arr[cur];

		while ( tmp < arr[pre] && pre >= 0)
		{
			arr[pre + 1] = arr[pre];
			pre--;
		}
		arr[pre] = tmp;
	}
	count_insert += 1;
}
/*
|简述下算法思路:
|当出现大量重复元素时,显然可以加以控制,改进效率。
|
|在划分循环中,每当扫描指针(i, j)停止时,交换i,j处的元素;
|同时判断指针处元素是否等于划分元素base;
|如果arr[i]等于划分元素,则把arr[i]和数组左边的元素交换;
|如果arr[j]等于划分元素,则把arr[j]和数组右边的元素。
|
|最后把两端的和划分元素相等的区域,移到数组中间来。
*/
index partion(int arr[], int left, int right)
{
	int i , j;
	int pleft, pright;
	int tag, base;
	index p;
	
	if ( left > right ) exit(-1) ;
	
	i = left - 1, j = right;
 	pleft = left - 1, pright = right;
 	base = arr[right];
	//@_1 
	for (;;)
	{
	    while ( i < j && arr[ ++i ] < base );
	    	  
	    while ( i < j && arr[ --j ] > base ) if ( j <= left ) break;
  	  	  
  	  	if ( j == i ) break;
  	  	  
  	  	swap( arr[j] , arr[i]); // @_2

		if ( arr[i] == base )
  	  	 {
   	 		pleft += 1;
			swap(arr[i], arr[pleft]);   	 	  
         }
              
         if ( arr[j] == base )
         {
 	  		pright -= 1;
 	  	    swap( arr[j], arr[pright]);//@_3
		 }
	}//for
	 
	swap( arr[right], arr[i]); //@_4
	
	j = i - 1; i = i + 1;
	
	for (tag = left; tag <= pleft; tag++, j--) swap(arr[tag], arr[j]);
	
	for (tag = right - 1 ; tag >= pright; tag--, i++) swap(arr[tag], arr[i]);//@_5
	
	p.left = j, p.right = i ;

	count_partion += 1;
	
	return p;  
}

/*
| 如果划分后子文件的长度小于20,则用插入排序,
|否则快速排序。
|在经过N此递归划分后,会产生大量的比如长度为arr[0 -> 10]这样的小文件
|此时继续快速排序显然得不偿失。
*/
void quick_sort(int arr[], int left, int right)
{
	if ( left < right )
	{
		if ( (right - left) <= M )
			insert_sort(arr, left, right);
		else
		{
			index sec = partion(arr, left, right);
			quick_sort(arr, left, sec.left);
			quick_sort(arr, sec.right, right);
		}
	}
}

int main()
{
	
	const int size = 500;
	static int s[size];
	srand(unsigned int ( time(NULL)));
	for (int i = 0; i < size; i++)
		s[i] = rand()%100;

	quick_sort(s, 0, size-1);

	for (i = 0; i < size; i++)
		cout << s[i] << " ";
	cout << endl;
	cout << "call insert_sort  " << count_insert << " times" <<endl;
	cout << "call partion_sort  " << count_partion << " times" <<endl;

	cin.get();

	return 0;
}









































【不看会后悔系列】排序之——快速排序优化(随机数key,三值取中,三路划分,自省排序)【最全三路划分讲解】 优快云最详细快排优化,三路划分讲解,不看会后悔系列~~~ 阅读详情

相关推荐

IPSec Over GRE和GRE Over IPSec技术

IPSec Over GRE 和 GRE Over IPSec 一. 技术介绍 IPsec     主要作用是对数据进行加密,因为他能提供所有有时候被单独用作实现加密的一种方法!IPsec建立的是一个逻辑隧道,并不是真正意义上的隧道!并且不能提供路由功能,因为IPsec不支持非ip流量,也不支持广播(组播)! GRE     (通用路由封装)能很好的提供一个真正意义上的点对点的隧道,GRE是一种三层VPN封装技术。GRE可以对某些网络层协议(如IPX、Apple Talk、IP等)的报文进行封装,使封装后

qq_56228347的博客 9870

快速排序之重复元素过多的改进

快速排序快的一点毛病没有(重新贴一下代码):def qsort(arr,lo,hi): if hi-lo&lt;=1: return pivot=arr[lo] i,j=lo+1,hi-1 while True: while i&lt;hi and arr[i]&lt;=pivot: i+=1 ...

六六先森的博客 6969

ENVI遥感技术

记录2024.03.06所遇到的遥感问题

qq_44453923的博客 4332

必学算法之快速排序及其改进方案

必学算法之快速排序及其改进方案

qq_41583040的博客 1702

视觉辅助RIS波束追踪:用摄像头“看见”用户,实现毫秒级波束对准

在无线通信领域,波束成形技术是提升高频段信号覆盖与质量的核心手段,其原理是通过调整天线阵列的相位,使信号能量在特定方向相干叠加,形成高增益定向波束。这项技术的价值在于能有效克服高频信号路径损耗大、穿透性差的瓶颈,广泛应用于5G/6G、毫米波通信及室内定位等场景。然而,传统波束追踪依赖信道估计或波束扫描,存在训练开销大、实时性差的问题。本文聚焦于一种创新解决方案:将计算机视觉与可重构智能表面(RIS)相结合。通过摄像头直接感知用户位置,并利用RIS快速重构反射波束方向,实现了近乎零开销、毫秒级延迟的波束追踪,

weixin_33552698的博客 620

Matlab实战:水声信号DEMON谱分析从入门到精通(附完整源码)

本文详细介绍了使用Matlab进行水声信号DEMON谱分析的完整流程,从基础理论到实战应用,涵盖信号预处理、包络提取、频谱分析等关键步骤,并附完整源码。特别针对水声通信中的低信噪比环境,提供了多种优化方案和性能提升技巧,帮助读者快速掌握这一水下目标检测的核心技术。

gamma的博客 296

【排序算法】快速排序的分析改进

基本的快速排序最基本的快速排序是由C.A.R.Hoare在1960年提出的,快速排序的算法是一种分治排序算法它将数组划分为两个部分,然后分别对两个部分进行排序快速每次对数组重新排序,选择一个基准值key,然后让数组满足下面的两个个条件·a[l], ... ,a[i - 1]之中的元素都比key值要小·a[i + 1], ... ,a[r]之中的元素都比key值要大然后通过划分来完成排序,递归的去处...

Qregi的博客 1万+

软件设计师---钉子户

软件设计师---钉子户

我从不打没有准备的仗! 2万+

快速排序遇到数组内含相同元素时的解法

今天刷蓝桥杯题时,遇到了快速排序的算法,题目很简单,就是简单的不超过10个数字的快排,我很快的写完了一提交,正确率为90%。错误原因为超时。于是我在想总共就10个数字,怎么会超时呢,会不会时陷入了死循环。于是我检查代码。我觉得可能出现问题的循环就是快排中的i++和j--那块。有一想只有10%错误会不会是某种特殊情况。突然想到数组里有元素重复的情况。于是我简单的在<和>右面加上了“=”号...

weixin_41851621的博客 7440

Android系统内存和性能关系的调研

摘要:本文分析了低内存导致性能问题的判断方法和评估思路。通过监控/proc/vmstat中的allocstall_normal、pageoutrun等指标可判断内存回收频率,当MemFree、MemAvailable和Cached均低于500MB时可能出现明显卡顿。全文通过实验和理论验证分析,回答因内存瓶颈导致性能问题的一些分析和解决的思路。

jidapenglin28的专栏 130

TI单芯片毫米波雷达1642demo代码走读(一)

今天我们来实际看下代码。 首先使用CCS软件导入demo工程,工程有两个,一个是ARM的工程,工程名是mmw_mss_16xx;另一个是DSP的工程,工程名为mmw_dss_16xx。我们将这两个工程的主函数打开,分别位于mss_main.c和dss_main.c文件中。 先看mss的主函数,代码如下。我为每行代码都加了中文注释和自己的理解。 int main (void) { Task_Params taskPara...

1万+

【数据结构】从快速排序优化到外部文件归并排序

排序是计算机科学中最基础的问题之一,在实际开发中无处不在。然而,面对不同的数据规模和场景,我们需要选择或设计合适的排序算法。快速排序的优化:介绍三路划分快速排序(处理大量重复元素)和自省排序(防止递归过深)两种改进版本。外部文件归并排序:当数据量超过内存容量时,如何利用磁盘文件进行排序。文章将结合具体C语言代码,分析算法思想、实现细节,并指出潜在的问题和改进方向。三路划分快速排序通过将相等元素集中,避免了重复比较,适合大量重复数据的场景。自省排序。

键盘敲碎了雾霭的博客 447

Arduino、ESP32驱动SFA40甲醛传感器(气体传感器篇)

SFA40甲醛传感器是一款基于盛思锐电化学原理的专业HCHO检测模块,具备卓越的抗酒精干扰能力(乙醇交叉敏感度<0.3%)、高达±20ppb的检测精度及0~1000ppb的宽量程。该传感器内置SHT4X温湿度传感器进行自动补偿,确保数据的长期稳定性;其小尺寸、低功耗的特性,可快速集成至智能家居、空气净化器、物联网环境监测等系统中,实现对甲醛浓度的精准、可靠监测。

不脱发的程序猿 302

排序算法03——快速排序之三路查找和自省排序

此时cur位置的数据大于key,所以和right进行交换,right自减,指向倒数第二个位置。交换后,cur的位置为9,仍然大于key,所以继续和right进行交换,交换完后自减,right指向倒数第三个位置。交换完后,此时cur位置的数据为4,小于key,所以和left进行交换,交换完后,cur自增,left自增。如上图所示,默认最左侧的值为key,在在对key寻找合适位置的过程中,有着多个相同的数据,将这些相同的数据放到一起,left和right下标最终是用来指示这些相同的数据的左右位置。

Ljwuhe的博客 925

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

排序算法第三辑——交换排序

交换排序算法详解

qq_41934502的博客 577

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

C语言入门(快速排序之三路划分)

三路划分快速排序是针对含大量重复元素数组的高效排序算法。相比传统快速排序将数组分为两部分,三路划分通过lt、i、gt三个指针将数组分为小于、等于和大于基准值的三个区域。这种方法能一次性处理所有重复元素,避免重复比较和交换,使平均时间复杂度稳定在O(nlogn),有效解决了传统快排处理重复元素时性能退化的问题。算法实现时通过一次遍历完成三路划分,仅需递归处理两侧区域,特别适合成绩、年龄等重复数据较多的排序场景,是工程实践中常用的优化方案。

nplplus的博客 7195

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

【数据结构与算法】三路划分处理快速排序遇到大量重复数据效率下降的情况

【数据结构与算法】三路划分处理快速排序遇到大量重复数据效率下降的情况

重铸自身根基的博客 942

【三路快速排序算法】深度解析:原理、图示与Java实现

三路快速排序是快速排序的高级变种,由Dijkstra提出的荷兰国旗问题演变而来。它将数组划分为三个部分,特别适合处理**包含大量重复元素**的排序场景。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 1万+

快速排序 详解(快速排序 双路快排 三路快排)

注:内容,图片来自于慕课网liuyubobobo老师的课程。 快速排序 快速排序可以说是20世纪最伟大的算法之一了。相信都有所耳闻,它的速度也正如它的名字那样,是一个非常快的算法了。当然它也后期经过了不断的改进和优化,才被公认为是一个值得信任的非常优秀的算法。 c++中algorithm中的sort一般都是用的快排(在快排恶化的情况下才会转换成其它的排序)。 核心思想:分治 ...

k_koris的博客 3万+

深入理解 快速排序 之三路划分算法

快速排序的三路划分算法通过将数组划分为三个部分,有效地处理了包含大量重复元素的数组,避免了不必要的交换操作,提高了算法的效率。该算法在实际应用中具有重要的价值,尤其是在处理大规模数据时。通过本文的详细介绍,你应该对快速排序的三路划分算法有了更深入的理解。如果你在实际应用中遇到相关问题,可以根据具体情况选择合适的排序算法。希望本文能对你有所帮助!如果你有任何疑问或建议,欢迎在评论区留言。

2501_90200491的博客 1238

深入解析C语言三路快速排序算法

传统快速排序采用二路划分:选择一个基准值(pivot)将数组分为两部分:小于等于基准值的元素和大于基准值的元素c// 传统二路快排分区函数j < high;j++) {i++;return i;问题:当数组包含大量重复元素时,会导致分区不平衡,递归深度增加,性能退化到O(n²)。

hello world/linux 1383

三路快速排序

双路快速排序的时间复杂度为O(nlog2n),空间复杂度为O(n) 双路快速排序的核心思想:单路快排会将等于V的元素分配在左侧或者右侧,当数组中有大量重复元素时,这将会导致左右两侧的元素数量极度不均衡,时间复杂度退化到O(n^2),,如下图所示:为了避免该问题,双路快排是将等于V的部分近乎平均的分配在左右两侧;三路快排是将等于V的部分集中到中间,左右两侧分别为小于V和大于V的部分,这样不用对大量...

muzigef的博客 2268

三路快排(基于三指针单趟排序的快速排序)+快排时间复杂度再分析

快速排序终章

小青菜的博客 3106

数据结构与算法-三路排序

三路快速排序是快速排序的一种变体,它通过将数组划分为三个部分(小于基准值、等于基准值、大于基准值)来减少比较次数和提高排序效率。这种排序算法特别适用于含有大量重复元素的数组,因为可以有效地处理这些重复元素,从而提高整体性能。本文将深入探讨三路快速排序的原理、实现步骤,并通过具体的案例代码详细说明三路快速排序的每一个细节。

菜鸟小码的博客 1626
上一篇: 快速排序 (解决小划分文件)
下一篇: QT :: Qwizard 用法
错_对
博客等级 码龄16年 68粉丝 80原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值