当前位置: 首页 > news >正文

归并排序延伸-非递归版本

非递归版本的归并排序是从已经有序的小数组开始逐渐到大数组的一个循环,这个时候我们需要创建临时的一个数组来存放排好序的数,因为我们如果直接交换就会导致之后没办法毕竟,所以我们需要这样做。其次我们还需要考虑数组为非偶数的情况,因为我们不能平分数组,所以我们需要额外来考虑这种情况,如果为含有奇数个元素的数组,则会导致最后一个组第二层循环结束时只有一个元素,这时begin2>=n或者加begin2==end2就直接跳出循环,而之后如果遇到begin2==n-1,end2又越界了,我们不能结束循环,因为我们需要来进行排序的,所以我们让end2=n-1这样就不会越界了,至于什么是begin1 end1 begin2 end2

我们可以让一个数组为1 2 3 4最小数组为1    2    3    4,这个时候每个数组有1个元素,则gap=1,这个时候就结束循环,如果为2 个元素的数组,那么我们开始的时候由于begin1为0,end1也为0,我们需要根据定义来求出end1由于end1-begin1=gap-1,而begin2为end1+1,end2为begin2+2*gap-1,我们如果是这样理解就变得简单了,那么如何让这个begin1的初始值改变呢?这个我们可以用一个for循环来让begin1=i,然后一直排序,当然最外围需要一个判断条件是gap<n的while循环,否则我们无法进行每一个数组的排序,这我们每一次结束一次while循环就相当于一次递归的结束,然后两个子数组就合并成一个数组,那么这个时候begin2为i+gap而我们也可以按照我那种方式写,这样方便理解,里面的排序就相当于之前的归并排序算法(不知道的可以直接去看我之前的博客)。所以最终代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include<stdbool.h>
#include<stddef.h>//NULL
#include<time.h>
//非递归版本的归并排序
void MergeSortNonR(int* a, int n)
{
	//创建一个数组
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail1!\n");
		exit(1);
	}
	//初始时令gap=1因为我们的最开始数组只有一个元素
	int gap = 1;
	while (gap < n)
	{
		//根据gap划分组,两两一合并
		//但是我们每一次都需要让i跨过两个数组的距离即为2*gap
		for (int i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i;
			int end1 = i + gap - 1;
			int begin2 = i + gap;
			int end2 = i + 2 * gap - 1;
			//如果begin2>=n越界了,我们就需要直接结束循环
			//为什么不是跳过这个情况?
			//因为这样已经遍历到最后一个数组了,所以我们直接跳出循环
			if (begin2 >= n)
			{
				break;
			}
			//如果end2越界了,则我们要让end2置为n-1
			if (end2 >= n)
			{
				end2 = n - 1;
			}
			//定义一个下标来存储有序的数组
			int index = begin1;
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] < a[begin2])
				{
					tmp[index++] = a[begin1++];
				}
				else
				{
					tmp[index++] = a[begin2++];
				}
			}
			//有一个数组没有插入完全
			while (begin1 <= end1)
			{
				tmp[index++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[index++] = a[begin2++];
			}
			//导入到原来数组中
			//这个函数可以自己去搜一下它的用法
			memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));
		}
		//需要进行gap的变化(每一次完成合并后都有gap=2*gap
		gap *= 2;
	}
}
//测试
int main()
{
	int a[] = { 5,4,6,3,8,2,9,0,1,7 };
	int n = sizeof(a) / sizeof(a[0]);
	printf("排序之前: ");
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	MergeSortNonR(a, n  );
	printf("\n排序之后: ");
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	return 0;
}

运行结果:

这个非递归算法的理解难度比递归的难多了,但是也是有好处的,有兴趣的可以去用!

http://www.dtcms.com/a/107802.html

相关文章:

  • 基于yolo11的BGA图像目标检测
  • Ubuntu18.04 编译 Android7.1代码报错
  • 使用numpy读取数据集
  • Ubuntu Wayland启动腾讯会议并实现原生屏幕共享
  • JS—页面渲染:1分钟掌握页面渲染过程
  • C语言实现排序
  • spring-ai-alibaba第六章阿里dashscope集成mcp百度翻译tools
  • Java 大视界 -- Java 大数据在智慧文旅虚拟场景构建与沉浸式体验增强中的技术支撑(168)
  • STM32F103_LL库+寄存器学习笔记14 - CAN发送完成中断
  • 【小兔鲜】day02 Pinia、项目起步、Layout
  • 2023年CIE SCI1区TOP:序列融合麻雀搜索算法ISSA,深度解析+性能实测
  • N元语言模型的时间和空间复杂度计算
  • 【网络协议】三次握手与四次挥手
  • 【区块链 + 可信存证】创世云区块链存证平台 | FISCO BCOS 应用案例
  • Redis 数据结构的底层实现—字符串、哈希表、列表、集合
  • 【银河麒麟系统常识】命令:reboot(立即重启操作系统)
  • SQL server 2022和SSMS的使用案例1
  • linux,物理机、虚拟机,同时内外网实现方案;物理机与虚拟机互通网络;
  • 机器学习 分类算法
  • 苍穹外卖day12
  • 网络安全的重要性与防护措施
  • 一、STM32简介
  • OpenCV 图形API(10)用于执行标量除以矩阵的逐元素操作函数divRC()
  • 低代码框架
  • 网络协议之系列
  • 商标知识产权管理系统平台有哪些功能?
  • 第三方平台步步紧逼之下,独立站商城系统应如何做
  • MoLe-VLA:通过混合层实现的动态跳层视觉-语言-动作模型实现高效机器人操作
  • 牛脸分割数据集labelme格式1324张1类别有增强图片
  • macvlan 和 ipvlan 实现原理及设计案例详解