快速排序和归并排序的非递归形式

news2025/1/14 18:20:59

        快速排序和归并排序都需要用递归的形式展开,那么有没有什么方法不需要递归就能实现归并和快速排序,有的!

 1.快速排序

        我们可以借助栈来模拟递归。

        递归的主要思想就是大事化小,小事化了。我们借助栈的 目的是将需要排序的“头” 和 “尾”找到,进而排序,然后找到合适的keyi并放入合适的位置,再将keyi两边的“头” 和 “尾”入栈,找到合适的keyi......如此重复下去.......

        keyi需要入栈吗?keyi不需要入栈,因为keyi已经在合适的位置了

前后指针法,结合上一篇博客来看, 

int PatrSort3(int* a, int begin, int end)
{

	int prev = begin, cur = begin+1;

	int keyi = begin;

	int midi = GetMidIndex(a , begin ,end);
	Swap(&a[keyi],&a[midi]);

	while (cur <= end)
	{
		//cur位置小于keyi发生交换
		if (a[cur] < a[keyi] && ++prev != cur)
		{
			//++prev;
			Swap(&a[prev], &a[cur]);
		}

		cur++;
	}

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

	keyi = prev;
	return keyi;

}
void QuickSortNonR(int* a, int begin, int end)
{
	ST st;
	STInit(&st);
	STPush(&st,end);
	STPush(&st, begin);

	while (!STEmpty(&st))
	{
		int left = STTop(&st);
		STPop(&st);

		int right = STTop(&st);
		STPop(&st);

		int keyi = PatrSort3(a,left,right);

		if (keyi + 1 < right)
		{
			STPush(&st,right);
			STPush(&st,keyi+1);
		}

		if (left < keyi - 1)
		{
			STPush(&st, keyi - 1);
			STPush(&st, left);
		}

	}

	STDestroy(&st);
}

2.归并排序

        归并排序的基本思想在上一篇已经讲过,快速排序是先对整个数组中选出适中的的keyi放到合适的位置,然后切分子块,层层递归,进行排序,快速排序类似于前序遍历。归并排序是先找到最小的子块,然后层层排序,层层归并,归并排序类似于后序遍历。

        归并排序还存在越界的问题:每个子区间应该怎么样确定,能给出明确的边界吗?

        边界是怎么确定的:

 

        gap每次增加是上一次的2倍,当gap = 4 时, 数组有10个元素,我们控制循环是按照一下的方式来控制的。

        当 i = 0 的时候 begin1 end1 ,begin2 end2 。[0 ,3]  [4 ,7]  。

        进入下一轮循环: i = 8 , begin1 end1 ,begin2 end2 。[8,11]  [12 ,15] 。

 

        此时问题来了,数组只有十个元素,下标为 10-15  已经越界访问了 ,这是我们要处理越界访问问题。

        

