多路归并 大数据处理

问题描述:

输入:给定一个文件,里面最多含有n个不重复的正整数(也就是说可能含有少于n个不重复正整数),且其中每个数都小于等于n,n=10^7。
输出:得到按从小到大升序排列的包含所有输入的整数的列表。
条件:最多有大约1MB的内存空间可用,但磁盘空间足够。且要求运行时间在5分钟以下,10秒为最佳结果。

分析文件大小:

10^7 = 1000,0000 = 10,000,000
一个数据=1B,那么大约为10M

归并排序(二路归并排序):

你可能会想到把磁盘文件进行归并排序,但题目要求你只有1MB的内存空间可用,所以,归并排序这个方法不行。

最终解决办法:

外排序(快速排序+多路归并排序):

内存中快速排序

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

个人理解:

1. 按个数 1000 个 ,文件内遍历每个数字做mod/1000操作,把数据分散到1000个文件中。每个小文件大约40KB大小。

2. 1000个小文件,分别导入内存做快排或者任何nlogn排序

3. 内存中创建,

//自定义从小到大排序

std::priority_queue < int, vector<int>, greater<int> > pq_int;

每次分别从1000个文件中读取一个数值(这个数值是每个文件中最小的一个),push到优先级队列内,写入队列后,优先级队列会自动排序,内部机制是堆排序,然后打印队列内1000个数值,即为结果(相当于归并排序)

接着,继续从1000个小文件内继续读取后面的数值,写入优先级队列,排序输出。

4.基本思想就是,拆分大文件,各个击破小文件,归并处理结果。

多路归并排序

  1. 将每个文件最开始的数读入(由于有序,所以为该文件最小数),存放在一个大小为40的first_data数组中;
  2. 选择first_data数组中最小的数min_data,及其对应的文件索引index;
  3. 将first_data数组中最小的数写入文件result,然后更新数组first_data(根据index读取该文件下一个数代替min_data);
  4. 判断是否所有数据都读取完毕,否则返回2。

多路归并程序的流程图:

第一步、Memory Sort。
这里写图片描述
第二步、Merge Sort。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/andylau00j/article/details/82859419