0.思路

10亿个32位整数需要4G左右的内存,一次性载入内存是不现实的,必须要采用外排。第一次接触,当然是从最简单的办法入手。

我们可以利用大容量的外存作为中转,将10亿个数切分成小块,每一块排序好后写入外存。
切分完成后,对这些小块进行归并排序。同时在归并排序过程中,获得最大(小)值将实时写入文件,这样就可以保证低内存占用。

注:下面的例子为升序排序


1.切分10亿个数

假设’billion’文件为包含10亿个32位整数数的二进制文件,我们需要将’billion’切分为n个小块(我取n为100,即每块10000000个数)暂存在外存。其中每块文件均需被排序,这里我用的是c的库函数qsort

需要注意的是,如果块大小过大(比如我取的10000000*4字节),块将无法作为auto数组分配,只能设为静态数组

static __int32 piece[PIECESIZE];  //PIECESIZE为块大小FILE *billion = fopen( "billion", "rb" );
int i = 0;
while( i < TOTAL / PIECESIZE ){  //TOTAL为billion文件中整数的数量//读取一块fseek( billion, PIECESIZE * i, SEEK_SET );fread( piece, sizeof( *piece ), PIECESIZE, billion );//排序qsort( piece, PIECESIZE, sizeof( *piece ), comp );char fileName[200];snprintf( fileName, sizeof(fileName), "piece/piece%d.bin", i );//输出FILE *outFile = fopen( fileName, "wb" );fwrite( piece, sizeof( *piece ), PIECESIZE, outFile );fclose( outFile );++i;
}

其中comp函数为一个比较函数,返回1或0,可设置为(按升序排列)

int comp( const void *a, const void *b )
{return *(__int32*)a - *(__int32*)b;
}

2.对这n块进行归并排序

10亿个文件已经切分成n块了,并且这n块已经为有序,于是我们可以利用归并排序读取这n块,并将每次的结果实时写入文件。在这期间内存的消耗将维持在很低的水平。

FILE *outFile = fopen( "out", "wb" );
FILE *fileList[FILEAMOUNT];  //FILEAMOUNT即为块的数量
int i;
//打开n个块
for( i = 0; i < FILEAMOUNT; ++i ){char filePath[200];snprintf( fileName, sizeof(fileName), "piece/piece%d.bin", i );fileList[i] = fopen( filePath, "rb" );
}//每个块读取第一个(最小的)元素
int numbers[ FILEAMOUNT ];
for( i = 0; i < FILEAMOUNT; ++i ){fread( numbers + i, sizeof( __int32 ), 1, fileList[i] );
}int n = 0;
//归并
while( 1 ){int minIndex = MinIndex( numbers );if( minIndex == -1 )  break;  //所有文件读取完毕//实时写入fwrite( numbers + minIndex, sizeof( __int32 ), 1, outFile );++n;fread( numbers + minIndex, sizeof( __int32 ), 1, fileList[minIndex] );if( feof( fileList[minIndex] ) ){numbers[minIndex] = -1;  //本文件读取完毕}
}//操作完成,关闭文件
for( i = 0; i < FILEAMOUNT; ++i ){fclose( fileList[i] );
}
fclose( outFile );

其中MinIndex函数获取数组中最小的值的下标,同时遇到-1会跳过(因为我用-1作为文件读取完毕的标记)。MinIndex函数如果返回-1则代表所有文件读取完毕(数组中全是-1)

