归并排序初体验

何为归并排序(MergeSort)?

和快速排序的思想一样,归并排序也是采用分治的思想,利用递归实现.我们要将一个数组排序,如果数组的左半边是有序的,右半边也是有序的,那么只要遍历左/右半边,将两个区间中较小的元素"挑"出来,存到数组里,如果相等,取第一个区间的元素,当遍历完,就可以合并成一个有序的数组.

那么问题来了,怎么样将左半边的数组变成有序的呢,答:如果左半边的左半边和右半边是有序的,就可以利用刚刚的方法排序...这样无限细分,当得到区间内只有一个元素的时候,这区间中的元素绝对有序.

所以归并排序是先递归到最小的区间,再依次合并排序成一个更大的区间,一个动态图可能更能说明:

代码实现

#include <iostream>

using namespace std;

const int N = 1000010; // 数组的大小
int n;
int q[N]; 
int temp[N]; // 临时数组


void merge_sort(int q[], int l, int r)
{
	//如果区间内的元素个数为1,或者没有元素就返回
	if (l >= r)
	{
		return;
	}

	int mid = (l + r) >> 1; // 将区间划分为两半

	merge_sort(q, l, mid);
	merge_sort(q, mid + 1, r);

	int k = 0, i = l, j = mid + 1; // k记录着临时数组中元素的个数

	while (i <= mid && j <= r)
	{
		if (q[i] <= q[j])
		{
			temp[k++] = q[i++];
		}
		else
		{
			temp[k++] = q[j++];
		}
	}

    // 左/右半边区级可能还有元素没被"挑选"
	while (i <= mid)
	{
		temp[k++] = q[i++];
	}
	while (j <= r)
	{
		temp[k++] = q[j++];
	}
	
    //q数组是从l开始r结束
    //temp数组是从0开始
	for (int i = l, j=0; i <= r; i++,j++)
	{
		q[i] = temp[j];
	}
}

int main(void)
{
	scanf("%d", &n);

	for (int i = 0; i < n; i++)
	{
		scanf("%d", &q[i]);
	}

	merge_sort(q, 0, n - 1);

	for (int i = 0; i < n; i++)
	{
		printf("%d ", q[i]);
	}

	return 0;
}

 稳定性

归并排序是稳定的排序,意思是数组中有两个相同的元素,拍完序后不改变他们的相对位置的话,就称这个排序是稳定的,快速排序就是一种不稳定的排序.

时间复杂度

对于归并排序每一层排序,都要遍历n个数据,那么要遍历多少次?看图,可以轻易得知,是n到1的次数,

每一层n都是除以2,n除以2的次数的次方等于1,次数为\log_{2} n,总共n\log_{2} n次,这就是时间复杂度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值