关于 merge sort

继quick sort后的第二个排序,merge sort,依然是分治的思想,将原数组分成若干个小数组,排序,然后再慢慢合并成大数组。

实现代码:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void merge(int a[], int b[], int lst, int rst, int re)
{
	int i, le, nums, tmp;
	le = rst - 1;
	tmp = lst;
	nums = re - lst + 1;
	while(lst <= le && rst <= re)//比较复制到临时表中 
		if(a[lst] >= a[rst])
			b[tmp++] = a[lst++];
		else
			b[tmp++] = a[rst++];
	while(lst <= le)//将未完成的复制完成 
		b[tmp++] = a[lst++];
	while(rst <= re)
		b[tmp++] = a[rst++];
	for(int i = 0; i < nums; i++, re--)//将临时数组中的内容拷贝回去 注意b中的顺序是和最后数组的顺序相反的
		a[re] = b[re];
}
void Msort(int a[], int b[], int left, int right)
{
	int center;
	if(left < right)
	{
		center = (left + right) / 2;
		Msort(a, b, left, center);//依然是分治的思想,类似快排 
		Msort(a, b, center + 1, right);
		merge(a, b, left, center + 1, right);
	}
}
void Mergesort(int a[], int n)//对大数据处理时常常要考虑到内存分配问题,所以要通过动态内存分配的方法来优化程序 
{
	int *tmp;
	tmp = (int *) malloc(sizeof(int) * n);
	if(tmp)
	{
		Msort(a, tmp, 0, n - 1);
	 	free(tmp);//每次归并排序时都只需要一个临时内存空间来协助排序,所以当排序结束后可以将其释放 
	}
	else
		puts("Error! No free ram left!");
} 
main()
{
	int nums[100];
	srand(time(NULL));
	for(int i = 0; i < 100; i++)
		nums[i] = rand() % 100;
	for(int i = 0; i < 100; i++)
		printf("%d ", nums[i]);
	puts("\n-----------------------------------------------");
	Mergesort(nums, 100);
	for(int i = 0; i < 100; i++)
		printf("%d ", nums[i]);
}
poj 2299: http://poj.org/problem?id=2299

本题是merge sort的经典题目,因为merge sort也是通过小数组的两两比较来排序的,和bubble很像,所以虽然本题可以用bubble得出正确答案,但超时是无疑的。

解题思路:计算每次排序后数字位置的变化量,将其累加。

AC代码:

#include<stdio.h>
#include<stdlib.h>
long long count;
void merge(int a[], int tmp[], int s, int m, int e)
{
	int ok = 0;
	int f = m - 1, k = s, n = e - s + 1, inis = s;
	while(s <= f && m <= e)
	{
		if(a[s] <= a[m])//临时数组tmp和原数组a是相同排序方式
		{
			tmp[k++] = a[s++];
		}
		else
		{
			count += abs(k - m);//只有当后面数列的数大于前面数列的数时才会互换,互换次数=abs(当前位-原位)
			tmp[k++] = a[m++];		
		}
	}
	while(s <= f)
		tmp[k++] = a[s++];
	while(m <= e)
		tmp[k++] = a[m++];
	for(int i = 0; i < n; i++)//为了使tmp复制到a上,特意设置了inis变量
		a[i + inis] = tmp[i+ inis];
}
void Msort(int a[], int tmp[], int s, int e)
{
	int mid;
	if(s < e)
	{
		mid = (s + e) / 2;
		Msort(a, tmp, s, mid);
		Msort(a, tmp, mid + 1, e);
		merge(a, tmp, s, mid + 1, e);
	}
}
void MergeSort(int a[], int n)
{
	int *tmp;
	tmp = (int *) malloc(sizeof(int) * n);
	if(tmp)
	{
		Msort(a, tmp, 0, n - 1);
		free(tmp);
	}
}
main()
{
	int n;
	int *nums;
	while(scanf("%d", &n) && n)
	{
		count = 0;
		nums = (int *) malloc(sizeof(int) * n);
		for(int i = 0; i < n; i++)
			scanf("%d", &nums[i]);
		MergeSort(nums, n);
		printf("%lld\n", count);
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值