【C++】最好懂的归并排序讲解(附程序)

由于快速排序不稳定,所以大佬们引入归并。
步骤大概如下:

I、先看一组无序数组: 19 ,97 ,09, 17, 01,08

II、然后分组,先将数组序列每一个成员分成一组(如下图):
在这里插入图片描述
**

III、将两组按指定顺序合并到一组,我们此处由小到大,如果是自定义类记得重载比较运算符。**
在这里插入图片描述

IV、重复步骤III。
在这里插入图片描述

V、直到只有唯一一组时,排序完成,结果即为当前数组。
(理解起来是不是很简洁,时间复杂度:O(n log n))*
在这里插入图片描述
**

好了我们要开始敲程序了:(注意看注释)**

#include <iostream>
using namespace std;
static int  number1 = 0; //debug时加上

//1、分组
template<typename T>  //泛型编程是一个很好的习惯,让程序复用性更强
void devide_group(T *array, int left, int middle, int right,int *temp)
{
	int k1 = right - left + 1;
	temp = (T *)malloc(sizeof(T)*k1);//重新开辟临时数组空间
	int i = left, j = middle + 1, num = 0;
//有一个比较到指定位置则结束循环,比如左侧数组边只比较了前两个位置,但是右侧已经遍历完
//则此时的意思是左侧剩余的元素大于右侧所有的元素,再将剩余的元素接在临时数组当前第一个空缺位置处即可
	while (i <= middle && j <= right)  
		                                                  
	{
		if (array[i] <= array[j])   //左边数组从左到右跟右边组比较大小
		{
			temp[num++] = array[i++]; //左边大则将 i 位置元素放置在临时数组第一个空位置
		}
		else if (array[i] > array[j])左边小则将右侧 j 元素放置在临时数组第一个空缺位置
		{
			temp[num++] = array[j++];
		}
	}

	if (i <= middle)   //判断前一组是否比较完毕,后一组不需要,
		                       // 因为相对于原数组来说,后一组剩下元素肯定是大于前面所有元素的,位置不会发生改变。
	{
		temp[num++] = array[i++];
	};

	//if (j <= right)   //判断前一组是否比较完毕,后一组不需要,因为相对于原数组来说,后一组剩下元素肯定是大于前面所有元素的,位置不会发生改变。
	//{
	//	temp[num++] = array[j++];
	//};
	cout << "当前排序:" << "left:" << left << "  ~  " << right << "  value:  ";

	for (int k = 0; k < j-left; k++)
	{
		array[left++] = temp[k];
		cout << array[left - 1] << " ";
	}
	cout << endl;
	free(temp); //分配的空间记得释放哟
	temp = NULL;
}

template<typename T>
void merge_soft(T*array, int left, int right,int *temp) //最末和最开始
{
	if (left >= right)
	{
		return;
	}
	int middle = (right + left) / 2;
	merge_soft(array, left, middle,temp); //迭代使左侧分组每一组到只剩一个元素,然后调回上一层迭代跟另一组比较。
	merge_soft(array, middle + 1, right,temp);
	devide_group<T>(array, left, middle, right,temp);  //将排序好的两组再进行排序
	cout << "此时";
	while (left <= right)
	{
		cout << array[left++];
	}
	cout << "序号 " << number1++ << endl;
}

int main()
{

	int array[7] = { 1,2,5,6,3,4,5 };
	int *temp = NULL;
	merge_soft<int>(array, 0, 6,temp);
	cout << array[4] << "  ";
	//devide_group<int>(array, 4,5, 6);
	cout << "排序后:";
	for (int i = 0; i < 7; i++)
	{
		cout << array[i];
	}
	cout << endl;
}

复习代码:

void fun(int *a, int low,int low_h,int high_l,int high)
{
	int size = high - low + 1;
	int *temp = new int[size];
	int i = low, j = high_l;
	int num = 0;
	
	while (i <= low_h && j <= high)
	{
		if (a[i] < a[j])
		{
			temp[num++] = a[i];
			i++;
		}
		if (a[i] >= a[j])
		{
			temp[num++] = a[j];
			j++;
		}
	}

	if (i != low_h)
	{
		for (int k = i; i <= low_h; i++)
		{
			temp[num++] = a[i];
		}
	}

	for (int q1 = low; q1 <j;  ++q1)  
	{
		cout << "此时temp[ ] " << temp[q1 - low] << " 此时a " << a[q1] << endl;
		a[q1] = temp[q1 - low];
	 }
	delete [] temp;
	temp = nullptr;
}


void merger(int *a, int low, int high)
{
	if (low == high)
	{
		return ;
	}
	int middle = (low + high) / 2;
	 merger(a,low, middle);
	 merger(a,middle+1, high);
	 fun(a, low, middle, middle + 1, high);
	return ;
}

图片来源:https://www.bilibili.com/video/BV1et411N7Ac?from=search&seid=4632645683604929268

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值