归并排序

归并排序

  • 基本思想:归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
  • 很明显我们可以意识到它有两个重要步骤
    1、向下分治
    2、向上合并
  • 让我们来看看具体的归并排序示意图
    在这里插入图片描述
  • 有了图我们就更容易理解归并排序了,但是在这里我们要注意的就是,既然要合并两个有序序列,那么必然要有空间才行,故此,在归并排序这里,我们要用到额外的辅助空间,将合并好的序列放入辅助空间,并且要拷贝回原序列中的位置,这样最终就能实现我们的归并排序了。
  • 看起来其实没有那么难,但是这个代码还有点不好写,但是只要你想清楚了,还是比较容易写出来的,我们先来看一下如何写一个归并排序

在这里插入图片描述
1、平均切割区间
2、分治处理两个小区间
3、合并两个有序序列

具体代码实现

#include<iostream>
using namespace std;


/*
归并排序:将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有
         序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
时间复杂度	O(n * log(n))
空间复杂度	O(n)
稳定性:    稳定
外部排序(海量数据排序,内存放不下)
*/


//打印数组内容
void print(int array[], int size) {
	for (int i = 0; i < size; i++) {
		cout << array[i] << " ";
	}
	cout << endl;
}
//交换函数
void swap(int array[], int i, int j) {
	int tmp = array[i];
	array[i] = array[j];
	array[j] = tmp;
}

//合并有序序列
void merge(int array[], int start, int mid, int end, int* tmp) {
	int start1 = start;  //子数组1开始
	int end1 = mid;      //子数组1结束
	int start2 = mid + 1;//子数组2开始
	int end2 = end;      //子数组2结束

	int len = 0;         //辅助空间的有效长度

	//进行数据排序合并
	while (start1 <= end1 && start2 <= end2) {
		if (array[start1] < array[start2]) {
			tmp[len++] = array[start1++];
		}
		else {
			tmp[len++] = array[start2++];
		}
	}
	//当两个数组不一样长时,将长的数组剩余的元素补全到辅助空间后面
	while (start1 <= end1) {
		tmp[len++] = array[start1++];
	}
	while(start2 <= end2) {
		tmp[len++] = array[start2++];
	}

	//将辅助空间的数据拷贝到原数组中的原位置
	for (int i = 0; i < len; i++) {
		array[start + i] = tmp[i];
	}

}

//归并排序内部实现
void MergeSortInner(int array[], int start, int end, int* tmp) {
	
	//递归结束条件
	if (start >= end) {
		return;
	}

	//分成子序列
	int mid = (start + end) / 2;
	//递归左部分
	MergeSortInner(array, start, mid, tmp);
	//递归右部分
	MergeSortInner(array, mid+1, end, tmp);
	//合并有序序列
	merge(array, start, mid, end, tmp);
}

//归并排序主框架
void MergeSort(int array[], int size) {
	//因为归并排序是要合并两个有序序列,故此要申请一个额外的辅助空间,来装合并后的有序序列
	int* tmp = new int [size];
	MergeSortInner(array, 0, size - 1, tmp);
	delete[] tmp;
}


int main(void) {

	int array[] = { 12,2,34,10,8,2,54,70,100,86,34,6 };
	int size = sizeof(array) / sizeof(int);
	cout << "排序前:";
	print(array, size);
	cout << "排序后:";
	MergeSort(array, size);
	print(array, size);
	system("pause");
	return 0;
}
  • 归并排序总结
  1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(N)
  4. 稳定性:稳定

注:若文件数据很大,我们可以采用多路归并的方式,解决磁盘中的外排序问题

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值