您的位置:首页 > 其它

多路归并排序

2014-07-25 19:28 162 查看
下面的问题描述及相关文字都参考于CSDN中JULY的博客,在此对JULY表示感谢。JULY的博客地址如下:
http://blog.csdn.net/v_JULY_v/article/details/6451990

在对海量数据排序时,有时不能把数据全部导入到内存中,这时需要用到多路归并排序。
比如
输入:一个最多含有n个不重复的正整数(也就是说可能含有少于n个不重复正整数)的文件,其中每个数都小于等于n,且n=10^7。

输出:得到按从小到大升序排列的包含所有输入的整数的列表。

条件:最多有大约1MB的内存空间可用,但磁盘空间足够。且要求运行时间在5分钟以下,10秒为最佳结果。

解答:
1、内存排序

由于要求的可用内存为 1MB,那么每次可以在内存中对 250K 的数据进行排序,然后将有序的数写入硬盘。那么 10M 的数据需要循环 40 次,最终产生 40 个有序的文件。

2、归并排序
1. 将每个文件最开始的数读入(由于有序,所以为该文件最小数),存放在一个大小为40 的 first_data 数组中;

2. 选择 first_data 数组中最小的数 min_data,及其对应的文件索引 index;

3. 将 first_data 数组中最小的数写入文件 result,然后更新数组 first_data(根据 index读取该文件下一个数代替 min_data);

4. 判断是否所有数据都读取完毕,否则返回 2。

流程图如下:





自己写的对19个数组进行5路归并的程序,只是简单实现。

假定5个数组已经分别排好序了:{0,5,11,18},{4,7,9,14},{6,8,12,17},{10,13,15,16},{1,2,3}

051118
47914
681217
10131516
123
刚开始时,从5个数组中读入最初的数据到tmp[5]数组中,即0,4,6,10,1.找出最小的值为0,在第0个数组中。把0放入最终的接收数组data[]中,并把第0个数组更新,data[0]=0:

051118
47914
681217
10131516
123
此时最小值为1,在第4个数组中,data[1]=1:

051118
47914
681217
10131516
123
data[2]=2

051118
47914
681217
10131516
123
...
直至全部比较完。

#include <iostream>
#include <time.h>
#include <bitset>
#include <assert.h>
#include <algorithm>
using namespace std;
const int Max=9999;

int main()
{
const int size=19;
int data[size]={0};//接收最终的有序数组

//等待归并的5个有序子数组
int a0[4]={0,5,11,18};
int a1[4]={4,7,9,14};
int a2[4]={6,8,12,17};
int a3[4]={10,13,15,16};
int a4[3]={1,2,3};
int len0,len1,len2,len3,len4;
len0=len1=len2=len3=4;
len4=3;

int i[5]={0};//指针数组,i[0]指向第一个数组,i[1]指向第二个数组.....
int k=0;

int tmp[5]={0};
while(i[0]<len0 ||i[1]<len1||i[2]<len2||i[3]<len3||i[4]<len4)
{
if(i[0]<len0)
tmp[0]=a0[i[0]];
else
tmp[0]=Max;

if(i[1]<len1)
tmp[1]=a1[i[1]];
else
tmp[1]=Max;

if(i[2]<len2)
tmp[2]=a2[i[2]];
else
tmp[2]=Max;

if(i[3]<len3)
tmp[3]=a3[i[3]];
else
tmp[3]=Max;

if(i[4]<len4)
tmp[4]=a4[i[4]];
else
tmp[4]=Max;
int min=tmp[0],pos=0;
//遍历,找最小值,并记录最小值所在位置
for(int j=1;j<5;j++)
{
if(min>tmp[j])
{

min=tmp[j];
pos=j;//记录最小值在哪个位置
}
}
i[pos]++;//指针往后移动一个
data[k++]=min;//记录

}

for(int i=0;i<size;i++)
{
if(i%5==0)
cout<<endl;
cout<<data[i]<<' ';
}
system("pause");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: