归并排序和分治

news2024/11/24 13:39:40

归并排序

归并排序是利用归并的思想实现的排序方法,该算法采用经典的分治策略(分治法将问题成一些小的问题然后递归求解,而的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。

分而治之

可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现)。

过程:左部分排好序,右部分排好序,利用merge过程让左右整体有序(merge过程:谁小拷贝谁,直到左右两部分所有的数字耗尽)

归并排序算法有两个基本的操作,一个是,也就是把原数组划分成两个子数组的过程。另一个是,它将两个有序数组合并成一个更大的有序数组。

  1. 将待排序的线性表不断地切分成若干个子表,直到每个子表只包含一个元素,这时,可以认为只包含一个元素的子表是有序表。
  2. 将子表两两合并,每合并一次,就会产生一个新的且更长的有序表,重复这一步骤,直到最后只剩下一个子表,这个子表就是排好序的线性表。

阶段

可以理解为就是递归拆分子序列的过程,利用二分法

递归深度为log2n。

合并两个有序数组流程

再来看看阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤。

代码:

# include <stdio.h>

int arr[100];
inr help[100];

int n;

void mergesort(int l, int r)
{
	if (l == r)
		return;
	
	int m = (l+r) / 2;
	mergesort(l, m);
	mergesort(m+1, r);
	merge(l, m, r); //让左右整体有序 
}

//让 l 到 r 变 有序
//把[l, m] 和 [m+1, r]进行合并 
void merge(int l, int m, int r)
{
	int i = l;
	int a = l;
	int b = m+1; 
	while (a <= m && b <=r)
	{
		if (arr[a] <= arr[b])
		{
			help[i] = arr[a];
			a = a + 1;
		}
		else
		{
			help[i] = arr[b];
			b = b + 1;
		}
		i = i + 1;
	}
	//左侧指针,右侧指针,必有一个越界,另一个不越界
	while (a <= m)
	{
		help[i] = a;
		i = i + 1;
		a = a + 1;
	} 
	while (b <= r)
	{
		help[i] = b;
		i = i + 1;
		b = b + 1;
	} 	
	for (int i=l; i<=r; ++i)
	{
		arr[i] = help[i];
	}
}

int main()
{
	scanf("%d", &n);
	for (int i=0; i<n; ++i)
		scanf("%d", &arr[i]);
		
	mergesort(0, n-1);

}

归并分治



问题一

本题发现

符合第一个原理

在计算跨越左右产生的答案时,我们发现如果左、右各有序,则会提高计算便利性

因此就可以考虑归并分治

代码:

# include <stdio.h>

int arr[100];
int help[100];

int n;

int sum(int l, int r)
{
	if (l == r)
		return 0;
	int m = (l + r) / 2;
	return sum(l, m) + sum(m+1, r) + merge(l, m, r);
}

int merge(int l, int m, int r)
{
	int ans = 0;
	int j = l;
	int sum = 0;
	for (int i=m+1; i<r; ++i)
	{
		while (j <= m && arr[i] >= arr[j])
		{
			sum = sum + arr[j];
			j = j + 1;
		}
		ans = ans + sum;
	}
	int i = l;
	int a = l;
	int b = m + 1;
	while (a <= m && b <=r)
	{
		if (arr[a] <= arr[b])
		{
			help[i] = arr[a];
			a = a + 1;
		}
		else
		{
			help[i] = arr[b];
			b = b + 1;
		}
		i = i + 1;
	}
	//左侧指针,右侧指针,必有一个越界,另一个不越界
	while (a <= m)
	{
		help[i] = a;
		i = i + 1;
		a = a + 1;
	} 
	while (b <= r)
	{
		help[i] = b;
		i = i + 1;
		b = b + 1;
	} 	
	for (int i=l; i<=r; ++i)
	{
		arr[i] = help[i];
	}
}

int main()
{
	scanf("%d", &n);
	for (int i=0; i<n; ++i)
		scanf("%d", &arr[i]);
	int ans = sum(0, n-1);
	
}

问题二

符合第一个原理

在计算跨越左右产生的答案时,我们发现如果左、右各有序,则会提高计算便利性

因此就可以考虑归并分治

代码:

# include <stdio.h>

int arr[100];
int help[100];

int n;

int cmp(int l, int r)
{
	if (l == r)
		return 0;
	int m = (l+r) / 2;
	return cmp(l, m) + cmp(m+1, r) + merge(l, m, r);
}

