您的位置:首页 > 其它

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

2015-03-10 09:56 405 查看


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.使用归并排序处理相关问题,统计数组中的逆序对

《剑指Offer》P191

// 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: