归并排序+分治

归并:将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有
序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
归并的本质–空间换时间,通过申请一个额外数组存储中间变化,从而实现排序
归并排序核心步骤:

在这里插入图片描述
归并排序的特性总结:
. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。—外部排序首选
2. 时间复杂度:O(N*logN)
3. 空间复杂度:O(N)
4. 稳定性:稳定

Merge(int array[], int left, int mid, int right, int extra[]) {
//向新数组放数
	int i = left;	// 左边区间的下标
	int j = mid;	// 右边区间的下标
	int k = left;		// extra 的下标---额外空间的下标
	while (i < mid && j < right) {
	//两个不同的区间可以理解为(0(i),mid)(j(mid),right)
		if (array[i] <= array[j]) {
			extra[k++] = array[i++];
		}
		else {
			extra[k++] = array[j++];
		}
	}
	while (i < mid) {
		extra[k++] = array[i++];
	}
	while (j < right) {
		extra[k++] = array[j++];
	}
	// 把 extra 的数据移回来
	for (int x = left; x < right; x++) {
		array[x] = extra[x];
	}
}
// [left, right)
void  MergeSort(int array[], int left, int right, int extra[]) {
	结束:size == 1	---左闭右开
	if (right == left + 1) {
		return;
	}
	// size == 0
	if (right <= left) {
		return;
	}
	// 1. 把数组平均分成两部分
	int mid = left + (right - left) / 2;
	// [left, mid)
	// [mid, right)
	// 2. 分治算法,排序左右两部分---递归的直到分成1个数字然后比较
	__MergeSort(array, left, mid, extra);
	__MergeSort(array, mid, right, extra);
	// 3. 合并两个有序数组 [left, mid)	[mid, right)
	Merge(array, left, mid, right, extra);
}
void MergeSort(int array[], int size) {
	int *extra = (int *)malloc(sizeof(int)* size);
	__MergeSort(array, 0, size, extra);
	free(extra);
}
void MergeSortNoR(int array[], int size) {
	int* extra = (int *)malloc(sizeof(int)* size);
	// i 的含义:i 个有序的数组 和另一个 i 个有序的数组进行合并
	for (int i = 1; i < size; i = 2 * i) {
		// 一层里需要多少次归并
		// j 表示的是要合并的两个有序数组的左边数组的左边界
		// i 是有序数组的长度
		for (int j = 0; j < size; j = j + 2 * i) {
			int left = j;
			int mid = j + i;
			if (mid >= size) {
				// mid 越界,说明没有右边一个有序数组,不需要归并
				continue;
			}
			int right = mid + i;
			if (right > size) {
				right = size;
			}
			Merge(array, left, mid, right, extra);
		}
	}
	free(extra);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值