归并排序(一)——递归排序

本文深入解析归并排序的原理,通过分解和合并数组实例,演示了其如何通过递归方式实现O(N*logN)的时间复杂度。从单层排序到递归排序代码,以及时间复杂度分析,适合理解排序算法的进阶学习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

归并的思想和前面说的快排比较类似,

 

快排是先通过单趟排序,产生一个分界点,然后分界点的两侧重新开始单趟排序

归并是直接将以数组的中心位置作为分界点,不断取中间位置,分成两个小区间,直到无法分解

核心思路:先分解左半部分,然后排序

                  再分解右半部分,然后排序

一、算法基本思路

1、先分解

将数组分解至无法继续往下分解,如下

2、再排序

排序时,从最底层开始排序

(1)9 可以看作一个数组arr1 ,3  可以看作一个数组arr2  

(2)3比9小,3先放入临时数组,由于arr2数组结束了,所以直接把9放到临时数组的末尾

    

(3)然后把tmp数组的值去替换 原数组中对应位置的值

​​​​​​​           ​​​​​​​

   3、整体过程

上面的数组更新过程可能有点抽象

先调整 9  3(倒数第一层)——会变成3 9

               

                 ​​​​​​​                                            

            

 后续过程

后续是按照红色、蓝色、橙色的区间排序,左边就排序结束了

然后再对右边开始排序,同样也是从底层向上排序

二、递归排序代码实现

1、单层排序

void SingleLevelSort(int* a,int left,int right)
{
    //第一个区间的起始位置
    int begin1 = left, end1 = mid;
    //第二个区间的起始位置
	int begin2 = mid + 1, end2 = right;
	//tmp 用于临时存放排列好的数据
	int size = right - left + 1;
	int* tmp = new int[size];

	int p = 0;
	while (begin1 <= end1 && begin2 <= end2)
	{
        //begin2小,则begin2放入临时数组,begin2向后移动一位
		if (a[begin1]>a[begin2])
		{
			tmp[p++] = a[begin2++];
		}
		else
		{
			tmp[p++] = a[begin1++];
		}
	}

	//将还有剩余的区间,拼接到tmp的后面
	while (begin1 <= end1)
	{
		tmp[p++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[p++] = a[begin2++];
	}

	//当前区间的排序结束,将tmp中的数据更新到原数组
	for (size_t i = 0; i < size; i++)
	{
        //注意 a 存放数据的范围是 [left,right]
        // tmp存放数据的范围是  [0,size-1]
		a[left+i] = tmp[i];
	}

	delete[] tmp;
	tmp = nullptr;
}

2、递归排序

void MergeSort(int* a,int left,int right) {
    //到达底端的只剩一个数的时候,无法分解,返回上一级
	if (left>=right)
	{
		return;
	}

    //取排序的中间位置,分成两个小区间
	int mid = (left + right) / 2;
	//左区间,向左分解
	MergeSort(a, left, mid);
	//右区间,向右分解
	MergeSort(a, mid + 1, right);

    //只有分解到达底端的时候,才会开始调用这个函数,然后一步步向上排序
    SingleLevelSort(a,left,right);
}

三、代码测试

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

	for (size_t i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	return 0;
}

 

四、时间复杂度

从第二部分的向下分解可以看出,逻辑结构类似于二叉树

====》时间复杂度:O(N*log N)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值