码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-03-10 10:24:52      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:





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;
}


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;
}


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

标签:

原文地址:http://blog.csdn.net/woliuyunyicai/article/details/44171621

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!