【发布时间】:2011-06-10 04:45:24
【问题描述】:
有没有一种方法可以迭代(可能很大)std::bitset,它在 设置为 true 的位数中线性?我想避免检查位集中的每个位置。迭代应该连续返回每个设置为 true 的位的索引。
【问题讨论】:
标签: c++ algorithm data-structures iteration bitset
有没有一种方法可以迭代(可能很大)std::bitset,它在 设置为 true 的位数中线性?我想避免检查位集中的每个位置。迭代应该连续返回每个设置为 true 的位的索引。
【问题讨论】:
标签: c++ algorithm data-structures iteration bitset
标准位向量不支持对真实位进行有效迭代 - 运行时间始终为 O(n),其中 n 是总位数,与 k 无关。但是,有专门的数据结构,如 van Emde Boas trees 和 y-fast tries,支持在时间 O(k lg lg n) 内对比特进行迭代,其中 n 是比特数,k 是真实比特数。
【讨论】:
为了使其成为线性,您需要一个链表/数组/索引集设置为 true。保留这样的二级索引不是 std::bitset 要求的性能/存储权衡的一部分,并且如果没有您的特定要求,它会使每个人都处于不利地位,因此实现无法提供这一点。你可以考虑自己用这样的容器来补充你的 bitset,或者使用 boost 的多索引容器库。
【讨论】:
您可以使用 u64 累加器和 32 条目表一次最多检查 32 位
u32 kTable[]
{
0x01, 0x03, 0x07, 0x0F ..., 0xFFFFFFFF
};
只需将 32 位读入 u64 累加器并根据偏移量将其向下移动,然后对照表检查您的位。您可以以二进制方式执行此操作,以使比较次数最多为 5。对于时尚非“线性”的数据,这将变慢。然后这成为日志时间。
【讨论】:
只有两个选项在总位数上比 O(N) 好得多:
【讨论】:
有时人们使用run-length encoding 来处理类似的事情。如果将传入的位集编码为一个运行长度数组,那么最终的运行次数不会超过设置位和清除位之间的转换次数,最多为2*k。此外,在许多应用程序中,转换次数远少于k,因此除了线性最坏情况之外,您还可以获得出色的平均时间性能。
此外,添加一个数据结构很简单,它可以让您有效地搜索诸如“数组中以nth 位置开始的下一个设置位”:只需构建一个运行长度的scan。
【讨论】:
遍历整个位集并简单地检查值并存储索引,如果为真,则为线性。您可以使用查找表加快速度。请参阅此代码:
【讨论】: