归并排序的代码实现

什么是归并排序

归并排序(Merge Sort) 是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。—百度百科
时间复杂度:O(n log n)
空间复杂度:O(n)

实现的过程

先将元素划分到单个,之后在进行排序
在这里插入图片描述

代码实现

//归并排序

#include <iostream>
using namespace std;

void mergeSort(int* arr, int num);//归并排序的入口
void process(int* arr, int L, int R);//实现过程
void merge(int* arr,int L,int M,int R);//排序过程


void mergeSort(int* arr, int num)
{
	if (arr == nullptr || num < 2)
	{
		return;
	}
	process(arr,0,num-1);//传入数组,第一个元素的下标,最后一个元素的下标
	
}
void process(int* arr, int L, int R)
{
	//如果L==R,表示这个元素已经被划分到最后,成为单个元素,返回它,让它和相邻的一个单个元素去排序
	if (L == R)
	{
		return;
	}
	//如果不是最后一个元素,继续调用自己,继续划分
	int mid = L + ((R - L) >> 1);//找中点,为什么不用(L+R)/2,因为L+R可能会导致溢出,但R-L不会 位运算右移表示除2
	//从中间划分    这里会导致函数压栈 先排好左边的,在排右边的,先最左边的一个元素和最左边的第二个元素先排序
	process(arr, L, mid);
	process(arr, mid + 1, R);
	//排序
	merge(arr, L, mid, R);
}

void merge(int* arr, int L, int M, int R)
{
	//开辟辅助空间,存放排序后的数组
	int* help = new int[R - L + 1];
	int i = 0;//用来当辅助空间的下标
	int p1 = L;//待排序的左边组的下标,用来偏移
	int p2 = M + 1;//待排序的右边组的下标,用来便宜
	//排序
	while (p1 <= M && p2 <= R)//边界条件
	{
		//比较arr数组中两个下标的数值,并且在赋值给辅助空间后进行下标偏移
		help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
	}
	//将剩下的未比较元素赋值拷贝到辅助空间
	while (p1 <= M)
	{
		help[i++] = arr[p1++];
	}
	while (p2 <= R)
	{
		help[i++] = arr[p2++];
	}
	//将辅助空间的数组拷贝到arr中,arr下标从L开始
	for (i = 0;i<R-L+1;i++)
	{
		arr[L + i] = help[i];
	}
	//释放辅助空间
	delete[]help;
	//指针制空,避免出现野指针
	help = nullptr;
	
}


int main()
{
	int arr[] = {0,5,4,2,7,5,1};
	mergeSort(arr, sizeof(arr)/sizeof(arr[0]));
	//mergeSort(arr, sizeof(arr));将导致Run-Time Check Failure #2 - Stack around the variable 'arr' was corrupted.
	//因为sizeof(arr)会是数组的大小而不是元素的个数,导致后面的访问下标越界
	for (int a : arr)
		cout << a;
	return 0;
}

遇到的问题

Run-Time Check Failure #2 - Stack around the variable ‘arr’ was corrupted.
栈被破坏,一般是内存溢出
解决办法:
断点调试发现传入mergeSort函数的num = 28,但是我想传入的是数组元素的个数应该是7。
之后反应过来,sizeof数组出来的结果是数组占用的内存,应该再除以单个元素的大小。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

czx鑫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值