void MergeSortNonR(int* a, int n)
{

	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
	}

	int gap = 1;
	while (gap < n)
	{
		printf("gap:%d->", gap);
		for (int i = 0; i < n; i += 2*gap)
		{

		
			//[i,i+gap-1] [i+gap ,i + 2*gap-1] 控制边界
			int begin1 = i;
			int end1 = i + gap - 1;
			int begin2 = i + gap;
			int end2 = i + 2 * gap - 1;


			//越界,修正边界
			if (end1 >= n)
			{
				end1 = n - 1;

				// [begin2, end2]修正为不存在区间
				begin2 = n;
				end2 = n - 1;
			}
			else if (begin2 >=n)
			{
			// [begin2, end2]修正为不存在区间
				begin2 = n;
				end2 = n - 1;
			}
			else if (end2 >= n)
			{
				end2 = n - 1;
			}

			printf("[%d,%d] [%d, %d]--", begin1, end1, begin2, end2);

			int m = end2 - begin1+1;
			int j = begin1;

 			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] < a[begin2])
				{
					tmp[j++] = a[begin1++];
				}
				else
				{
					tmp[j++] = a[begin2++];
				}
			}

			while (begin1 <= end1)
			{
				tmp[j++] = a[begin1++];
			}

			while (begin2 <= end2)
			{
				tmp[j++] = a[begin2++];
			}
			
		memcpy(a+i, tmp+i, sizeof(int) * m);


		}
	//	memcpy(a, tmp, sizeof(int) * m);
	
		printf("\n");
		
		gap *= 2;
 	}

	free(tmp);

}
void TestMergeSort()
{
	int a[] = { 9, 1, 2, 5, 7, 4, 8, 6, 3, 5 };
	//MergeSort(a, sizeof(a) / sizeof(int) );
	MergeSortNonR(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

归并排序的特性总结:
        1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
        2. 时间复杂度:O(N*logN)
        3. 空间复杂度:O(N)
        4. 稳定性:稳定

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面试题:有了 for 循环 为什么还要 forEach ?

文章目录 **本质区别****for循环和forEach的语法区别****for循环和forEach的性能区别** js中那么多循环&#xff0c;for for…in for…of forEach&#xff0c;有些循环感觉上是大同小异今天我们讨论下for循环和forEach的差异。我们从几个维度展开讨论&#xff1a; for循环和fo…

RJ45网络信号浪涌保护器解决方案

RJ45网络信号浪涌保护器是一种用于保护网络设备免受雷击或其他高压电流干扰的装置&#xff0c;它可以有效地吸收和释放信号线路上的过电压&#xff0c;从而避免设备损坏或数据丢失。 RJ45信号浪涌保护器的应用领域和施工方案如下&#xff1a; 地凯科技RJ45网络信号浪涌保护器…

合肥综合性国家科学中心人工智能研究院-机器学习作业(一)

1.试析min-max规范化和z-score规范化的优缺点 可参考博客&#xff1a;https://wenku.csdn.net/answer/fdbf30eb204644e5b69fc533a3757268 2.试分析损失函数与性能度量的关系 损失函数和性能度量之间的关系可以根据优化目标来理解。损失函数的优化目标是最小化预测值与实际值之…

laravel框架 - 开发实战(目录结构,路由,控制器,模型,视图)

一、laravel框架的目录结构 app:应用目录&#xff0c;保存项目中的控制器、模型等 bootstrap:保存框架启动的相关文件 config:配置文件目录 database:数据库迁移文件和数据填充文件 public:应用入口文件index.php和前端资源文件&#xff08;如CSS、JavaScript等&#xff09…

都2023年了你还不学ts (一)

TypeScript基础语法入门 TypeScript究竟是什么&#xff1f; 他主要就是想把JavaScript里面不完美的一些语法来进行一个提升 就像官网中所说的 TypeScript is JavaScript with syntax for types. 例如我们看下面的这段代码 if ("" 0) {console.log(hello) }在Jav…

VS新功能:智能添加函数标记

今天&#xff0c;我们官宣 Visual Studio 预览版的两项新功能&#xff1a; 1) 标记类成员函数为 const。 2) 标记全局函数为 static。 标记类成员函数为 const 如果一个类成员函数不会修改对象的状态&#xff0c;则 Visual Studio 会给出建议&#xff0c;将这个函数标记为 c…

Python统计pdf中英文单词的个数

之前的文章提供了批量识别pdf中英文的方法,详见【python爬虫】批量识别pdf中的英文,自动翻译成中文上。以及自动pdf英文转中文文档,详见【python爬虫】批量识别pdf中的英文,自动翻译成中文下。    本文实现python统计pdf中英文字符的个数。 文章目录 一、要统计字符的pdf…

JDK14特性——GC的改进和优化

文章目录 G1的NUMA内存分配优化NUMA介绍目标 弃用SerialCMS,ParNewSerial Old理由 删除CMSCMS弊端其他垃圾收集器 ZGC on macOS and Windows G1的NUMA内存分配优化 NUMA介绍 NUMA就是非统一内存访问架构&#xff08;英语&#xff1a;non-uniform memory access&#xff0c;简…

【Flask】会话保持-API授权-注册登录

http - 无状态-无法记录是否已经登陆过 #会话保持 – session cookie session – 保存一些在服务端 cookie – 保存一些数据在客户端 session在单独服务器D上保存&#xff0c;前面数个服务器A,B,C上去取就好了&#xff0c;业务解耦。—》》现在都是基于token的验证。 以上是基…

SpringMVC自定义注解和使用

一.引言 1.简介&#xff1a; 在Spring MVC中&#xff0c;我们可以使用自定义注解来扩展和定制化我们的应用程序。自定义注解是一种通过Java的注解机制定义的特殊注解&#xff0c;可以应用于控制器类、方法或者方法参数上&#xff0c;以实现不同的功能和行为。&#xff08;注解…

[uni-app] iOS/Android端 禁止单个页面侧滑返回的处理记录

需要禁止部分页面侧滑返回 iOS端 popGesture 但是实测后, 其实设置popGesture:none 是无效的 真正可以用的是这个 disableSwipeBack android端 别的方案没有逐一尝试, 这边可以在需要禁止的页面的 onBackPress onBackPress() {// 禁止侧滑(但注意也会禁止导航返回,导航返…

如何在外网访问公司项目?快解析实现内网ip让公网连接

随着互联网技术的不断发展&#xff0c;越来越多的企业和个人选择使用服务器进行网站或应用程序的部署。公司内部项目需要提供外网访问是个常见的网络场景&#xff0c;需要怎么操作设置也是网络或项目人员需要关注的。 企业使用服务器搭建公司业务系统一般会使用云服务器或者使…

最新AI创作系统ChatGPT源码/支持国内AI模型/支持GPT4.0/支持AI绘画

一、AI创作系统 SparkAi系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT系统&#xff1f;小编这里写一个详细图文教程吧&am…

WebGPU学习(10)---如何利用 WebGPU 实现高性能

虽然是WebGPU&#xff0c;但是速度很慢&#xff01;&#xff1f; 我们将解释如何充分利用 WebGPU 性能。这次我们以绘制大量物体为例&#xff0c;根据“使用纹理”中的代码进行一些更改并绘制 900 个立方体。 要均匀分布立方体&#xff0c;可以按如下方式更新 worldMatrix&am…

微信小程序 解决 当套在scroll-view中后 wx.pageScrollTo 函数失效问题解决

pageScrollTo 只是 页面的API 他对 scroll-view 的滚动是无法控制的 但是 scroll-view 也提供了一个scroll-into-view属性 我们编写一个小案例 wxml 参考代码如下 <view><scroll-view scroll-y"{{ true }}" style"height: 100vh;" scroll-into-v…

笑笑云航服悦《乡村振兴战略下传统村落文化旅游设计》许少辉博士新著

笑笑云航服悦《乡村振兴战略下传统村落文化旅游设计》许少辉博士新著

Android高级开发-APK极致优化

九道工序 1. SVG(Scalable Vector Graphics)可缩放矢量图 使用矢量图代替位图可以减小 APK 的尺寸&#xff0c;因为可以针对不同屏幕密度调整同一文件的大小&#xff0c;而不会降低图像质量。 矢量图首次加载时可能消耗更多的 CPU 资源。之后&#xff0c;二者的内存使用率和…

Spring 篇

1、什么是 Spring&#xff1f; Spring是一个轻量级的IOC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架&#xff0c;目的是用于简化企业应用程序的开发&#xff0c;它使得开发者只需要关心业务需求。常见的配置方式有三种&#xff1a;基于XML的配置、基于注解的配置…

06JVM_类加载器

一、类加载器 以JDK8为例&#xff1a; ①启动类加载器 ②扩展类加载器 ③应用程序类加载器 ④自定义类加载器 ①类加载器具有层级关系&#xff0c;当加载一个类的时候&#xff0c;要看所有的上级有没有加载此类。【双亲委派模式】 ②类加载器负责在运行时将Java类动态加载…

4.开放-封闭原则

这个原则其实是有两个特征&#xff0c;一个是说‘对于扩展是开放的(Open for extension)&#xff0c;另一个是说‘对于更改是封闭的(Closed for modification)[ASD]。