归并排序详解(C++实现)

学习视频:acwing算法基础课

目录

归并排序步骤:

代码实现

部分调试演示


基本思想:分治

归并排序步骤:

1.确定分界点mid=(l+r)/2 : 数组将数组要排序的 l到r的部分分为 l到(l+r)/2 和 (l+r)/2+1到r 两组

2.递归排序left部分,right部分

3.归并:把两个有序的数组合为一个有序的数组

        实现方法:假设两个有序数组为a[ ],b[ ],用一个新数组temp[ ]来记录答案

                 此时数组a,b已经排好序,所以i,j指针指向的数为数组a,b中最小的数。比较a[i],b[j],选其中较小的值放入temp数组,若相等则可任选一个放入。这里假设a[i]较小,则将a[i]的值放入temp数组,i右移一位

                 再次比较a[i],b[j],将较小的值放入temp数组,并让此指针后移一位,循环比较,直到有一指针到终点

                 假设i指针先到达终点,跳出循环,再将b数组j指针所指及之后的部分放到temp数组里

 

                                            a[i]<b[j],所以a[i]放入temp,i指针后移一位

                                                 b[j]<a[i],b[j]放入temp,j指针后移一位

                                                  b[j]<a[i],b[j]放入temp,j指针后移一位

    b[j]=a[i],这里设相等时将a数组中的数放入temp数组,所以a[i]放入temp数组,i指针后移一位

 

                                                   b[j]<a[i],b[j]放入temp,j指针后移一位

      b[j]=a[i],a[i]放入temp数组(这里设相等时将a数组中的数放入temp数组),i指针后移一位

                                                    b[j]<a[i],b[j]放入temp,j指针后移一位

                                             a[i]<b[j],所以a[i]放入temp,i指针后移一位

     a[i]<b[j],所以a[i]放入temp,i指针后移一位,但是i指针已经指到a数组末尾无法后移,跳出循环

 此时a指针已经遍历完毕,应将b数组从j指针开始遍历,将j指针及之后的所有数放入temp数组;从j指针开始的所有数只有一个12,所以将12放入temp,最后temp为2  3  5  6  6  8  8  9  10  12

代码实现

#include<iostream>
using namespace std;

const int N = 100005;//数组最大存储量
int q[N], temp[N], n;//q为待排序数组  temp为暂时保存答案的数组  n为待输入数组个数

//归并排序
void merge_sort(int l, int r)//l和r为待排序区间的两端
{
	if (l == r) return;//当l与r重合时返回(此时数组只有一个数字)
	int mid = (l + r) / 2;//求mid
	merge_sort(l, mid);//排序l到mid
	merge_sort(mid + 1, r);//排序mid+1到r

	int i = l, j = mid + 1, t = 0;
	while (i <= mid && j <= r)//将待排序区间分为两个区间l到mid和mid+1到r
	{
		//谁小就将谁放入temp
		if (q[i] < q[j]) temp[t++] = q[i++];
		else temp[t++] = q[j++];
	}
	
	//哪个数组没遍历完就遍历哪个数组
	while (i <= mid) temp[t++] = q[i++];
	while (j <= r) temp[t++] = q[j++];

	//将排完序的数组放回原数组
	for (int i = l, t = 0; i <= r; i++, t++)
	{
		q[i] = temp[t];
	}
}

int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> q[i];
	}

	merge_sort(0, n - 1);

	for (int i = 0; i < n; i++)
	{
		cout << q[i] << " ";
	}

	return 0;
}

部分调试演示

 输入n  及数组元素


 断点放在merge_sort()调用这一句,merge_sort函数调用,传入参数merge_sort(0,6)


 进入merge_sort函数(为了方便以下简称ms函数)并继续运行到ms函数再次调用之前

此时l=0,r=6,mid=3

 


 调用ms(0,3)并继续运行到ms函数再次调用之前

此时l=0,r=3,mid=1

 


 调用ms(0,1)并继续运行到ms函数再次调用之前

此时l=0,r=1,mid=0

 


调用ms(0,0) 此时l=0,r=0,l==r    所以返回

 


 

 调用ms(1,1) 此时l=1,r=1,l==r    所以返回

 


 继续向下运行,此时l=0,r=1,mid=0;令i=l=0,r=mid=1

将区间0到1分为了 区间left:下标0 和 区间right:下标1

进入while循环比大小


 q[i]:q[0]=6       q[j]:q[1]=8      q[i]<q[j]  所以temp[t]:temp[0]=6

 i++后i=1,i>mid  所以跳出while循环

此时区间right还没遍历

所以遍历区间right

temp[1]=q[1]=8

 跳出while循环

 


 通过for循环将temp数组的数放回原数组

放回原数组后函数结束 返回上一级调用

 


 调用ms(2,3) 

 

接下来就是重复的过程 就不一一列举啦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值