我正在寻找一个合适的结构来处理以下问题:
- 应用程序正在接收(例如从 Web 服务器)可变大小数据的页面 Pi,例如页面 P1 可以包含 20 个元素,P2 3、P3 20、P4 20 等...
- 每个页面包含具有全局唯一递减 Id j 的元素 Tj,例如 P2=[T150, T149, T120]。在此示例中,P1 Tj 元素 ID 将严格低于 120,P3 元素将严格大于 150。
- 这意味着 Pi 中的 i 不代表网络接收顺序,而是最终的页面顺序,当我们接收到页面时它是未知的,并且在插入新页面时会发生变化。
这些页面可以按任何顺序接收。一组页面 P1..P10 的示例:
- 先 P3 然后 P2 然后 P1
- 然后 P6 然后 P5 然后 P4
- 然后 P10 然后 P9
- 然后是 P8,然后是 P7(注意 P10 和 P9 将是插入这些页面之前的第 8 页和第 9 页)。
我想找到一个允许我执行以下操作的结构:
- 在页面序列的中间、结尾或开头的任何位置插入新页面(例如在 P9 和 P6 之间插入 P8 和 P7),因此根据内部 Tj 元素。但我正在寻找比 O(n) 更好的复杂性。
- 删除页面也很好。
- 有趣的部分是查询:我希望能够根据间隔进行查询:例如从第 15 个元素到第 25 个元素。在首先呈现的示例中,我将检索 P1 的最后 5 个元素 + P2 的 3 + P3 的两个第一个元素。当然,在这里,我也期待比 O(n) 更好的复杂性......
基本上,我想要实现的是在收到推文时有效地将它们存储在内存页面中(推特时间线)。我当然可以使用数组或链接列表,但这意味着 O(n) 插入和查询时间......当然我需要能够根据它们在列表中的“位置”来查询项目以显示它们在列表视图中。
我想了一些解决方案,但没有一个是合适的:
- 首先,区间树,但它们允许插入和查询“相同范围”的元素,即插入“j”但查询“j”而不是“i”。不确定我是否可以根据“i”向它附加一种前缀总和。
- 我想的是使用 Fenwick 树来存储项目页数的累积总和,Pi 中的 i 是树中的“位置”,它表示与值 Tj 关联的键。但是 Fenwwick 树不适合插入新元素......我想知道是否可以用红黑树实现 Fenwick 树,但我不确定......
- 另一种解决方案可能是摆脱页面并在我猜的一种 B-tree 中直接插入元素。但是如果我想一次插入一个包含许多元素的页面,我有点担心速度。
我希望我的问题得到明确说明。关于可扩展的可能有效解决方案的任何想法?
编辑:我想查询的页面不是内部项目 ID(例如 T140、T150 或其他任何东西),而是元素(即 Tweet)索引。例如,在我的第一个示例中,T120 将是第 21 个项目(因为页面 P1 有 20 个元素)。所以我希望能够查询一个区间 [20-29],它应该返回元素 [T120, ...]。我不想直接搜索120。