【算法】——归并排序的解析

2023-11-10

目录

1.归并排序的思想

 2.归并排序的分析

3.内排序和外排序


1.归并排序的思想

归并是将两个或两个以上的有序表组合成一个新的有序表,假设初始序列含有n个记录,则可看成是n个子序列,每个子序列的长度为1,然后两两归并,得到[ n/2 ]个长度为2或为1的有序的子序列;在两两归并... ... ,如此重复,直到得到一个长度为n的有序序列为止。如下:

 2.归并排序的分析

我们先来对两个序列合成新的有序序列进行分析;我们以上面的第三趟排序作为例子

 这就完成了两个序列合并的算法,代码如下。

void _MergeSortNonR(int* a,int* tmp,int begin1,int end1, int begin2, int end2)
{
	int cur1 = begin1;//cur1是子序列1的指针指向位置
	int cur2 = begin2;//cur2是子序列2的指针指向位置
	int cur3 = begin1;//临时数组指向的位置
	//将子序列1和子序列2进行比较,然后将较小的值
	//插入到临时数组中
	while (cur1 <= end1 && cur2 <= end2)
	{
		if (a[cur1] < a[cur2])
		{
			tmp[cur3] = a[cur1];
			cur1++;
		}
		else
		{
			tmp[cur3] = a[cur2];
			cur2++;
		}
		cur3++;
	}
	
	//将剩下的子序列的值插入到
	//临时数组中
	while (cur1 <= end1)
	{
		tmp[cur3++] = a[cur1++];
	}

	while (cur2 <= end2)
	{
		tmp[cur3++] = a[cur2++];
	}

	//将临时数组中的数组拷贝给原来的数组
	for (int i = begin1; i <= end2; i++)
	{
		a[i] = tmp[i];
	}
}

其中a是为原数组,tmp是临时数组。begin1和end1为序列1的区间,begin2和end2为序列2的区间。

当然完成两个序列合并只是其中的一部分,要完成归并排序的算法,我们还要继续往下分析:

 起初begin1为指向4的位置为0,则endl为begin1+gap-1,begin2为begin1+gap,end2为begin1+2gap-1,其中gap为子序列的间隔,此时的gap为2.

当上面的子序列排完序后,则跳到下一组序列进行排序。则begin1为指向1的位置,其中的begin1由上一个being1+=2gap跳过来的。如果按照上面计算的话,我们在每一趟中的后面需要在判断end2和end1,如果end2大于n-1时,则表示end2比数组最后一个数据的地址要大,所以令end2等于n,如果end1大于n-1时,则表示end1比数组最后一个数据的地址要大,这时候最后一个就只有一个子序列,所以不用在比较了,直接跳出循环循环即可.

当每趟归并排序完成最后一组排序时,则begin1>n,则代表这一趟的归并排序结束,再将gap乘以2倍,进行下一趟的归并排序,当最后一趟排序结束时,其中的gap>=n/2,所以当gap>n时就完成排序.        

void MergeSort(int* a, int n)
{
	//创建一个临时数组
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		printf("malloc申请失败\n");
		exit();
	}

	int gap = 1;//第一趟排序的gap为1
	while ( gap <= n)
	{
		//设i为每两个序列中begin1的值
		for (int i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			//end2大于n-1,则end2改为n-1
			if (n-1 < end2)
			{
				end2 =n-1;
			}
			//如果end1大于n-1,则这一趟就不需要在排序了
			if (n-1 < end1)
			{	
				break;
			}
		  //两个序列合成为一个新的序列
			_MergeSortNonR(a, tmp, begin1, end1, begin2, end2);

		}
		gap *= 2;
	}
    //释放临时数组
	free(tmp);
	tmp = NULL;
}

归并排序的时间复杂度:每一趟归并排序都得遍历一次数组,时间复杂度为O(n),从第一趟都到最后一趟的归并排序总共要进行log2n趟排序,所以归并排序的时间复杂度为O(nlogn).

归并排序的空间复杂度:归并排序需要创建与原来序列一样的临时序列,所以归并排序的空间复杂度为O(N).

3.内排序和外排序

内排序:数据数量少,内存中放的下,直接在内存中排序即可,

外排序:数据数量多,内存放不下,数据都放在磁盘中,但不能直接通过内存对它们排序,得在内存中进行一部分排序后,然后在磁盘中完成排序。

外排序的思想:

假设文件A中有5个亿的整数,要对它们进行排序,需要进行怎样排序呢?

(5个亿的整数大约为2个g,内存大概有512个g)

显然这文件A中的数据不能直接放到内存中进行排序,所以就得要使用外排序来对我们的数据进行排序。

 好啦,今天的内容就分享到这里了,如果你觉得这篇文章对你有帮助的话,麻烦你给个三连,谢谢!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【算法】——归并排序的解析 的相关文章

