【数据结构】八大排序之归并排序以及完整代码

一、思想

1、基于分治策略

把大规模问题划分为小规模问题,集中起来解决小规模的问题,从而导致整体的大规模问题被解决。

2、核心

归并排序就是分和合的过程,为什么会这么说??他就是想办法在怎样的情况下让他是有序的,如果是一个数据,那我们是不是可以认为他不用排序都是有序的。
分:把数组中的数据划分成一组一组的小组,并且保证组内有序。
合:把分好的小组又进行合并,合并后的小组要保证组内有序。

3、怎样划分小组?

我们对每一个小组都去找它的中间值,也就是( right - left ) / 2 + left,其中,right 为小组的第一个元素下标,left 为小组的最后一个元素下标。
划分小组的过程又是一个递归的过程。

4、分和合的图解过程

在这里插入图片描述
结合变量我们来分析一下,如何从第二次合并到第三次合并的:
在这里插入图片描述
(1)现在有4个小组,结合第一次到第二次的划分我们发现,要将前两组合并,胡两组合并,最终合并为两个组。
(2)开辟一个数组 tmp 作为排序后结果保存的临时数组;
mid 标识拆分时的中间位置;k 标志tmp的初始位置
i 标识左小组的第一个元素位置;j 标识右小组的第一个元素位置
(3)arr[0] < arr[3],将arr[0]存入tmp[k]中,i++,k++;
(4)arr[1] < arr[3],将arr[1]存入tmp[k]中,i++,k++;
(5)arr[2] < arr[3],将arr[2]存入tmp[k]中,i++,k++;
(6)此时i++的时候第一个小组越界了,所以就将与它合并的小组直接存入tmp接下来的位置中
(7)此时在调用一个函数,进行右边两个小组的合并,而这个函数不断地对有不止一个元素的数组进行划分,所以就要用到递归。
在这里插入图片描述
(8)arr[6] < arr[9],将arr[6]存入tmp[k]中,i++,k++;
(9)arr[7] > arr[9],将arr[9]存入tmp[k]中,j++,k++;
(10)arr[7] < arr[10],将arr[7]存入tmp[k]中,i++,k++;
(11)arr[8] > arr[10],将arr[10]存入tmp[k]中,j++,k++;

5、总结

(1)如果第一个小组越界了,但是第二个小组还没有遍历完,那就直接将第二组剩余的数据存入tmp中。
(2)比较两个数据的大小,哪边数据小,取哪边数据,哪边的下标- -。
(3)start 标记每组的起始位置,end 标记每组的末尾位置,划分后,被分为[start,mid] 和 [mid+1,end]两个小组。
(4)最后将在 tmp 排好的数据直接存入原数组中。

二、代码实现

#include<stdio.h>
#include<stdlib.h>

void Merge(int arr[], int tmp[], int start,int mid, int end)//合并小组并排序
{
	int i = start;//i标识左小组的第一个元素位置
	int j = mid + 1;//j标识右小组的第一个元素位置
	int k = start;//tmp当前小组存放的起始位置
	while (i < mid + 1 && j < end + 1)//左小组越界或右小组越界才能退出
	{
		if (arr[i] <= arr[j])
		{
			/*tmp[k] = arr[i];
			k++;
			i++;*/
			tmp[k++] = arr[i++];
		}
		else
		{
			tmp[k++] = arr[j++];
		}
	}
	while (j < end + 1)//右边小组没有越界
	{
		tmp[k++] = arr[j++];
	}
	while (i < mid + 1)//左边小组没有越界
	{
		tmp[k++] = arr[i++];
	}
	for (i = start; i <= end; i++)
	{
		arr[i] = tmp[i];
	}
}
void MergeS(int arr[], int tmp[], int start, int end)//划分小组
{
	if (start < end)
	{
		int mid = (start+end)/2;
		MergeS(arr, tmp, start, mid);
		MergeS(arr, tmp, mid + 1, end);
		Merge(arr, tmp, start, mid, end);
	}
}

void MergeSort(int arr[], int len)
{
	int *tmp = (int *)malloc(sizeof(int)*len);//排序后结果保存的临时数组
	MergeS(arr, tmp, 0, len - 1);
	free(tmp);
}
int main()
{
	int arr[] = { 12, 3, 21, 32, 1, 34, 12, 35, 34 };
	int len = sizeof(arr) / sizeof(arr[0]);
	MergeSort(arr, len);
	for (int i = 0; i < len; i++)
	{
		printf("%d  ", arr[i]);
	}
	printf("\n");
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值