int merge(int l, int m, int r)
{
	int j = l;
	int q = m+1;
	int sum = 0;
	int ans = 0;
	for (int i=l; i<=m; ++i)
	{
		while (q <= r && arr[i] > arr[q] * 2)
		{
			q = q + 1;
		}
		ans = ans + (q - m - 1) - i;
	}
	int x = l;
	int a = l;
	int b = m + 1;
	while (a <= m && b <=r)
	{
		if (arr[a] <= arr[b])
		{
			help[x] = arr[a];
			a = a + 1;
		}
		else
		{
			help[x] = arr[b];
			b = b + 1;
		}
		x = x + 1;
	}
	//左侧指针,右侧指针,必有一个越界,另一个不越界
	while (a <= m)
	{
		help[x] = a;
		x = x + 1;
		a = a + 1;
	} 
	while (b <= r)
	{
		help[x] = b;
		x = x + 1;
		b = b + 1;
	} 	
	for (int i=l; i<=r; ++i)
	{
		arr[i] = help[i];
	}
	return ans;
}



int main()
{
	scanf("%d", &n);
	for (int i=0; i<n; ++i)
		scanf("%d", &arr[i]);
		
}

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

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

相关文章

前端实现菜单搜索搜索(功能模版)

目录 前言正文 前言 总体界面如下所示&#xff1a; 正文 <template><div class"avue-searchs"click.self"handleEsc"><div class"avue-searchs__title">菜单搜索</div><div class"avue-searchs__content"…

游戏运营分析:如何在新游戏上线初期实现精细化运营?

一、背景介绍 在当今的手游市场中&#xff0c;每一款新游戏的发布都如同踏上一段充满未知与挑战的探险之旅。游戏刚上线时&#xff0c;运营情况往往如同飘摇的小船&#xff0c;随时可能受到风浪的侵袭。此时&#xff0c;如何准确地找到问题所在&#xff0c;为游戏的健康运营和持…

瀚海贫者福,铜子恣意游

上学时打饭追求性价比的习惯一直不改&#xff0c;半个大鱼头三块钱&#xff0c;一份豆腐一块钱&#xff0c;还有一个红烧茄子2块5&#xff0c;再加三毛钱的饭&#xff0c;共6块8毛钱&#xff0c;早晚餐也会有这类性价比高又营养的选择&#xff0c;科大食堂现在越来越人性化&…

蓝桥杯练习——拼出一个未来

选中 index.html 右键启动 Web Server 服务&#xff08;Open with Live Server&#xff09;&#xff0c;让项目运行起来。接着&#xff0c;打开环境右侧的【Web 服务】&#xff0c;就可以在浏览器中看到如下效果&#xff1a; 目标 完善 js/index.js 的 TODO 部分&#xff0c;实…

零基础学会Python

⭐简单说两句⭐ ✨ 正在努力的小新~ &#x1f496; 超级爱分享&#xff0c;分享各种有趣干货&#xff01; &#x1f469;‍&#x1f4bb; 提供&#xff1a;模拟面试 | 简历诊断 | 独家简历模板 &#x1f308; 感谢关注&#xff0c;关注了你就是我的超级粉丝啦&#xff01; &…

C 回调函数的两种使用方法

对回调&#xff08;callback&#xff09;函数的一点粗陋理解&#xff0c;在我小时候&#xff0c;隔壁村有家月饼小作坊&#xff08;只在中秋那段时间手工制作一些月饼出售&#xff0c;后来好像不做了&#xff09;&#xff0c;做出的月饼是那种很传统很经典的款式&#xff0c;里…

电机的工作电流怎么计算?

电机的工作电流计算通常需要考虑多个因素&#xff0c;包括电机的额定功率、工作电压、效率以及负载情况等。以下是一个基本的计算方法&#xff0c;用于估算直流电机或交流电机在特定条件下的工作电流。 了解电机参数 额定功率 (P_rated) 电机的额定功率是指在额定工作条件下&am…

深入C语言:探究static关键字的奥秘

文章目录 一、链接属性二、static变量1、定义静态局部变量2、在函数内部使用静态变量3、函数中静态局部变量与递归 三、static变量与全局变量的区别1、存储期与生命周期2、可见性与作用域3、使用场景4、静态与动态内存分配 注意事项 当用于不同的上下文环境时&#xff0c; sta…

005 高并发内存池_CentralCache设计