随机推荐

  • 数据库系统原理实验(实习)报告——单表查询

    一 实验目的 1 掌握select语句的基本语法和查询条件表示方法 2 掌握数据汇总方法 3 掌握group by子句的作用和使用方法 4 掌握having子句的作用和使用方法 5 掌握order by子句的作用和使用方法 二 实验内容与步
  • 数据结构三大算法(案例解析)

    概述 本文讲述数据结构中最常用到的三大算法 分治法 动态规划法和贪心算法 主要从这些算法的经典案例入手来对算法进行分析和理解 分治法 分治法可以通俗的理解为将一条大鱼分成好几块 分别料理每一块鱼肉 然后再组成一道菜 也就是说分治法是将一个大
  • Cadence17.2 > OrCAD Capture CIS > 设计规则检查(Design Rule Check)DRC学习记录详解

    目录 一 Design Rule Check对话框选项详解 1 Design Rule Options选项详解 2 Electrical Rules 电气规则检查 选项详解 3 Physical Rules 物理规则检查 选项详解 4 ER
  • 并发编程中需要谨记的规则(翻)

    并发编程中需要谨记的规则 最小化临界区 Amdahl定律和Gustafson定律都将并行算法中的顺序执行的工作视为性能问题的头号敌人 两个执行代码区段中间的时间需要顺序执行 这就是众所周知的临界值 在图1 16的分析Gustafson定律的
  • [资源]--IOS捷径大全,众多实用小功能

    一 实用工具 1 支付助手3 0 新 扫一扫 微信扫码 微信收款 支付宝扫码 Apple Pay AA付款 查快递 蚂蚁森林 蚂蚁庄园 彩票 股票 运动 淘票票 乘车码 生活缴费 火车票等等 https www icloud com sho
  • 剑指offer 面试题14- I. 剪绳子 面试题14- II. 剪绳子 II

    动态规划 https leetcode cn com problems integer break solution dong tai gui hua zhi xing yong shi da bai 100 c by 动态规划 class
  • Open3D (C++) 计算点云的均值与标准差

    目录 一 算法原理 二 主要函数 三 代码实现 四 结果展示 一 算法原理 计算给定点云数据x y z坐标各字段的均值和标准差 其中标准差为n 1实现 二 主要函数 getMeanStd const std vector lt float
  • 基于Java的连连看游戏设计与实现(含源文件)

    欢迎添加微信互相交流学习哦 项目源码 https gitee com oklongmm biye 毕业设计 论文 任务书 第1页 毕业设计 论文 题目 基于Java的连连看游戏设计与实现 毕业设计 论文 要求及原始数据 资料 1 简述Jav
  • 拥塞控制域流量控制

    流量控制 也就是管理两端的流量 以免任一方向上因发送过块导致接收端溢出 或者因接收端处理太快而浪费时间的状态 具体包括 1 发送端的进程产生数据很慢 时不时的来个1字节数据 那么TCP就会1字节1字节的发送 效率很低 解决办法是建立一个时基
  • 冗余架构控制器下的攻与防

    本文系原创 转载请说明出处 Please Subscribe Wechat Official Account 信安科研人 获取更多的原创安全资讯 防 A Quad Redundant PLC Architecture for Cyber R
  • Deformable Attention学习笔记

    Deformable Attention学习笔记 Vision Transformer with Deformable Attention Abstract Transformer 最近在各种视觉任务中表现出卓越的表现 大的 有时甚至是全局
  • 《MySQL必知必会》01_书中例程:所有的创表语句、插入语句

    目录 书中例程 所有的创表语句 插入语句 create sql populate sql 书中例程 所有的创表语句 插入语句 create sql MySQL Crash Course http www forta com books 06
  • jmeter压测步骤

    参考 使用Jmeter压测的第一个接口 第一步 在测试计划里添加一个线程组 要压测的接口名称 如图所示 在测试计划里右键 添加 线程 线程组就可以了 第二步 设置线程组参数 如下图所示 第三步 添加请求 在线程组上右键 添加 取样器 HTT
  • 服务器virsh不显示虚机,【openEuler 20.09】【虚拟化】virsh attach-interface热插rtl8139网卡后,虚拟机内部不显示,重启后才显示...

    环境信息 Host NAME openEuler VERSION 20 09 ID openEuler VERSION ID 20 09 PRETTY NAME openEuler 20 09 ANSI COLOR 0 31 Guest C
  • Python函数(def, return)

    函数 函数 Function 喂 给函数一些数据 它就能内部消化 给你 吐 出你想要的东西 这就像自动贩卖机 只不过贩卖机是喂点钱 吐出来一些吃的喝的用的东西 而Python函数则是喂各种各样的数据 吐出来各种各样的功能 函数定义 在Pyt
  • c#对字符串的各种操作

    1 字符串定义 2 在字符串后面追加字符串 3 获取字符串长度 4 截取字符串的一部分 5 字符串转为比特码 6 查指定位置是否为空字符 7 查字符串是否是标点符号 8 截头去尾 Trim 9 替换字符串 10 得到用单个字符串分隔字符串单
  • MT7688路由器 openwrt编译笔记

    Openwrt 19 07 4 路由器平台 MT7688 代码下载 git clone git git openwrt org openwrt git 或者更快的下载如下 git clone https gitee com mirrors
  • Java实现数据脱敏

    一 什么是数据脱敏 数据脱敏指的是某些敏感的信息通过脱敏规则进行数据的变形 实现敏感隐私数据的可靠保护 敏感数据包括 姓名 身份证号 手机号 银行卡号等信息 防止这些敏感数据在不安全的情况下使用 所以就要使用数据脱敏的技术 使用数据脱敏会在
  • 微服务,那些你该懂的知识(服务的注册和发现)

    微服务 微服务按照我个人的理解就是将众多的功能拆分成一个个子服务 其中以现在很流行的SpringBoot框架进行开发 再以SpringCloud方式进行部署 进而可以在SpringCloud的服务平台中对SpringBoot的一个个服务进行
  • 【算法】——归并排序的解析

    目录 1 归并排序的思想 2 归并排序的分析 3 内排序和外排序 1 归并排序的思想 归并是将两个或两个以上的有序表组合成一个新的有序表 假设初始序列含有n个记录 则可看成是n个子序列 每个子序列的长度为1 然后两两归并 得到 n 2 个长