You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建支持压缩的有序64位long型集合数据结构?

带压缩的有序Long型集合设计方案

针对你提出的倒排索引倒排列表场景——数值唯一有序、大量连续区间+少量跳跃,同时需要支持动态插入/删除、交并集操作且内存占用最小的需求,放弃单值红黑树,改用区间编码红黑树是最优解,以下是具体实现思路:

核心压缩逻辑:区间编码代替单值存储

不再用红黑树存储单个long值,而是存储连续数值区间,每个区间用(start: long, end: long)表示。比如你给出的示例序列1,2,3,1000,1001,1002,15001,15002,会被压缩为3个区间:(1,3)、(1000,1002)、(15001,15002),仅占用6个long的空间(原序列需8个),连续数值越多,压缩比越高。

动态操作的实现(基于区间红黑树)

红黑树的节点为区间对象,按start字段排序,平衡特性保证插入、删除、查找的时间复杂度为O(log n)(n为区间数量,远小于原序列长度)。

插入操作

  1. 查找候选区间:找到红黑树中start小于等于插入值x的最大区间(左邻区间),以及start大于x的最小区间(右邻区间)。
  2. 去重检查:如果x落在任一已有区间内(left.start <=x <=left.end),直接返回(数值唯一)。
  3. 合并左邻区间:若左邻区间存在且left.end +1 ==x,则将左邻区间更新为(left.start, x)。
  4. 合并右邻区间:若右邻区间存在且right.start -1 ==x,则将右邻区间(或合并后的左邻区间)更新为(new_start, right.end)。
  5. 新增区间:若无法合并左右区间,直接插入新节点(x,x)。

删除操作

  1. 定位目标区间:找到包含x的区间(start <=x <=end)。
  2. 单值区间处理:若区间start == end,直接删除该节点。
  3. 多值区间拆分:
    • 若x == start:将区间更新为(start+1, end)。
    • 若x == end:将区间更新为(start, end-1)。
    • 若x在区间中间:删除原区间,插入两个新区间(start, x-1)和(x+1, end)。

交并集操作优化

基于区间的特性,交并集操作无需遍历单个数值,直接通过区间的重叠/相邻判断完成,效率远高于单值集合:

交集操作

采用双指针遍历两个区间红黑树:

  1. 初始化指针p1(指向集合A的第一个区间)、p2(指向集合B的第一个区间)。
  2. 循环处理直到任一指针为空:
    • 计算重叠区间:overlap_start = max(p1.start, p2.start),overlap_end = min(p1.end, p2.end)。
    • 若overlap_start <= overlap_end,将该区间加入结果集合。
    • 移动end较小的指针:若p1.end < p2.end,p1移至下一个区间,否则p2移至下一个区间。

并集操作

同样用双指针遍历合并:

  1. 初始化指针p1、p2,结果集合为空。
  2. 每次取当前start更小的区间,将其与结果集合的最后一个区间尝试合并(重叠或last.end +1 == current.start则合并),更新结果集合。
  3. 重复直到所有区间处理完毕。

小规模序列适配优化

当集合元素极少(比如少于10个),区间编码的额外开销(每个区间2个long)可能超过单值存储的成本。此时可以做分层实现:

  • 元素数小于阈值时,用有序数组存储单值,插入/删除时通过二分查找定位,交并集直接遍历数组。
  • 元素数超过阈值时,自动转换为区间红黑树结构。

内存开销对比

以10万个连续数值为例:

  • 原数组:100000 * 8B = 800KB
  • 单值红黑树:100000个节点(每个节点含8B数值+24B左右树结构开销)≈ 3.2MB
  • 区间红黑树:仅1个节点(16B数值+24B树结构)≈ 40B,压缩效果极其显著。

内容的提问来源于stack exchange,提问作者namdosan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 20:55:52