​&#x1f308;个人主页&#xff1a;Fan_558 &#x1f525; 系列专栏&#xff1a;高并发内存池 &#x1f339;关注我&#x1f4aa;&#x1f3fb;带你学更多知识 文章目录 前言本文重点一、构建CentralCache结构二、运用慢开始反馈调节算法三、完成向CentralCache中心缓存申请四…

Netty经典32连问

文章目录 1、Netty是什么&#xff0c;它的主要特点是什么&#xff1f;2、Netty 应用场景了解么&#xff1f;3、Netty 核心组件有哪些&#xff1f;分别有什么作用&#xff1f;4、Netty的线程模型是怎样的&#xff1f;如何优化性能&#xff1f;5、EventloopGroup了解么?和 Event…

第十三届蓝桥杯大赛软件赛省赛CC++大学B组

第十三届蓝桥杯大赛软件赛省赛CC 大学 B 组 文章目录 第十三届蓝桥杯大赛软件赛省赛CC 大学 B 组1、九进制转十进制2、顺子日期3、刷题统计4、修建灌木5、x进制减法6、统计子矩阵7、积木画8、扫雷9、李白打酒加强版10、砍竹子 1、九进制转十进制 计算器计算即可。2999292。 2、…

RD55UP06-V 三菱iQ-R系列C语言功能模块

RD55UP06-V 三菱iQ-R系列C语言功能模块 RD55UP06-V用户手册&#xff0c;RD55UP06-V功能&#xff0c;RD55UP06-V系统配置 RD55UP06-V参数规格&#xff1a;10BASE-T/100BASE-TX/1000BASE-T 1通道&#xff1b;字节存储次序格式小端模式; 可使用SD存储卡插槽&#xff1b;工作RAM 1…

路由、插槽

路由 前端路由&#xff1a;Hash地址(url中#后面的部分)与组件之间的对应关系 页面效果&#xff1a;在浏览器中访问不同的Hash地址时&#xff0c;会显示不同的组件 SPA项目(单页面应用程序&#xff0c;就是Vue项目&#xff0c;最后所有模板都展示在一个html上) vue路由(vue-r…

VUE3——生命周期

Vue3.0中可以继续使用Vue2.x中的生命周期钩子&#xff0c;但有有两个被更名&#xff1a; beforeDestroy改名为 beforeUnmountdestroyed改名为 unmounted Vue3.0也提供了 Composition API 形式的生命周期钩子&#xff0c;与Vue2.x中钩子对应关系如下&#xff1a; beforeCreate&g…

3D Gaussian Splatting Linux端部署指南(含Linux可视化)

3D Gaussian Splatting Linux端部署指南 目录 项目地址 部署记录 11. Linux端在线远程可视化训练进程 准备自己的数据 SIBR_remoteGaussian在线远程可视化 补充&#xff1a;sibr_3Dgaussian离线可视化训练好的模型 朋友浩哥说环境是最难配的&#xff0c;配好环境&#x…

Tinymce富文本编辑器二次开发电子病历时解决的bug

前言 本文是在Tinymce富文本编辑器添加自定义toolbar&#xff0c;二级菜单&#xff0c;自定义表单&#xff0c;签名的基础之上进行一些bug记录&#xff0c;功能添加&#xff0c;以及模版的应用和打印 项目描述 建立电子病历模版—录入&#xff08;电子病历模版和电子病历打印…

运筹学基础(三):求解整数规划的切平面法(cutting plane method)

文章目录 算法思想一个例子参考文档 算法思想 先将整数规划问题松弛为线性规划问题&#xff0c;然后割掉线性规划问题可行域的一部分&#xff08;只包含非整数解&#xff09;&#xff0c;使得线性规划问题的最优解在原整数规划问题的可行域某顶点上取得。 因此&#xff0c;割平…

Spring之BeanFactoryPostProcessor详解

目录 功能与作用 使用案例 spring提供的常见BeanFactoryPostProcessor 1.EventListenerMethodProcessor 2.BeanDefinitionRegistryPostProcessor 功能与作用 使用案例 spring提供的唯一BeanDefinitionRegistryPostProcessor 总结 功能与作用 参考BeanFactoryPostProce…

如何插入LinK3D、CSF、BALM来直接插入各个SLAM框架中

0. 简介 LinK3D、CSF、BALM这几个都是非常方便去插入到激光SLAM框架的。这里我们会分别从多个角度来介绍如何将每个框架插入到SLAM框架中 1. LinK3D:三维LiDAR点云的线性关键点表示 LinK3D的核心思想和基于我们的LinK3D的两个LiDAR扫描的匹配结果。绿色线是有效匹配。当前关…