《算法导论》学习:归并排序(哨兵)+ 逆序对问题

void merge(int (&a)[8], int left, int mid, int right)
{
#define MAX_NUM 0x7fffffff
	int la[100];
	int ra[100];
	int nla = mid - left + 1;
	int nra = right - mid;
	for (int i = 0; i < nla; ++i)
	{
		la[i] = a[left + i];
	}
	la[nla] = MAX_NUM;	//哨兵
	for (int i = 0; i < nra; ++i)
	{
		ra[i] = a[mid + 1 + i];
	}
	ra[nra] = MAX_NUM;	//哨兵

	int i = 0;
	int j = 0;
	for (int k = left; k <= right; ++k)
	{
		if (la[i] <= ra[j])
		{
			a[k] = la[i++];
		}
		else
		{
			a[k] = ra[j++];
		}
	}
}

void merge_sort(int (&a)[8], int start_pos, int len)
{
	if (start_pos < 0 || len <= 1)
	{
		return;
	}
	int half = len / 2;
	merge_sort(a, start_pos, half);
	merge_sort(a, start_pos + half, len - half);

	int mid_pos = 0;
	if (len % 2 == 0) //若长度为偶数,中位数取左边的一个, 以方便merge函数处理
	{
		mid_pos = start_pos + half - 1;
	}
	else
	{
		mid_pos = start_pos + half;
	}
	merge(a, start_pos, mid_pos, start_pos + len - 1);
	
}

void display(int (&a)[8], int len)
{
	for (int i = 0; i < len; ++i)
	{
		cout << a[i] << " ";
	}
	cout << endl;
}

int main(int argc, char* argv[])
{
	int a[] = { 4,2,5,1,3,4,8,2 };
	display(a, 8);
	merge_sort(a, 0, 8);
	display(a, 8);
	getchar();
	return 0;
}

逆序对问题定义:假设A[1..n]是一个有n个不同数的数组。若i<j且A[ i ]>A[ j ],则对偶(i, j)称为A的一个逆序对。

用归并排序很好解决这个问题,在merge函数里面,有两个有序数组,左边的有序数组la,右边的有序数组ra。在归并la和ra时判断两数组中元素大小,如果存在la[ i ] > ra[ j ] (i < j),那么逆序对数量就+1。

由于la和ra存在哨兵MAX_NUM,由于哨兵的存在而使得la[ i ] > ra[ j ] (i < j),这种情况不能算作是逆序对。比如:



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值