我想在C ++ std::map
中有一个用户定义的密钥。键是具有最大值2^V
的整数集的二进制表示,因此我无法表示所有2^V
个可能的值。我是通过有效的二进制集表示来实现的,即uint64_t
。
现在的问题是,要将这个用户定义的bitset作为std::map
中的键,我需要定义bitset值之间的有效比较,但如果我的最大大小为,{{1}那么我无法得到一个我可以比较的数字,更不用说将它们全部聚合起来了,即V=1000
是不可表示的。
因此我的问题是,假设我有两个不同的集合(通过在我的bitset表示中设置正确的位)并且我不能代表最终的数字,因为它会溢出:
2^1000
是否有合适的转换可以产生我可以比较的价值?我需要能够说id_1 = 2^0 + 2^1 + ... + 2^V
id_2 = 2^0 + 2^1 + ... + 2^V
所以我想将指数之和转换为可表示的值,但保持“小于”的不变量。我正在考虑例如以巧妙的方式应用日志转换以保留“小于”。
以下是一个例子:
id_1 < id_2
完美!一般集可以有set_1 = {2,3,4}; set_2 = {8}
id(set_1) = 2^2 + 2^3 + 2^4 = 28; id(set_2) = 2^8 = 256
id(set_1) < id(set_2)
,因此{1,...,V}
可能的子集怎么样?
答案 0 :(得分:4)
我是通过有效的二进制集表示,即uint64_t数组来实现的。
假设通过密钥类型ra
的数据成员Key
访问此数组,并且两个数组的长度均为N
,那么您需要一个比较器,如下所示:< / p>
bool operator<(const Key &lhs, const Key &rhs) {
return std::lexicographical_compare(lhs.ra, &lhs.ra[N], rhs.ra, &rhs.ra[N]);
}
这隐含地认为数组是大端的,即第一个uint64_t
是最重要的。如果您不喜欢这样,这是公平的,因为您可能已经记住了将V
位存储到数组中的任何顺序的相对重要性。 lexicographical_compare
没有什么大不了的,所以只需查看an example implementation并根据需要进行修改。
这被称为“词典顺序”。除了我使用uint64_t
而不是char
并且两个数组长度相同的事实之外,它是比较字符串的方式[*] - 事实上使用uint64_t
并不重要,您可以在比较器中使用std::memcmp
而不是比较64位块。通过将整个字符串转换为整数,字符串的operator<
不起作用,比较器也不应该。
[*]直到您将特定于语言环境的整理规则付诸实践。