`
xuexing
  • 浏览: 24547 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

问题:假设一个文件中有9亿条不重复的9位整数,现在要求对这个文件进行排序。

阅读更多
楔子:
问题:假设一个文件中有9亿条不重复的9位整数,现在要求对这个文件进行排序。

一般解题思路:
1、将数据导入到内存中
2、将数据进行排序 (比如插入排序、快速排序)
3、将排序好的数据存入文件

难题:
一个整数为4个字节
即使使用数组也需要900,000,000 * 4byte = 3.4G内存
对于32位系统,访问2G以上的内存非常困难,而且一般设备也没有这么多的物理内存
将数据完全导入到内存中的做法不现实

其他解决办法:
1、导入数据库运算
2、分段排序运算
3、使用bit位运算

解决方案一:数据库排序
将文本文件导入到数据库,让数据库进行索引排序操作后提取数据到文件

优点:操作简单
缺点:运算速度慢,而且需要数据库设备。

解决方案二:分段排序
操作方式:
规定一个内存大小,比如200M,200M可以记录52428800条记录,我们可以每次提取5000万条记录到文件进行排序,要装满9位整数需要20次,所以一共要进行20次排序,需要对文件进行20次读操作

缺点:
编码复杂,速度也慢(至少20次搜索)

关键步骤:
先将整个9位整数进行分段,亿条数据进行分成20段,每段5000万条
在文件中依次搜索0~5000万,50000001~1亿……
将排序的结果存入文件

解决方案三:bit位操作
思考下面的问题:
一个最大的9位整数为999999999
这9亿条数据是不重复的
可不可以把这些数据组成一个队列或数组,让它有0~999999999(10亿个)元素
数组下标表示数值,节点中用0表示这个数没有,1表示有这个数
判断0或1只用一个bit存储就够了

声明一个可以包含9位整数的bit数组(10亿),一共需要10亿/8=120M内存
把内存中的数据全部初始化为0
读取文件中的数据,并将数据放入内存。比如读到一个数据为341245909这个数据,那就先在内存中找到341245909这个bit,并将bit值置为1
遍历整个bit数组,将bit为1的数组下标存入文件

关键代码
检查是某一个char里面(first)的第second位中存储的数据是否为1

bool CompareBit (unsigned char first, int second)
{
const static int mark_buf[] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
if (second > .8)
return false;

return (first & mark_buf[second]) == mark_buf[second];
}

将某一个char(Desc)中的第source位置为1

bool WriteToBit (unsigned char *Desc, int source)
{
const static int mark_buf[] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};

if (source >  .8)
return false;

Desc[0] |= mark_buf[source];

return true;
}

案例
在某个项目中,我们需要对2亿条手机号码删除重复记录(过滤号码黑名单同样有效)

工作难点就在于如何处理这2亿条电话号码,直接用哈希表存放手机号码不大现实,即使经过优化,用一个unsigned int存放一条记录,那也得需要2亿*4=8亿byte,远超过32位系统的寻址能力

解决方案:
将电话号码由12位单个数字组成的字符串转换为一个unsigned int型数据(这个完全可能,手机号码由前三位数字和后面八位数字组成,后面八位需要占到1~1000万的空间,而前面用0~100的数字存储已经足够)
为简单起见,默认为0~4G的数字都有可能分布号码,为此我们分配4G/32=512M的内存
将这2亿个号码整理成unsigned int类型后按上述办法存放在这块内存中(比如13512345678我们整理后为112345678,我们找到内存中112345678bit的下标,并将此bit值设为1)
遍历整个bit数组,记录下所有的号码,这些号码即是不重复的手机号码

总结
建立一个足够大的bit数组当作hash表
以bit数组的下标来表示一个整数
以bit位中的0或1来表示这个整数是否在这个数组中存在
适用于无重复原始数据的搜索
原来每个整数需要4byte空间变为1bit,空间压缩率为32倍
扩展后可实现其他类型(包括重复数据)的搜索
分享到:
评论

相关推荐

    c语言数组C++要求给一个一维数组输入任意6个整数,假设是7,4,8,9,1,5,然后按下列方阵打印

    在这个特定的问题中,我们需要处理一个一维数组,并按照特定的方阵格式来打印这组数据。下面将详细解释如何实现这个任务。 首先,我们创建一个一维整型数组,比如`int arr[6]`,来存储给定的6个整数。这里,数组的...

    给定2到15个不同的正整数,你的任务是计算这些数里面有多少个数对满足:数对中一个数是另一个数的两倍。

    给定2到15个不同的正整数,你的任务是计算这些数里面有多少个数对满足:数对中一个数是另一个数的两倍。 比如给定1 4 3 2 9 7 18 22,得到的答案是3,因为2是1的两倍,4是2的两倍,18是9的两倍。 输入形式 输入...

    对一个含有N整数的数组,使用堆排序让其由小到大输出

    对一个含有N整数的数组,使用堆排序让其由小到大输出 样例输入 6 43 2 56 1 22 9 样例输出 1 2 9 22 43 56 堆排序 对一个含有N整数的数组,使用堆排序让其由小到大输出 样例输入 6 43 2 56 1 22 9 样例输出 1 2 9 ...

    基于Qt5-实现九大排序算法的代码汇总

    通过选取一个“基准”元素,将序列划分为两部分,使得一部分的所有元素都小于另一部分,然后递归地对这两部分进行排序。快速排序的平均时间复杂度为O(n log n),但在最坏情况下(输入已排序或反向排序)为O(n^2)。 ...

    整数数位和

    在实际应用中,这种数位和的计算方法还可以扩展到其他场景,比如计算大整数的数位和,或者对一个整数数组的每个元素进行同样的操作。此外,还可以优化算法以处理负数,考虑到负号不参与计算数位和,或者处理非十进制...

    给一维数组输入M个整数,假设M=6,数组元素分别为 7 4 8 9 1 5

    给一维数组输入M个整数,假设M=6,数组元素分别为 7 4 8 9 1 5 给一维数组输入M个整数,假设M=6,数组元素分别为 7 4 8 9 1 5 , 要求建立一个如下数组(矩阵): 7 4 8 9 1 5 4 8 9 1 5 7 8 9 1 5 7 4 9 1 5 7 4 8 1...

    不重复整数排序编码的遗传算法MATLAB完整代码

    不重复整数排序编码的遗传算法MATLAB完整代码 算法: 遗传算法 编码:不重复整数排序编码 目标函数: 逼近序列[9,8,7,6,5,4,3,2,1] 特点: 代码完整, 自动安装工具箱, 绘制迭代曲线 %% 遗传算法主循环 %进度条 wait_...

    输入任意一个整数转换成一定要求的整数,要求在下面

    标题中的“输入任意一个整数转换成一定要求的整数”指的是编程中常见的数字转换问题。这可能涉及到将用户输入的整数按照特定格式或规则进行转换,例如二进制、八进制、十六进制之间的转换,或者是指将整数进行位运算...

    排序算法: 冒泡排序,桶排序,计数排序,堆排序,插入排序,合并排序,快速排序,基数排序,选择排序,希尔排序 实现语言: C

    快速排序也是基于分治法,选取一个基准值,通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,然后再分别对这两部分记录进行排序。快速排序在平均情况下有很好的性能,...

    接收从键盘输入某班学生的学号、姓名、成绩,对学 生的成绩进行排序.zip

    程序需要实现对成绩的排序,常见的排序算法如冒泡排序、选择排序、插入排序、快速排序等都可以在汇编语言中实现。这里可能用到了比较和交换元素的操作,通过改变内存中的数据顺序达到排序的目的。 4. **内存管理**...

    排序,输入整数,从小到大,字符则反串

    本文将详细讲解如何实现标题所描述的功能,即设计一个类,其包含一个排序方法`SORT()`,该方法能根据输入的数据类型进行不同的处理:对于整数序列进行升序排序,而对于字符串则进行反向字符排列。 首先,我们需要...

    拖拽式文件排序改名工具

    "拖拽式文件排序改名工具"就是一种为了提升效率而设计的实用软件,它允许用户通过简单直观的拖放操作来对文件进行排序和重命名,极大地简化了传统手动操作的繁琐过程。以下是对这个工具及其相关知识点的详细解释: ...

    上海电机学院C语言实训答案

    (29)某公司在传输数据过程中为了安全要对数据进行加密,若传递的是四位的整数,对其进行加密的规则为:每位数字都加上5,然后用和除以10的余数代替该数字,再将第一位和第四位交换,第二位和第三位交换。...

    9大排序算法java版

    "9大排序算法java版"这个压缩包可能包含了以下九种经典的排序算法的Java实现: 1. 冒泡排序(Bubble Sort):这是一种简单的排序算法,通过重复遍历待排序的数组,依次比较相邻元素并交换位置来完成排序。时间...

    山东大学数据结构课程设计第一部分代码——外排序

    1. **大文件处理**:当数据量超过内存容量时,不能一次性将所有数据加载到内存中进行排序。外排序需要在磁盘和内存之间进行多次交互,确保数据的有效处理。 2. **多路归并排序**:外排序通常采用多路归并排序作为...

    电子学会等级考试二级:按照个位数排序 测试数据

    在这个问题中,考生需要编写程序,能够接受一个整数列表,并根据它们的个位数值进行升序排序。 首先,我们要理解什么是"个位数"。在数字系统中,个位是指最右边的数字,对于正整数,个位数是决定数字大小的最小单位...

    _leetcode-python.pdf

    - Search in Rotated Sorted Array II: 假设按照升序排序的数组在预先未知的某个点上进行了旋转,该问题要求在旋转后的数组中搜索特定元素。 这些知识点涵盖了数据结构和算法的核心概念,以及如何用Python语言实现...

    用javascript实现的十大排序算法详解

    基数排序根据数位进行排序,从最低有效位开始,依次对每一位进行排序。适合于处理大量整数排序,尤其当数值范围较大时。 10. 希尔排序(Shell Sort) 希尔排序是插入排序的一种优化版本,通过设定间隔序列来减少...

    Java语言实现9大排序

    基数排序是针对非负整数的一种排序,根据数字的每一位进行排序。它的时间复杂度为O(kn),k是数字的最大位数,不受原数组顺序影响,适合大量整数排序。 8. **桶排序**: 桶排序假设输入数据均匀分布在一定区间内,...

    java九宫排序算法

    九宫排序,也被称为幻方,是一种将数字填入3x3矩阵中,使得每行、每列以及两条对角线上的数字之和都相等的数学问题。在编程领域,实现九宫排序通常涉及算法设计和数据结构的运用。在Java中,我们可以采用不同的方法...

Global site tag (gtag.js) - Google Analytics