归并排序

归并排序运用分治法,先将无序序列不断分解,再将有序子序列逐层合并,得到完全有序序列。

归并排序的算法我们通常用递归实现,终止条件为分解到子区间只有一个元素。先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,默认单个元素不用排序。最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。

归并细节:比较已排好序的左区间a[i]和右区间b[j]的大小,若a[i]≤b[j],则将左区间中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将右区间中的元素b[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。


归并排序时间复杂度为O(nlog₂n),空间复杂度为 O(n)比较占用内存,但却是一种效率高且稳定的算法。

C++实现代码如下:

//将data[]每层每个子序列已经排好序的左右区间的数据归并到result[]相应的下标中
void merge(int *data, int start, int end, int *result)
{
	int mid = (start+end)/2;
	int left_index = start;//左区间下标
	int right_index = mid+1;//右区间下标
	int result_index = start;
	while (left_index <= mid && right_index <= end )
	{
		if (data[left_index] <= data[right_index])
			result[result_index++] = data[left_index++];
		else
			result[result_index++] = data[right_index++];
	}
	while (left_index <= mid )
		result[result_index++] = data[left_index++];
	while (right_index <= end )
		result[result_index++] = data[right_index++];
}
//注意每层每个子序列的start和end是不一样的
void merge_sort(int *data, int start, int end, int *result)
{
	int mid = (start + end) / 2;
	if (start == end)//划分到每个子序列只有一个元素结束
		return;
	else
	{
		merge_sort(data, start, mid, result);//划分每层每个子序列的左区间
		merge_sort(data, mid + 1, end, result);//划分每层每个子序列右区间
		merge(data, start, end, result);//开始归并每层每个子序列已经排好序的左区间和右区间,即该层start到end之间的数据,单个元素不用排序
		for (int i = start; i <= end; ++i)//把排序后的区间数据复制到原始数据中去
			data[i] = result[i];
	}
}

int main()
{
	int data[] = { 23,21,34,45,35,56,89,12 };
	const int length = 8;
	int result[length];
	cout << "Before sorted:" << endl;
	for (int i = 0; i < length; ++i)
		cout << data[i] << "  ";
	cout << endl;
	merge_sort(data, 0, length - 1, result);
	cout << "After sorted:" << endl;
	for (int i = 0; i < length; ++i)
		cout << data[i] << "  ";
	cout << endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值