c++ 归并排序

news/2024/7/7 21:31:22

归并排序算法时间复杂度较为稳定,一般为nlogn,而快速排序受源数组排序影响较大,今天来学习归并排序。

一.归并排序代码

首先上代码:可以直接运行

#include<bits/stdc++.h>
using namespace std;

void insertsort(vector<int>&nums, int left,int mid, int right)
{
	if (nums[mid] <= nums[mid + 1])
		return;
	for (int i = left+1; i <= right; ++i)
	{
		int idx = i;
		while (idx > left && nums[idx] < nums[idx - 1])
		{
			swap(nums[idx], nums[idx-1]);
			--idx;
		}			
	}
}

vector<int>temp;
void merge(vector<int>&nums,int left,int mid,int right)
{
	if (nums[mid] <= nums[mid + 1])
		return;

	for (int i = left; i <= right; ++i)
		temp[i] = nums[i];
	int x = left, y = mid + 1;
	for (int i = left; i <= right; ++i)
	{
		if (y > right|| (y<=right&&x<=mid&&temp[x] <= temp[y]))
		{
			nums[i] = temp[x];
			++x;
		}			
		else if (x>mid||(x<=mid&&temp[x]>temp[y]))//条件可省略
		{
			nums[i] = temp[y];
			++y;
		}			
	}
}


void mergesort(vector<int>&nums,int left,int right)
{
	if (left >=right) return;
	int mid = left + (right - left)/2;
	mergesort(nums, left, mid);
	mergesort(nums, mid + 1, right);
	if (mid - left + 1 <= 10)
		insertsort(nums, left, mid, right);
	else
		merge(nums, left, mid, right);
}


int main()
{
	vector<int>nums = { 2,1,4,6,5,88,99,0,999};
	int n = nums.size();
	temp.resize(n);
	mergesort(nums,0,n-1);
	for (auto &num : nums)
		cout << num << endl;
	return 0;
}

二.代码详解

1.主函数

主函数较为简单,就是定义数组,然后调用mergesort函数,最后打印输出。

值得注意的是在主函数中我们将一个temp数组定义了大小,这个数组是辅助数组,在详细的有序合并的操作中用得到,因为我们需要好多次的合并,每次合并后的数组都不一样。

2.mergesort函数

这个函数就是一个递归函数,不断地去分割,直到分割到最后只有一个元素时,它会退出分割操作,然后这个元素会和分割出的另一半元素进行合并操作,合并完成跳到上一级继续合并。

3.merge合并函数

在合并函数中,首先如果左右两个已经是有序的,则不需要合并,直接返回。

然后我们将要合并的left到right之间的元素拷贝到temp辅助数组中,

因为原来左右两边就是有序的,所以我们只关注左右两边的起始索引,将较小的那个放进nums[i]中,

特别要注意的是元素过界问题,因为只是归并操作,索引并不会突破数组上限,从而造成结果不正确而很难发现出问题。

如果说y右侧索引超出了限定right,我们将temp[x]赋值给nums[i],此时x不会出上限。

或者说y没出索引,x也没出索引,那么当temp[x]<temp[y]时,我们也将temp[x]赋值给nums[i].

其余情况均是temp[y]赋值给nums[i]。

4.插入排序insertsort 

当right-left特别小的时候,我们可以直接使用插入排序,想象一下我们只有两个元素[2,1],

插入排序只需要swap两个值即可,而不需要赋值给赋值数组。

插入排序的思想是前面的数组元素是有序的,那么我遍历到第idx个元素时,我要把它插入到前面的合适位置,特别地如果这个值比较大,那么它不用动,

如果它比较小,那么让他和idx-1的数进行不断交换,直到遇到合适的位置。 


http://lihuaxi.xjx100.cn/news/1561258.html

相关文章

堆和树的区别

“堆” 这个术语在计算机科学中指的是一种特定类型的数据结构&#xff0c;它满足一些特定的性质&#xff0c;主要用于实现优先队列和相关算法。虽然堆通常以树的形式呈现&#xff0c;但它们与通常的树结构有一些重要的区别&#xff0c;因此被单独命名为 “堆” 而不是 “树”。…

ruoyi-nbcio移植过程中的一些问题记录

1、打包去掉测试出现 Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.2:test 错误 在pom.xml里增加下面 去掉测试 <!--添加配置跳过测试--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId…

MySQL数据库入门到精通1--基础篇(MySQL概述,SQL)

1. MySQL概述 1.1 数据库相关概念 目前主流的关系型数据库管理系统&#xff1a; Oracle&#xff1a;大型的收费数据库&#xff0c;Oracle公司产品&#xff0c;价格昂贵。 MySQL&#xff1a;开源免费的中小型数据库&#xff0c;后来Sun公司收购了MySQL&#xff0c;而Oracle又收…

Android 匿名共享内存的使用

注&#xff1a;本文内容转载自如下文章&#xff1a;Android 匿名共享内存的使用 Android View 的绘制是如何把数据传递给 SurfaceFlinger 的呢&#xff1f; 跨进程通信时&#xff0c;数据量大于1MB要怎么传递呢&#xff1f;用 匿名共享内存&#xff08;Ashmem&#xff09; 是个…

uniapp开发h5,解决项目启动时,Network: unavailable问题

网上搜了很多&#xff0c;发现都说是要禁用掉电脑多余的网卡&#xff0c;这方法我试了没有好&#xff0c;不晓得为啥子&#xff0c;之后在网上看&#xff0c;uniapp的devServer vue2的话对标的就是webpack4的devserver&#xff08;除了复杂的函数配置项&#xff09;&#xff0c…

day37 代码回想录 单调递增的数字监控二叉树

大纲 ● 738.单调递增的数字 ● 968.监控二叉树 738.单调递增的数字 题目&#xff1a;738.单调递增的数字 // 最大递增数 // 从后向前&#xff0c;找到第一个满足是每位递增的数字 // 怎么判断是否是递增值// 但是超时了 bool isIncreaseVal(int val) {// to stringauto st…

【python】anaconda使用指南

安装anaconda 访问官方 官网链接注册并登陆安装 无脑下一步即可配置path D:\ProgramData\anaconda3D:\ProgramData\anaconda3\ScriptsD:\ProgramData\anaconda3\Library\binD:\ProgramData\anaconda3\Library\mingw-w64\bin 进入anaconda环境 # 查询版本 conda --version# …

软考之软件设计师考试总结(内附资料)

今年5月27日参加的软考&#xff0c;虽然研究生专业已经和计算机无缘了&#xff0c;但是只要想学&#xff0c;就没有什么能够阻挡。 参加软考的初衷只是因为&#xff0c;&#xff0c;&#xff0c;辽宁省软考它不要钱&#xff0c;不要钱的证书咱不白嫖一个说不过去&#xff0c;先…