对于我的用例,最有效的位向量压缩方法是什么?

时间:2011-01-22 15:41:21

标签: c compression bitmap indexing bit-manipulation


我正在研究计算生物学项目,我需要存储许多序列之间不同的基因座索引。现在,我正在使用B +树来实现这个目的,但我想使用位图索引对于这样一个用例来说会更快:两个序列之间只有少量基因座不同,平均为1%,并且它们沿序列分布几乎相等;所以似乎有很大的位图索引压缩空间。 我的问题是我无法找到一种可以有效的压缩方法:

  • 允许快速个别位设置/取消设置
  • 允许对位图进行有效范围查询
  • 可能允许两个索引的快速异或/和

提前获取您的建议。

2 个答案:

答案 0 :(得分:2)

查看FastBit:

https://sdm.lbl.gov/fastbit/

答案 1 :(得分:0)

您可以使用这样的简单树数据结构:

struct node {
    node * leftChild;
    node * rightChild;
    long mask;
};
struct tree {
    int exponent; // the size of the tree is 2^exponent
    node rootNode;
};

每个节点表示大位阵列的子阵列,其为(2 ^ n)* sizeof(长)位,n> = 0。如果叶子节点位于树的底部,则它们会在“掩码”中存储原始位掩码,否则它们会在“掩码”中存储0。这样,“掩码”值为0的叶节点可以表示位数组中的(2 ^ n)* sizeof(长)大小的空区域,因此可以有效地存储稀疏位数组。

leftChild和rightChild在所有叶节点中当然都是null。每个其他节点都有一个leftChild和rightChild指针,并且每个不是叶子节点的节点都至少有一个带有掩码的子节点,其中的掩码设置在其中。

要找到给定索引的位:

bool find_bit_at_index(tree t, long ind) {
    long divider = 1 << (t.exponent - 1);
    node *n = &t.rootNode;
    node *lastNode;
    while (n)
    {
       lastNode = n;
       if (ind >= divider) {
          n = n->rightChild;
          ind -= divider;
       }
       else {
          n = n->leftChild;
       }
       divider >>= 1;
    }
    return lastNode->mask & (1 << ind);
}

一旦理解了这个想法,构建树和开发其余算法应该很容易。我实际上没有测试过代码,因为这不是一个完整的解决方案,可能会留下一些拼写错误。而且我不是位图索引专家,可能(可能是)现成的包可以做得更好,但这个解决方案很简单,应该相对有效。与仅仅一个普通的位数组相比,1%可能还不够稀疏以使其更好(假设longs每个存储64位,平均多于一个位设置不超过2个长度),但是如果稀疏度增加超出节省的空间和时间。