【发布时间】:2010-11-11 15:10:53
【问题描述】:
给定一系列索引(标识符),我想将每个索引映射到一个布尔值,即:
// interface pseudocode
interface bitmap {
bool identifier_is_set(unsigned int id_idx) const;
void set_identifier(unsigned int id_idx, bool val) const;
};
这样我就可以设置和查询每个 ID(索引)是否已设置,您希望使用什么来实现它?
我认为这称为位数组或位图或位集,如果我错了,请纠正我。
假设最大标识符是预先确定的,并且不大于 1e6 (1m),可能要小得多 (10k - 100k)。 (这意味着 sizeof(int)*maximum_id_idx 使用的大小很容易适合进入记忆。)
目前我看到的可能解决方案:
-
std::set<size_t>- 根据需要向该集合添加或删除标识符。只要我们有一个稀疏位图,这将允许任意大的标识符。 -
std::vector<bool>- 大小为适当的最大值,为每个 id_idx 存储 true 或 false。 -
std::vector<char>- 同样的事情,但没有遇到奇怪的std::vector<bool>问题。使用的内存比vector<int>少。 -
std::vector<int>- 使用int作为布尔标志来拥有使用机器自然字长的容器。 (不知道这是否会有所作为。)
请回答您更喜欢哪种容器类型以及原因,考虑到上面提到的最大 id 限制,特别是考虑到 查询位图的性能方面(插入性能无关紧要)。
注意:vector 与 set 的接口用法无关紧要,因为无论如何它都会隐藏在它的包装类后面。
编辑:添加关于 std::bitset 的讨论:std::bitset 会将整个数组大小合并到对象中,即 sizeof(std::bitset) 的大小约为 1 /8 兆字节,这构成了一个巨大的单个对象,并且构成了您无法再放入堆栈的东西(可能相关也可能不相关)。
【问题讨论】:
-
当性能很重要并且您最初无法做出“明显”的选择时,您必须运行测试来比较等效行为。
标签: c++ performance