数据结构【初阶】--排序(归并排序和基数排序)

目录

一.归并排序的非递归写法

1.思想应用 

2.代码基本实现 

(1)单趟归并逻辑 

(2)多趟(循环)的控制条件

① 迭代条件:i+=2*gap

② 结束条件:i(或i<=n-2*gap)<>

(3)代码展示 

① 单趟逻辑

②整体逻辑 

3.优化代码 

(1)end1和begin2越界 

(2)begin2不越界而end2越界

 二.计数排序

1.思想应用 

2.(直接映射)逻辑图示 

3.优点以及局限性 

4.针对分散的数据进行优化 

(1)(相对映射)图示解析 

(2)代码实现 


一.归并排序的非递归写法

1.思想应用 

采用思想:一个数肯定是有序的,就每一个数和另一个数归并成一个含有两个数的有序序列,然后一个含有两个数的有序序列在和另一个含有两个数的有序序列归并成一个含有四个数的有序序列,依次类推,最后整体有序。 

  • 图示 

 

2.代码基本实现 

(1)单趟归并逻辑 

  • 图示 

 

(2)多趟(循环)的控制条件

① 迭代条件:i+=2*gap
  • 图示 
② 结束条件:i<n(或i<=n-2*gap)

 

(3)代码展示 

① 单趟逻辑
    int* tmp = (int*)malloc(sizeof(int) * n);//开辟一个新数组
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
    int gap = 1;
	for (size_t i = 0;i<n;i+=2*gap)
	{
		int begin1 = i,end1=i+gap-1;//第一组数据的首尾
		int begin2 = i + gap,end2=i+2*gap-1;//第二组数据的首尾
		//[begin1,end1][begin2,end2]--归并区间
		int j = begin1;
		while (begin1 <= end1 && begin2 <= end2)
		{
            //小数向前调(尾插)
			if (a[begin1] < a[begin2])
			{
				tmp[j++] = a[begin1++];
			}
            //大数向后调(尾插)
			else
			{
				tmp[j++] = a[begin2++];
			}
		}
        //由于上面的begin1和begin2是分别向后走,一定有一个没走完
        //这里控制没走完的继续走
		while (begin1 <= end1)
		{
			tmp[j++] = a[begin1++];
		}

		while (begin2 <= end2)
		{
			tmp[j++] = a[begin2++];
		}
		memcpy(a + i, tmp + i, sizeof(int) *2*gap);//每归并两个数就拷贝回去
	}
	gap *= 2;
  • 效果 

 

②整体逻辑 
void MergeSortNonR(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	int gap = 1;
	while (gap < n)//控制多趟
	{
		for (size_t i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			//[begin1,end1][begin2,end2]--归并区间
			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) * 2 * gap);//每归并两个数就拷贝回去
		}
		gap *= 2;
	}
	free(tmp);
}
  • 效果演示 

 

  •  存在问题 

此样例给的数组数据个数恰好可以通过测试,但是代码本身存在问题导致其并不适用于所有样例,例如:

 我们观察一下分割的区间来看一看问题所在:

下面对代码进行改进。

3.优化代码 

(1)end1和begin2越界 

由于begin1=i,所以可以判断begin1是不可能越界的,那么越界的就可能是end1和begin2。(这里先不考虑begin2不越界而end2越界的情况。)

  • 解决方式 :发生越界时直接跳出循环
	if (end1 >= n || begin2 >= n)//begin2或end1越界
	{
		break;
	}

(2)begin2不越界而end2越界

  • 解决方式:修改end2的值,并且调整拷贝数据的大小 
//优化部分
if (end1 >= n || begin2 >= n)//begin2或end1越界
{
	break;
}
if (end2 >= n)
{
	end2 = n - 1;
}

memcpy(a + i, tmp + i, sizeof(int) * (end2-i+1));
  • 完整代码 
void MergeSortNonR(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	int gap = 1;
	while (gap < n)
	{
		for (size_t i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			//[begin1,end1][begin2,end2]--归并区间
			int j = begin1;
			if (end1 >= n || begin2 >= n)//begin2或end1越界
			{
				break;
			}
			if (end2 >= n)
			{
				end2 = n - 1;
			}
			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) * (end2-i+1));//每归并两个数就拷贝回去
		}
		gap *= 2;
	}
	free(tmp);
}
  • 效果 

 

 二.计数排序

