归并排序及统计数组逆序对





1.归并排序


《算法导论》P19


参考网址:


白话经典算法系列之五 归并排序的实现 - MoreWindows Blog -博客频道 - CSDN.NET


http://blog.csdn.net/morewindows/article/details/6678165


#include "stdafx.h"
#include <iostream>
using std::cout;

#define ARRAY_LENGTH 11

//排序两个已经排好序的数组
//参数:data原始数组,copy组合成的数组,start,mid,end记录两个数组在原始数组中的位置
//      mid表示第一个数组的截止位置
void Merge(int data[],int copy[],size_t start,size_t mid,size_t end)
{
	//判断输入参数是否合法
	if ((data != nullptr) && (copy != nullptr) && (start <= mid) && (mid < end))
	{
		size_t i = start;    //左数组开始位置
		size_t j = mid + 1;  //右数组开始位置
		size_t index = start;//辅助数组开始位置
		while ((i <= mid) && (j <= end))
		{
			//比较两个值,较小者放入辅助数组中,并将指针前移
			if (data[i] <= data[j])
			{
				copy[index++] = data[i++];
			}
			else
			{
				copy[index++] = data[j++];
			}
		}

		//处理一个数组遍历完,另一个数组还有剩余元素的情况
		while (i <= mid)
		{
			copy[index++] = data[i++];
		}

		while (j<=end)
		{
			copy[index++] = data[j++];
		}

		//整理排序好后的data数组
		for (size_t k = 0; k <= end; k++)
		{
			data[k] = copy[k];
		}
	}
}

//归并算法核心算法
void Merge_Sort(int data[], int copy[], size_t start, size_t end)
{
	if ((data != nullptr) && (copy != nullptr))
	{
		if ((start < end))
		{
			size_t mid = (start + end) / 2;
			//分治思想
			Merge_Sort(data, copy, start, mid);
			Merge_Sort(data, copy, mid + 1, end);
			//对数组进行排序
			Merge(data, copy, start, mid, end);
		}
	}
	else
	{
		cout << "数组参数输入有误";
	}
}

//打印数组
void printf_array(int data[], size_t length)
{
	for (size_t i = 0; i < length; i++)
	{
		cout << data[i] << std::endl;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	int data[] = {10,32,9,1,23,42,5,67,88,23,7};
	//printf_array(data, ARRAY_LENGTH);
	int copy[ARRAY_LENGTH];
	Merge_Sort(data, copy, 0, ARRAY_LENGTH - 1);
	printf_array(data, ARRAY_LENGTH);
	return 0;
}


Java版,代码几乎相同:

public class Merge_Sort {

	// 排序算法
	private void Merge(int[] data, int[] copy, int start, int mid, int end) {
		
		//判断输入参数是否合法
		if ((data != null) && (copy != null) && (start <= mid) && (mid < end))
		{
			int i = start;    //左数组开始位置
			int j = mid + 1;  //右数组开始位置
			int index = start;//辅助数组开始位置
			while ((i <= mid) && (j <= end))
			{
				//比较两个值,较小者放入辅助数组中,并将指针前移
				if (data[i] <= data[j])
				{
					copy[index++] = data[i++];
				}
				else
				{
					copy[index++] = data[j++];
				}
			}

			//处理一个数组遍历完,另一个数组还有剩余元素的情况
			while (i <= mid)
			{
				copy[index++] = data[i++];
			}

			while (j<=end)
			{
				copy[index++] = data[j++];
			}

			//整理排序好后的data数组
			for (int k = 0; k <= end; k++)
			{
				data[k] = copy[k];
			}
		}
		
	}



	public void Merge_Sort(int[] data, int[] copy, int start, int end) {
		if (start < end) {
			int mid = (start + end) / 2;
			Merge_Sort(data, copy, start, mid);
			Merge_Sort(data, copy, mid + 1, end);
			Merge(data, copy, start, mid, end);
		}

	}

	public static void main(String[] args) {
		
		int data[] = {2,34,45,2,13,24,5,24,57};
		new Merge_Sort().Merge_Sort(data, new int[data.length], 0, data.length-1);
		
		for(int  num : data)
		{
			System.out.print(num);
			System.out.print(" ");
		}
	}

}



2.使用归并排序处理相关问题,统计数组中的逆序对


《剑指OfferP191


// InversePais1.cpp : 计算N个元素的数组的逆序对
//

#include "stdafx.h"

//计算逆序对函数
int get_InversePairs(int data[],int copy[],size_t start,size_t mid,size_t end)
{
	int count = 0;
	//判断数组是否为空,及输入的位置参数是否合法
	if ((data!=nullptr)&&(copy!=nullptr)&&(start <= mid)&&(mid < end))
	{
		int i = mid;
		int j = end;
		int index = end;

		while ((i >= start)&&(j >= mid + 1)&&(i * j >= 0))
		{
			//比较取最大者,放在辅助数组的末位
			if (data[i] > data[j])
			{
				copy[index--] = data[i--];
				count += (j - mid);//逆序对统计
			}
			else
			{
				copy[index--] = data[j--];
				//此时表示后者大于前者,不满足逆序对的定义,故count不进行操作
			}
		}
		//处理剩余数组(注:此情况count也不再会发生改变,因为已经统计完全)
		while ((i >= start) && (i >= 0))
		{
			copy[index--] = data[i--];
		}

		while ((j >= mid + 1) && (j >= 0))
		{
			copy[index--] = data[j--];
		}
		printf("原始数据:");
		for (size_t k = start; k <= end; k++)
		{
			printf("%d ", data[k]);
		}
		printf("\n当前数据:");
		for (size_t k = start; k <= end; k++)
		{
			data[k] = copy[k];
			printf("%d ", data[k]);
		}
		printf("\n");
		printf("逆序对数:%d\n", count);
	}
	return count;
}

int Reverse_Pairs(int data[], int copy[], size_t start, size_t end)
{
	if ((data == nullptr) || (copy == nullptr))
	{
		return 0;
	}
	if (start >= end)
	{
		return 0;
	}
	//分治策略
	int mid = (start + end) / 2;
	int left = Reverse_Pairs(data, copy, start, mid);
	int right = Reverse_Pairs(data, copy, mid + 1, end);
	int count = get_InversePairs(data, copy, start, mid, end);
	return left + right + count;

}


int _tmain(int argc, _TCHAR* argv[])
{
	int data[] = {7,5,6,4};
	const size_t LENGTH = 4;
	int copy[LENGTH];
	printf("%d\n", Reverse_Pairs(data, copy, 0, LENGTH-1));
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值