如何给1000万条记录排序,每条记录都是7位的整数
1. 问题描述
输入: 一个最多包含n个不重复的正整数的文件,其中每个数都小于n,每个数是一个7位的整数, n=10^7。
条件: 最多有1MB的内存可用, 排序最多只允许执行几分钟,10s是比较理想的运行时间.有充足的磁盘存储空间可用.
输出: 按升序排列的输入整数的列表.
2. 解决方案
2.1 归并排序
由于内存的限制, 只能采用多路归并的方法来解决这个问题.
排序方法; 把这个文件分为若干大小的几块,然后分别对每一块进行排序,最后完成整个过程的排序。k趟算法可以在kn的时间开销内和n/k的空间开销内完成对最多n个小于n的无重复正整数的排序。比如可分为2块(k=2,1趟反正占用的内存只有1.25/2M),1~4999999,和5000000~9999999。先遍历一趟,首先排序处理1~4999999之间的整数(用5000000/8=625000个字的存储空间来排序0~4999999之间的整数),然后再第二趟,对5000001~1000000之间的整数进行排序处理。
排序步骤:
(1) 内存排序: 由于要求的可用内存为1MB,那么每次可以在内存中对250K的数据进行排序,然后将有序的数写入硬盘。那么10M的数据需要循环40次,最终产生40个有序的文件。
(2) 归并排序:
- 将每个文件最开始的数读入(由于有序,所以为该文件最小数),存放在一个大小为40的first_data数组中;
- 选择first_data数组中最小的数min_data,及其对应的文件索引index;
- 将first_data数组中最小的数写入文件result,然后更新数组first_data(根据index读取该文件下一个数代替min_data);
- 判断是否所有数据都读取完毕,否则返回2。
实现过程中, 需要多次读写文件.
2.2 位图方案
数据表示: 使用一个具有1000万个位的字符串来表示输入文件数据, 其中,当且仅当整数i在文件中存在时,第i位为1.
采用位图原因: 利用了该问题在排序问题中不常见的3个属性:
- 输入数据限制在相对较小的范围内
- 数据没有重复
- 对于每条记录而言, 除单一整数外, 没有任何其他关联数据
位图解决三个步骤:
- 第一步, 将所有位置为0, 从而将集合初始化为空
- 第二步, 读入文件中的每个整数来建立集合, 将每个对应的位置为1
- 第三步, 检验每一位, 若该位为1, 就输出相应的整数, 由此产生有序的输出文件
其伪代码如下;
//第一步,将所有的位都初始化为0
for i ={0,....n} bit[i]=0;
//第二步,通过读入文件中的每个整数来建立集合,将每个对应的位都置为1。
for each i in the input file bit[i]=1; //第三步,检验每一位,如果该位为1,就输出对应的整数。
for i={0...n} if bit[i]==1 write i on the output file
java实现代码如下:
/** 位向量的实现及其应用在1000万个数的排序中*/
public class Bitvector {public static void main(String[] args){int number = 10000000; //待排序数的数量int len = (number - 1)/32 +1; //java中int占4字节,一位代表一个数,分配多少个int型变量int[] a = new int[len];int[] data = new int[number];//产生随机输入数据,数据是乱序的int temp,temp1;Random rand = new Random();for(int i=0;i<10000000;i++){data[i] = i;//随机交换temp = rand.nextInt(i+1);temp1 = data[temp];data[temp] = data[i];data[i] = temp1; }for(int i=0;i<len;i++){a[i]=0;}for(int i=0;i<number/10;i++){set(a,data[i]);}for(int i=0;i<number/10;i++){if(read(a,i)==1)System.out.print(i+" ");} }//将第i位置为1public static void set(int[] num,int i){num[i>>5] |= (1<<(i&0x1F)); //i>>5指的是i/32,确定其在哪一个int中,i&0x1F则是i%32,确定其在int中的哪一位}//将第i位置为0public static void clr(int[] num, int i){num[i>>5] &= ~(1<<(i&0x1F));}//读取第i位,判断是0/1public static int read(int[] num,int i){return num[i>>5] & (1<<(i&0x1F));}
}
上述java实现的是对100万个数据进行排序, 这些数据的大小在1000万之间, 由于限制了内存只有1M, 而1000 0000/(8*1024*1024)>1M, 故实现时应该分2趟进行排序,即
- 第一次,只处理1—4999999之间的数据,这些数都是小于5000000的,对这些数进行位图排序,只需要约5000000/8=625000Byte,也就是0.625M,排序后输出。
- 第二次,扫描输入文件时,只处理4999999-10000000的数据项,也只需要0.625M(可以使用第一次处理申请的内存)。
因此,总共也只需要0.625M
***位图的适用范围仅限于针对不重复的数据进行排序.
如何给1000万条记录排序,每条记录都是7位的整数相关推荐
- mysql单表1000万条_mysql单表千万条数据测试
软件环境:win7,mysql版本5.5,InnoDB存储引擎. 硬件环境:普通笔记本,CPU P8700双核2.53GHz,内存3G,5400转机械硬盘1000GB. 建了一张表,id列是自增长bi ...
- 1000并发 MySQL数据库_再送一波干货,测试2000线程并发下同时查询1000万条数据库表及索引优化...
继上篇文章<绝对干货,教你4分钟插入1000万条数据到mysql数据库表,快快进来>发布后在博客园首页展示得到了挺多的阅读量,我这篇文章就是对上篇文章的千万级数据库表在高并发访问下如何进行 ...
- 再送一波干货,测试2000线程并发下同时查询1000万条数据库表及索引优化
原文:再送一波干货,测试2000线程并发下同时查询1000万条数据库表及索引优化 继上篇文章<绝对干货,教你4分钟插入1000万条数据到mysql数据库表,快快进来>发布后在博客园首页展示 ...
- java sql 写入万条数据_如何快速向数据库插1000万数据?4种方法对比,它简单却速度最快
目录 场景介绍 项目配置 Mybatis为什么慢? JdbcTemplate让我眼前一亮 原生JDBC就是快啊! 存储过程怎么样? 越简单越快 前言 一直有一种说法:批量插入大量数据到MySQL数据库 ...
- 面试题-批量向MySQL导入1000万条数据有什么方法?
批量向MySQL导入数据 直接导入 使用存储过程循环拼接 使用load data infile 修改ENGINE=InnoDB为MyISAM(v5.1之前是MyISAM,之后是InnoDB) 减少IO ...
- 量化投资:记录自己知与行的实操,通过量化实践,用7年从0打造一个1000万的组合
知与行,理解和实践盈亏同源的理论.通过量化投资以最小的风险获取最高的收益是这个组合的道与术.按量化指数模型构建一个1000万组合的流程和方法,实践在量化投资之路上积小胜为大胜,最终实现7年1000万的 ...
- 绝对干货,教你4分钟插入1000万条数据到mysql数据库表,快快进来
我用到的数据库为,mysql数据库5.7版本的 1.首先自己准备好数据库表 其实我在插入1000万条数据的时候遇到了一些问题,现在先来解决他们,一开始我插入100万条数据时候报错,控制台的信息如下: ...
- akka 异常处理_使用Akka处理1000万条消息
akka 异常处理 Akka演员承诺并发. 有什么更好的模拟方法,看看使用商品硬件和软件处理1000万条消息需要花费多少时间,而无需进行任何低级调整.我用Java编写了整个1000万条消息的处理过程, ...
- 使用Akka处理1000万条消息
Akka演员承诺并发. 有什么更好的模拟方式,看看使用商品硬件和软件处理1000万条消息需要花费多少时间,而无需进行任何低级调整.我用Java编写了整个1000万条消息的处理过程,整个结果令我惊讶. ...
最新文章
- centos + php+ unixodbc + FreeTDS 配置
- 11、MySQL常见错误代码一览表
- python算法攻略_算法基础及python实现笔记一(堆和DFS)
- 冗余的Runnable代码
- 程序员十大心愿,程序员:你这么了解我的心声的嘛!
- PHP类参数_PHP依赖注入的含义
- Oracle行列转换的思考与总结
- WebRTC通信流程
- mysql++编程规范_建议收藏 - 专业的MySQL开发规范
- 安卓签名MD5相关说明
- python3使用MyQR库生成动态二维码
- IT行业是什么工作?做什么的?
- 计算机网络--哈工大网课--MOOC中国大学 慕课 答案
- bookmarks_2021_9_28
- Win7笔记本电脑启用虚拟WIFI共享上网
- android百度地图自动定位
- 3.12 编写程序从键盘输入一个整数,计算并输出该数的数字之和。例如:请输入 一个整数:8899123 各位数字之和为:40
- 如何在 Lightly 用 JavaScript 制作俄罗斯方块游戏
- DAY DAY UP 1
- Android 使用Gson解析json案例详解
热门文章
- 污水处理程序 工厂污水处理控制系统。 西门子PLC200smart和上位机wincc(版本号V7.4)污水处理控制系统
- 污水处理程序 工厂污水处理控制系统 西门子PLC200smart和上位机wincc(
- python爬虫介绍及其应用
- mpp架构 mysql,MPP架构知识整理
- js字符串通过正则转mac地址格式
- Sage X3基于业务的预算管理
- 人口学特征或个人因素适合做结构方程模型的潜变量吗?
- 美国东北大学计算机学院和工程学院,美国东北大学相当于中国什么等级的大学?...
- Android 模拟器连接 USB 设备
- 真是没的说,我也深深感觉这样,现在什么也干不下去,总是心静不下来.想学习,看点书,总是被工作打断.闲下来总想多休息一下,放松一下