1.思想应用 

思想:计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。

操作步骤

  1. 统计相同元素出现次数
  2. 根据统计的结果将序列回收到原来的序列中 

2.(直接映射)逻辑图示 

 

 

3.优点以及局限性 

优点

  1. 效率极高
  2. 时间复杂度为O(aN+countN(有一个范围))

局限性

1.不适合分散的数据,更适合集中的数据

2.不适合浮点数、字符串、结构体数据排序,只适合整数

4.针对分散的数据进行优化 

(1)(相对映射)图示解析 

 

(2)代码实现 

void CountSort(int* a, int n)
{
	int min = a[0], max = a[0];
	for (int i = 1; i < n; i++)
	{
		if (a[i] < min)
			min = a[i];
		if (a[i] > max)
			max = a[i];
	}
	int range = max - min + 1;//相对映射开的数组大小
	int* count = (int*)calloc(range, sizeof(int));
	if (count == NULL)
	{
		printf("calloc fail\n");
		return;
	}
	//统计次数
	for (int i = 0; i < n; i++)
	{
		count[a[i] - min]++;
	}
	//排序
	int i = 0;
	for (int j = 0; j < range; j++)
	{
		while (count[j]--)
		{
			a[i++] = j + min;//把相对映射还原回去
		}
	}
}
  • 结果 

 

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

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

相关文章

Springboot响应数据详解

功能接口 Controller下每一个暴露在外的方法都是一个功能接口 功能接口的请求路径是RequestMapping定义的路径&#xff0c;浏览器需要请求该功能则需要发出该路径下的请求。 RestController RestControllerControllerResponseBody(响应数据的注解) ResponseBody 类型&#…

找不到d3dcompiler 43.dll如何解决,5个方法轻松解决d3dcompiler 43.dll问题

计算机系统中d3dcompiler_43.dll文件的丢失可能会引发一系列显著的问题&#xff0c;这一动态链接库文件在Windows操作系统中扮演着至关重要的角色。它主要与Direct3D图形API相关&#xff0c;对于支持和运行使用Direct3D技术开发的各种应用程序和游戏至关重要。 一旦d3dcompiler…

RabbitMQ-如何保证消息不丢失

RabbitMQ常用于 异步发送&#xff0c;mysql&#xff0c;redis&#xff0c;es之间的数据同步 &#xff0c;分布式事务&#xff0c;削峰填谷等..... 在微服务中&#xff0c;rabbitmq是我们经常用到的消息中间件。它能够异步的在各个业务之中进行消息的接受和发送&#xff0c;那么…

sqli.labs靶场(第18~22关)

18、第十八关 经过测试发现User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0加引号报错 这里我们闭合一下试试 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0,127.0.0.1,adm…

