[算法] 位图排序

初始化于: 2013-09-10

更新: 2013-09-18

《编程珠玑(第2版)》第1章 开篇

问题描述:

输入: 一个最多包含n个正整数的文件, 每个数都小于n, 且n=10^7. 如果在输入文件中有任何整数重复出现就是致使错误. 没有其他数据与该整数相关联.

输出: 按升序排列的输入整数的列表.

约束: 最多有(大约)1MB的内存空间可用, 有充足的磁盘存储空间可用. 运行时间最多几分钟, 运行时间为10秒就不需要进一步优化了.

位图数据结构: 该数据结构描述了一个有限定义域内(有范围)的稠密集合, 其中的每一个元素最多出现一次(不重复)并且没有其他任何数据与该元素相关联. 即使这些条件没有完全满足(例如, 存在重复元素或额外的数据), 也可以用有限定义域内的键作为一个表项更复杂的表格的索引.

三个阶段:

  1. 将所有的位都置为0, 从而将集合初始化为空.
  2. 通过读入文件中的每个整数来建立集合, 将每个对应的位置都置为1.
  3. 检验每一位, 如果该位为1, 就输出对应的整数, 由此产生有序的输出文件.

问题: 找出1到10^7中没有出现的两个数字

这个没啥好想的了...这里主要是了解bitarray模块的使用, 顺便与bitstring模块进行比较. bitstring模块速度比bitarray模块慢很多, 内存占用也比较多.

#--coding: utf8 --
from bitarray import bitarray
def use_bitarray(seq):
    ba = bitarray(10000000)
    ba.setall(0)
    for i in seq:
        ba[i] = 1
    for i in range(1, len(ba.to01())):
        if ba[i] == 0:
            print(i)

from bitstring import BitArray
def use_bitstring(seq):
    BA = BitArray(length=10000000)
    for i in seq:
        BA.set(1, i)
    for i in range(1, len(BA)):
        if BA[i] == 0:
            print(i)

# 初始化10w个数, 打乱, 移除两个数
import random
seq = [i for i in range(10000000)]
random.shuffle(seq)
seq.pop()
seq.pop()

import cProfile
cProfile.run('use_bitarray(seq)') # 8.063 seconds
cProfile.run('use_bitstring(seq)') # 169.849 seconds

相关文章:

程序员编程艺术:第十章、如何给10^7个数据量的磁盘文件排序

【编程珠玑】位图排序