int MinIndex( int *arr )
{int i, index = -1;for( i = 0; i < FILEAMOUNT; ++i ){if( arr[i] == -1 ) continue;  //判断文件是否读取完毕if( index == -1 || arr[index] > arr[i] ) index = i;}return index;
}

3.总结

根据计时器可知,分割+每块排序用时281s,归并用时453s,可见硬盘IO性能是这个程序主要的耗时
刚接触外排,所以用的方法比较原始和简陋,先去补补算法吧。。

如何排序10亿个数--外排小试相关推荐

  1. 在10亿个数中找出前1000个最大的

    在10亿个数中找出前1000个最大的 假设现在有一个文件,里面存放了10亿个整数,需要找出前1000个最大的. 方法: 1.普通排序,部分排序:几乎不可取. 2.分治法:随机选一个数t,然后对整个数组 ...

  2. 利用最小堆找出10亿个数中最大的10000个数

    最小堆 最小堆是一种完全二叉树,特点是根节点比两个子节点都小(或者根节点比子节点都大) 过程 先找10000个数构建最小堆 依次遍历10亿个数,如果比最小堆的最小值大,则替换这个最小值,并重新构建最小 ...

  3. 谈从10亿个数中找出前10万个最大的

    谈从10亿个数中找出前10万个最大的 期的实验显示10亿个浮点数大概占据3G左右的空间,因此全部一次性读入内存目前在个人PC上是不太现实的.本次讨论不考虑内存等等,只考虑算法. 如果一次性比较排序,然 ...

  4. 海量数据处理 - 10亿个数中找出最大的10000个数(top K)

    海量数据处理 - 10亿个数中找出最大的10000个数(top K问题) 版权声明:本文为博主原创文章,未经博主允许不得转载 前两天面试3面学长问我的这个问题(想说TEG的3个面试学长都是好和蔼,希望 ...

  5. 10亿个数中找出最大的10000个数

    转载自  海量数据处理 - 10亿个数中找出最大的10000个数(top K问题) 前两天面试3面学长问我的这个问题(想说TEG的3个面试学长都是好和蔼,希望能完成最后一面,各方面原因造成我无比想去鹅 ...

  6. 如何在10亿个数中找到前1000大的数?

    2019独角兽企业重金招聘Python工程师标准>>> 如何在10亿个数中找到前1000大的数? 定位 TopN问题 算法 排序不是最优的解决方案: 可以考虑分治法: 类似快速排序中 ...

  7. 10亿个数中找出最大的10000个数(top K问题)

    原博链接: https://blog.csdn.net/cbjcry/article/details/84917432 问题引入:10亿个数中找出最大的10000个数(top K问题) top K问题 ...

  8. 在存有10亿个数的文件中找到最大的100万个数

    这是<编程珠玑>中的一道题目.10亿个整数,假设每个整数需要四个字节,如果使用排序的话,需要大约4G的内存,现在的很多pc都没有多这么内存,更不用说作者那个年代. 我们借助最小堆来解决这个 ...

  9. 10亿个数中求最大的10个数字

    10亿个数中求最大的10个数字 应用场景 比如求10亿个数中的最大的前10个数,此时构建只有10个元素的小顶堆,如果比堆顶小,则不处理:如果比堆顶大,则替换堆顶,然后依次下沉到适当的位置. 比如求10 ...

最新文章

  1. java 生成pdf itext_使用Java组件itext 生成pdf介绍
  2. 接口有class类对象吗
  3. 目前我国家庭计算机用户接入因特网的下述,目前我国家庭计算机用户接入因特网的下述几种方法中,速度最快的是________ 。...
  4. 互联网基础知识_数字化工业网络—工业互联网的网络技术.pptx
  5. Swift基础--方法
  6. makefile之目标与依赖(1)
  7. 一道NP中的EIGRP拓扑表的题
  8. 基于SSM实现的网上书城系统【附源码】(毕设)
  9. [EXCEL高级应用与数据分析].沈浩.扫描版 百度云盘
  10. C# 正态分布图 标准偏差 STDEV 概率密度函数 NORM.DIST
  11. uniapp 最接近微信的图片压缩插件 Ba-ImageCompressor
  12. 无线路由器常用的五种工作模式详细介绍
  13. 基于asp.net028住院部病人管理系统
  14. 信息隐藏与数字水印实验:图片类隐写(MATLAB)
  15. Java程序员如何写简历,给大家一个小建议?
  16. PtCMS采集,PtCMS采集插件,PtCMS全自动采集无需采集规则详解(图文)
  17. mysql5.6解压包卸载_windows下安装、卸载mysql服务的方法(mysql 5.6 zip解压版安装教程)...
  18. 计算机中的图形(Graphic)和图像(Image)
  19. [转贴]让板载声卡支持ASIO
  20. 通过可视化图了解您的 Spark 应用程序

热门文章

  1. 什么是K线图,怎么看K线图
  2. ZSD019发票号码查询报表
  3. 用命令行去除音频文件的背景噪声
  4. Android手机实时视频监控
  5. React hooks 不能拿到最新的的setState的值
  6. puppy linux u盘,Puppy Linux v4.0 下载 可安装在U盘上的操作系统
  7. python毕业设计项目源码选题(16)跳蚤市场二手物品交易系统毕业设计毕设作品开题报告开题答辩PPT
  8. 对拉格朗日乘数法和KKT条件的简单理解(来自PRML的附录)
  9. SockJS简单介绍
  10. python自学免费图片_自学Python----爬取Beautyleg图片