【爬坑】临时修复To connect to xxx insecurely, use `--no-check-certificate‘报错

解决方案&#xff1a;wget请求时跳过证书验证。 sudo vim /etc/wgetrc 插入一行&#xff1a; check_certificate off 重新运行wget命令即可。

STM32-电动车报警器

STM32-电动车报警器 1.振动传感器点亮LED灯 需求:当振动传感器接收到振动信号时&#xff0c;使用中断方式点亮LED1 //重写中断服务函数&#xff0c;如果检测到EXTI中断请求&#xff0c;则进入此函数 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {//一根中断线上接有多个…

RHCE练习3

1.基于域名www.openlab.com可以访问网站内容为 welcome to openlab 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于www.openlab.com/student 网站访问学生信息&#xff0c;www.openlab.com/data网站访问教学资料www.openlab.com/mo…

Unity Editor 获取Screen.width, Screen.height 与Game视图对不上问题

之前在项目中写测试代码时 获取Screen.width 发现的跟game视图不一致 最后发现 通过在其他面板去触发函数 获取Screen.width 拿到的是其他面板的大小 而不是Game视图的大小

SpringCloud-高级篇(十八)

前面我们已经实现了多级缓存架构&#xff0c;大大提高了查询商品的性能&#xff0c;缓存在提高性能的同时&#xff0c;也带来了一致性的问题&#xff0c;比如说数据库发生了修改&#xff0c;这个时候&#xff0c;如果缓存依然是旧的数据&#xff0c;两者就产生了不一致&#xf…

任务修复实例(1)

实例1 任务名&#xff1a;增强防御&#xff08;quest_template.id 8490&#xff09; 涉及的两个数据表分别为 smart_script 和 creature_summon_groups smart_script Reactstate 取值参考源码 UnitDefines.h 的 ReactStates 定义&#xff0c;其中&#xff1a;0为被动&#…

【React教程】(3) React之表单、组件、事件处理详细代码示例

目录 事件处理示例1示例2示例3&#xff08;this 绑定问题&#xff09;示例4&#xff08;传递参数&#xff09;Class 和 Style 表单处理组件组件规则注意事项函数式组件&#xff08;无状态&#xff09;类方式组件&#xff08;有状态&#xff09;组件传值 Propsthis.props.childr…

【劳德巴赫 Trace32 高阶系列 1 -- svf 文件介绍】

文章目录 SVF 文件概述SVF文件的格式以及头Trace32 如何识别和使用SVF文件如何使用SVF文件SVF 命令支持总结小结总结SVF 文件概述 SVF 文件是一种ASCII文本文件,用于描述JTAG(Joint Test Action Group)测试动作的串行向量。这些文件包含了对JTAG TAP(Test Access Port)的…

寒假思维训练计划day16 A. Did We Get Everything Covered?

今天更新一道1月27号晚上div2的C题作为素材&#xff0c;感觉用到了我的构造题总结模型&#xff0c;我总结了一系列的模型和例题。 摘要&#xff1a; Part1 定义"边界贪心法" Part2 题意 Part3 题解 Part4 代码 Part5 思维构造题模型和例题 Part1 边界贪心…

生产解决方案:实现上传图片至主机文件夹下

1 需求&#xff1a; 目前需要实现&#xff0c;上传图片时候&#xff0c;自动根据图片上传地址&#xff0c;创建对应文件夹&#xff0c;例如&#xff1a;上传文件地址为&#xff0c;/2024/1/29/楼层1/1713.jpg&#xff0c;则存储结构应如下图所示。

[杂项:AD画板]B站_01

一、PCBA 1、快捷方式 CTRL鼠标滚轮&#xff1a;缩放界面 鼠标右键&#xff1a;拖拽界面 SHIFT鼠标滚轮&#xff1a;左右移动界面 CAPSLK鼠标滚轮&#xff1a;上下移动界面 CTRL鼠标左键&#xff1a;高亮选中接线网络 【】&#xff1a;调节高亮亮度&#xff0c;需要处于…

Sqli靶场 11--->22Less

打靶场&#xff0c;打靶场&#xff0c;打靶场&#xff0c;打靶场......靶场你别打我 球球 11.不用密码&#xff08;狂喜) 这一关知不知道账号密码都无所谓 那么我们就尝试一下报错类型&#xff0c;单引号报错&#xff0c;好&#xff0c;字符型 构造poc I_don_t_know_t…

C++ 之LeetCode刷题记录(二十二)

&#x1f604;&#x1f60a;&#x1f606;&#x1f603;&#x1f604;&#x1f60a;&#x1f606;&#x1f603; 开始cpp刷题之旅。 目标&#xff1a;执行用时击败90%以上使用 C 的用户。 112. 路径总和 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该…

[PHP]严格类型

PHP: 类型声明 - Manual

数字身份保护:Web3如何改变个人隐私观念​

随着Web3时代的来临&#xff0c;数字身份保护成为人们关注的焦点之一。Web3技术的引入不仅为个人隐私带来了新的挑战&#xff0c;同时也为我们重新思考和改变个人隐私观念提供了契机。本文将深入探讨Web3如何改变个人隐私观念&#xff0c;以及在数字身份保护方面的创新举措。 1…