归并排序-排序算法

前言

如果一个数组的左右区间都有序,我们可以使用一种方法(归并),使这个数组变得有序。

如下图:

过程也很简单,分别取左右区间中的最小元素,再把其中较小的元素放到临时数组中,例如第一次1和2被取出,1 被放到临时数组;第二次3和2被取出,2 被放到临时数组。重复此操作就能得到有序的临时数组,最后把临时数组拷贝到原数组中就好了。

这就是归并的思想,目前先依照上面过程写出归并方法的代码。注意不是归并排序的代码

#include <iostream>
using namespace std;

void mergeAdd0(int arr[], int left, int right,int *temp) //函数参数传入临时数组
{
	int mid = (left + right) / 2 ; //区间的中间位置,[left,mid]为左区间,[mid+1,right]为右区间
	int i = left;		//指向左区间最小元素的位置
	int j = mid + 1 ;	//指向右区间最小元素的位置
	int k = 0;			//临时数组的下标

	while (i <= mid && j <= right) //这个循环是取出元素的过程
	{
		if (arr[i] < arr[j])
		{
			temp[k++] = arr[i++];
		}
		else
		{
			temp[k++] = arr[j++];
		}
	}
    
    //因为有一个区间的元素必定会先被取完,下面两个循环是将另一个区间的元素拿到临时数组
	while (i <= mid)
	{
		temp[k++] = arr[i++];
	}

	while (j <= right)
	{
		temp[k++] = arr[j++];
	}

	//将temp数组拷贝到原数组
	memcpy(arr + left, temp, sizeof(int) * (right - left + 1 ));

}
int main(void)
{
	int arr[] = { 1 , 3, 5 ,7 ,2 ,4 ,6 ,8 };
	int len = sizeof(arr) / sizeof(arr[0]);

	int* temp = new int[len]; //和原数组大小一样的临时数组
	mergeAdd0(arr, 0, len - 1,temp);

	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << " ";
	}
	return 0;
}

看完了归并方法,有些人会问,你这个归并方法并不能适用于一般情况,一般数组都是无序的,哪里是你那样的数组:左半边有序,右半边也有序。

也是,下面请先看看归并排序的过程吧(也就是处理一般情况)。

具体步骤

接下来讲的就是排序本身的具体步骤了,对于下面待排序的数组

------170 189 187 186 169 173 162 170 168------

先以中间为界,均分为A、B两组(如果是奇数个,允许两组的个数相差一个)

A------170 189 187 186 169------

B------173 162 170 168------

如果A、B两组数据有序的话,那么就可以通过上面的归并方法让数组有序,可是此时两个数组都无序,此时可以使用分治法继续对A、B两组进行均分,以B组为例,可以分为B1、B2组如下:

B1------173 162------

B2------170 168------

均分后依旧无序,继续利用分治法细分,以B1组为例,可分为如下两组

B11------173------

B12------162------

数组细分到一个元素后,这时候就可以使用之前的归并法借助一个临时数组将B1组有序化!B2数组同理。

B1------162 173------

B2------168 170------

依次类推,B1、B2组有序后,可归并成有序的B组,A组同理。

A------169 170 186 187 189------

B------162 168 170 173------

最后将A、B两组通过归并法合并得到了有序的数组。

------162 168 169 170 170 173 186 187 189------

思路

上面这个过程,按我的理解是:首先归并方法可以使一个左区间有序、右区间有序的数组有序,那左区间怎么有序呢?

恭喜你,学会抢答了。那就是左区间的左区间有序并且左区间的右区间有序(使用归并方法),右区间同理。那左区间的左区间如何有序呢?......直到细分到区间内只有一个元素时,可以保证这个区间有序,从而得到一个个有序区间,最终使数组有序。

这个过程正如排序的名称归并,先递归,使大问题变成小问题,再合并,依次解决问题。

就如上过程结合归并方法可以得到以下代码:

//归并排序
void mergeSort(int arr[], int left, int right, int* temp)
{
	if (left < right) //区间大于1个数,就要分而治之
	{
		int mid = (left + right) / 2;
		mergeSort(arr, left, mid, temp);  
		mergeSort(arr, mid+1, right, temp);  
		mergeAdd(arr, left, right, temp); 
	}
}

归并排序时间复杂度: n

全部代码以及测试图

#include <iostream>
#include <time.h>
using namespace std;

//归并方法
void mergeAdd(int arr[], int left, int right,int *temp)
{
	int mid = (left + right) / 2 ; //区间的中间位置,[left,mid]为左区间,[mid+1,right]为右区间
	int i = left;		//指向左区间最小元素的位置
	int j = mid + 1 ;	//指向右区间最小元素的位置
	int k = 0;			//临时数组的下标

	while (i <= mid && j <= right)
	{
		if (arr[i] < arr[j])
		{
			temp[k++] = arr[i++];
		}
		else
		{
			temp[k++] = arr[j++];
		}
	}

	while (i <= mid)
	{
		temp[k++] = arr[i++];
	}

	while (j <= right)
	{
		temp[k++] = arr[j++];
	}

	//将temp数组拷贝到原数组
	memcpy(arr + left, temp, sizeof(int) * (right - left + 1 ));

}

//归并排序
void mergeSort(int arr[], int left, int right, int* temp)
{
	if (left < right) //区间大于1个数,就要分而治之
	{
		int mid = (left + right) / 2;
		mergeSort(arr, left, mid, temp);  
		mergeSort(arr, mid+1, right, temp);  
		mergeAdd(arr, left, right, temp); 
	}
}
int main(void)
{
	int arr[] = { 170 ,189,187 ,186 ,169 ,173 ,162 ,170 ,168 };
	int len = sizeof(arr) / sizeof(arr[0]);

	int* temp = new int[len]; //和原数组大小一样的临时数组
	
	mergeSort(arr, 0, len - 1, temp);
	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << " ";
	}
	
	return 0;
}
相关推荐
A懿轩A5 分钟前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
古希腊掌管学习的神5 分钟前
[搜广推]王树森推荐系统——矩阵补充&最近邻查找
python·算法·机器学习·矩阵
云边有个稻草人9 分钟前
【优选算法】—复写零(双指针算法)
笔记·算法·双指针算法
半盏茶香10 分钟前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
忘梓.1 小时前
解锁动态规划的奥秘:从零到精通的创新思维解析(3)
算法·动态规划
️南城丶北离1 小时前
[数据结构]图——C++描述
数据结构··最小生成树·最短路径·aov网络·aoe网络
✿ ༺ ོIT技术༻1 小时前
C++11:新特性&右值引用&移动语义
linux·数据结构·c++
tinker在coding3 小时前
Coding Caprice - Linked-List 1
算法·leetcode
XH华8 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生8 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论