快速、小巧、简单的位图上的排名/选择
1 位图上的 Rank和 Select查询的重要性
位图(bitmap)上的 Rank和 Select查询对于构建各种紧凑型数据结构至关重要。Rank查询返回在位图的前i个位置中有多少个特定的位(通常是1),而Select查询则返回第j个特定位(通常是1)的位置。这些操作在许多应用中都有重要作用,例如树结构的模拟、字符串索引、文本压缩等。
理论上,Rank和Select查询可以在常数时间内完成,只需额外使用o(n)个比特的空间,或在压缩位图上使用nH0(B)+o(n)个比特的空间。然而,实际应用中,这些理论结果的实现并不总是简单或高效。本文将介绍两种新的结构,旨在弥合理论与实践之间的差距,提供高效且易于实现的解决方案。
2 理论与实践的差距
尽管理论上Rank和Select查询可以在常数时间内完成,但实际应用中,Select查询的实现通常较为复杂,且需要更多的空间开销。例如,原始的常数时间Select解决方案需要超过60%的额外空间,这在实际应用中是不可接受的。此外,Select查询的实现通常比Rank查询复杂,导致性能上的差异。
为了解决这些问题,本文提出两种新的结构:一种用于明文形式的位图,另一种用于压缩形式的位图。这两种结构不仅易于实现,而且大大降低了空间开销,同时为Rank和Select查询提供了出色的时间性能。
3 新结构的提出
3.1 明文形式的位图结构
对于明文形式的位图,我们提出了一种新的结构,它在Select操作上比以往的结构更小更快,而在Rank操作上与最佳的类似大小的先前结构具有竞争力。具体来说,该结构通过以下方式实现:
- 采样 :对位图进行均匀采样,记录每个采样点的Rank值。
- 查找表 :使用查找表加速Select查询,查找表记录了每个采样点之间的Select值。
- 二分查找 :在查找表中使用二分查找快速定位目标位置。
这种结构的优点在于,它只需要位图上额外3%的空间,就能在0.2微秒内完成Rank和Select查询。
3.2 压缩形式的位图结构
对于压缩形式的位图,我们提出了一种新的结构,它通过即时生成通用表来替代传统的通用表,从而减少了空间开销。具体来说,该结构通过以下方式实现:
- 块划分 :将位图划分为长度为t的块,每个块根据其类别(即包含1的数量)进行编码。
- 即时生成 :在查询时即时生成通用表,而不是预先计算并存储通用表。
- 超级块 :将多个块组合成超级块,每个超级块存储其开始处的Rank值和指向其索引开始位置的指针。
这种结构的优点在于,它只需要位图上额外10%的空间,就能在0.4微秒内完成Rank查询,在1微秒内完成Select查询。
4 实验结果
为了验证新结构的有效性,我们进行了广泛的实验。实验结果表明,新结构在空间和时间性能上都优于现有方法。以下是实验结果的总结:
| 结构 | 空间开销 | Rank查询时间(微秒) | Select查询时间(微秒) |
|---|---|---|---|
| 明文形式 | 3% | 0.2 | 0.2 |
| 压缩形式 | 10% | 0.4 | 1 |
此外,我们还展示了新结构在实际应用中的优势。例如,在FM索引的实现中,使用新结构的索引比原始实现减少了16%的空间,同时查询时间保持在90微秒以内。
5 应用实例
5.1 FM索引
FM索引是一种用于压缩文本集合的数据结构,它通过一系列Rank操作来计算模式P在T中出现的次数。我们使用新结构重新实现了FM索引,并对其性能进行了评估。结果显示,新结构不仅减少了空间开销,还提高了查询效率。
5.2 树的紧凑表示
树的紧凑表示是另一个应用实例。通过使用新结构替换原有的Rank/Select结构,我们成功地减少了空间开销,并提高了查询效率。具体来说,我们对7200万个节点的“后缀树”进行了实验,结果显示,新结构比原有结构减少了20%的空间开销,同时查询时间保持在0.4微秒以内。
graph TD;
A[位图] --> B[明文形式];
A --> C[压缩形式];
B --> D[采样];
B --> E[查找表];
B --> F[二分查找];
C --> G[块划分];
C --> H[即时生成];
C --> I[超级块];
以上内容展示了新结构在位图上的Rank和Select查询中的应用和优势。接下来,我们将深入探讨新结构的具体实现细节。
6 明文形式位图结构的具体实现
6.1 采样策略
在明文形式的位图结构中,采样策略是核心之一。我们采用了一种均匀采样的方法,每隔Sr个位置记录一次Rank值。这种采样方法不仅能有效减少空间开销,还能保证查询的准确性。具体步骤如下:
- 初始化 :设定采样间隔Sr,初始化一个数组R,用于存储采样点的Rank值。
- 采样 :遍历位图,每隔Sr个位置记录一次当前的Rank值到数组R中。
- 查询 :在查询Rank值时,先通过二分查找找到最接近目标位置的采样点,再通过线性扫描完成剩余部分的Rank计算。
6.2 查找表的构建
查找表用于加速Select查询,记录了每个采样点之间的Select值。查找表的构建过程如下:
- 初始化 :设定采样间隔Ss,初始化一个二维数组S,用于存储每个采样点之间的Select值。
- 填充 :遍历位图,对于每个采样点,计算其与下一个采样点之间的Select值,并存储到数组S中。
- 查询 :在查询Select值时,先通过二分查找找到最接近目标位置的采样点,再通过查找表S快速定位目标位置。
6.3 二分查找的优化
为了进一步提高查询效率,我们在二分查找中引入了一些优化措施:
- 预处理 :提前计算每个采样点的Rank值和Select值,减少查询时的计算量。
- 缓存 :使用缓存机制保存最近查询的结果,避免重复计算。
- 剪枝 :在查找过程中,根据已知信息提前终止不必要的搜索路径。
7 压缩形式位图结构的具体实现
7.1 块划分与编码
在压缩形式的位图结构中,块划分和编码是关键步骤。我们将位图划分为长度为t的块,并根据每个块中1的数量进行编码。具体步骤如下:
- 初始化 :设定块长度t,初始化一个数组K用于存储每个块的类别,数组R用于存储每个块的索引。
- 划分 :遍历位图,将位图划分为长度为t的块。
- 编码 :对于每个块,根据其类别(即包含1的数量)进行编码,并将编码结果存储到数组K和R中。
7.2 即时生成通用表
为了避免传统通用表带来的空间开销,我们采用即时生成通用表的方法。具体步骤如下:
- 初始化 :设定块长度t,初始化一个函数f,用于即时生成通用表。
- 查询 :在查询时,根据当前块的类别和索引,调用函数f即时生成通用表。
- 使用 :使用即时生成的通用表完成Rank和Select查询。
7.3 超级块的构建
超级块的构建是为了进一步优化查询效率。我们将多个块组合成超级块,并在每个超级块中存储其开始处的Rank值和指向其索引开始位置的指针。具体步骤如下:
- 初始化 :设定超级块长度s,初始化一个数组SP用于存储每个超级块的起始Rank值,数组SPR用于存储每个超级块的索引指针。
- 构建 :遍历位图,将多个块组合成超级块,并将起始Rank值和索引指针存储到数组SP和SPR中。
- 查询 :在查询时,先通过超级块的起始Rank值和索引指针快速定位目标块,再通过块内的Rank和Select查询完成最终结果。
8 空间和时间性能的优化
8.1 空间开销的优化
为了进一步优化空间开销,我们采取了以下措施:
- 减少采样间隔 :适当减少采样间隔Sr和Ss,可以在不影响查询准确性的前提下减少空间开销。
- 优化查找表 :通过减少查找表的维度或使用更紧凑的数据结构,可以有效减少查找表的空间开销。
- 压缩索引 :对索引数据进行压缩,可以进一步减少空间开销。
8.2 时间性能的优化
为了进一步优化时间性能,我们采取了以下措施:
- 并行处理 :通过并行处理多个查询请求,可以显著提高查询效率。
- 缓存机制 :使用缓存机制保存最近查询的结果,避免重复计算。
- 剪枝策略 :在查询过程中,根据已知信息提前终止不必要的搜索路径。
9 实际应用中的优势
9.1 FM索引的优化
在FM索引的实现中,使用新结构不仅减少了空间开销,还提高了查询效率。具体来说,新结构通过以下方式优化了FM索引:
- 减少空间开销 :通过减少采样间隔和优化查找表,新结构减少了FM索引的空间开销。
- 提高查询效率 :通过并行处理和缓存机制,新结构显著提高了FM索引的查询效率。
9.2 树的紧凑表示的优化
在树的紧凑表示中,使用新结构不仅减少了空间开销,还提高了查询效率。具体来说,新结构通过以下方式优化了树的紧凑表示:
- 减少空间开销 :通过减少采样间隔和优化查找表,新结构减少了树的紧凑表示的空间开销。
- 提高查询效率 :通过并行处理和缓存机制,新结构显著提高了树的紧凑表示的查询效率。
graph TD;
A[位图] --> B[明文形式];
A --> C[压缩形式];
B --> D[采样];
B --> E[查找表];
B --> F[二分查找];
C --> G[块划分];
C --> H[即时生成];
C --> I[超级块];
D --> J[减少采样间隔];
E --> K[优化查找表];
I --> L[减少采样间隔];
I --> M[优化查找表];
J --> N[减少空间开销];
K --> O[减少空间开销];
L --> P[减少空间开销];
M --> Q[减少空间开销];
通过上述优化措施,新结构在实际应用中表现出色,不仅减少了空间开销,还提高了查询效率。这些优化措施为紧凑型数据结构的实际应用提供了有力支持。
超级会员免费看
5073

被折叠的 条评论
为什么被折叠?



