• 怎样对千万级甚至亿级数据量排序


    编程珠玑第二版第一章就有类似的问题,问题描述如下:

    有最多1000万条不同的整型数据存在于硬盘的文件中(数据不超过最大值),如何在1M内存的情况下对其进行尽可能快的排序。

    数据特征:单个数据<=1000万、不同的(没有重复)、整型(int,4B)
    
    要求:1M内存、尽可能快
    
    分析:1MB = 1*1024*1024 B   能存储大于25万个int类型的整数。所以每次我们可以排序25万条记录,一共排序40次。

    (1)一个简单的思路是读1000万条1次,对第i个25万条数据进行排序,并将排好的结果存成外部文件i(这里可以用常见的内部排序,如快排),最后我们生成了40个排好序的外部文件,然后对这40个文件进行归并排序输出成1个文件。

    (2)更好的思路是位向量排序,我们可以申请一个1千万长度的位向量bit[10000000],所有位设置为0,顺序读取待排序文件,每读入一个数i,便将bit[i]置为1。当所有数据读入完成,便对 bit做从头到尾的遍历,如果bit[i]=1,则输出i到文件,当遍历完成,文件则已排好序。

    这个思路和桶排序一样,算法的关键是位向量。对于不支持bit数据结构的语言我们可以自己实现位操作,int是32位的,所以我们需要[1千万/32+1]个int类型存储,大约1.2M。(虽然差点不符合题目的要求,但是不失为一种更好的解题思路)。

    将第i位置为1的时候可以用如下操作:

    a[i/32] | (1 << (i%32)); 

    第i位肯定在i/32个int上,i%32是偏移量,然后通过按位或来将特定位置1。(不明白的可以了解一下位计算)

    为了计算速度更快,上述公式可以完全由位运算替代:

    a[i >>5] |= (1 << (i & 31));

    总结

    对于大的数量级的排序,基本思路是分而治之的思想,位向量方法虽然效率很高,但是要注意一些限制条件(数据不能重复、不适合稀疏的数据分布等)。

    编程珠玑中的例子是int型的数据排序,实际我们面临的问题可能不会这么简单,例如需要对复杂数据类型进行排序(对象),我们可以让对象实现compareTo,重写hashcode、equals等等。

  • 相关阅读:
    [hdu4631 Sad Love Story]最近点对,枚举
    [hdu4629 Burning]三角形面积并,扫描线
    [hdu4628 Pieces]二进制子状态,DP
    [hdu4627 The Unsolvable Problem]数论
    [hdu4622 Reincarnation]后缀数组
    [hdu5379 Mahjong tree]dfs计数
    [hdu5375 Gray code]DP
    决策树
    算法题解之位运算
    算法题解之滑动窗口
  • 原文地址:https://www.cnblogs.com/ouym/p/9361171.html
Copyright © 2020-2023  润新知