我想使用multiset
来计算一些自定义键。密钥在数字上是不可比的,比较两个密钥并不意味着什么,但可以检查它们的相等性。
我看到multiset
模板需要Compare
来订购多重集。订单对我来说并不重要,只有重要性才算重要。如果我完全省略Compare
会发生什么? multiset对我的自定义键没有任何问题吗?如果我不能使用std::multiset
我的替代方案是什么?
答案 0 :(得分:4)
如果您只能比较密钥是否相等,则无法使用std::multiset
。对于关联容器,您的密钥类型必须具有由比较操作强加的严格弱排序。
严格弱排序不一定必须是数字。
[在关联容器中使用时,实际上并不需要进行相等比较。关键等价由!compare(a, b) && !compare(b, a)
确定。]
如果确实无法定义键的排序,那么您唯一的选择是使用键值对的序列容器并使用线性搜索进行查找。毋庸置疑,与multiset
相比,设置类似操作的效率会降低,因此如果可能的话,您可能会尽力创建排序。
答案 1 :(得分:2)
如果您完全省略Compare
,它将获得默认值,即less
(它会将<
运算符的结果应用于您的密钥) - 这可能是可能甚至没有编译你的密钥。
进行排序的原因是它允许实现通过其键更快地查找元素(插入,删除等时),为了理解原因,想象在字典中查找单词。传统词典使用字母顺序,这使得单词易于查找。如果你正在准备一本不易订购的语言的字典 - 比如一种象形语言 - 那么要么很难在其中找到单词(你必须搜索整个字典)或者你试图找到一种合理的方式来订购它们(例如,通过首先用一个笔划绘制所有可以绘制的图片,然后是两行等等) - 因为即使这个订单完全是任意,它会使字典中的条目更有效率。
同样,即使您的钥匙不是为了您自己的目的而订购,也没有任何自然顺序,您通常可以定义一个足以解决这些问题的订单。排序必须是可传递的(如果a<b
和b<c
然后a<c
),而严格(永远不会对a<a
返回true),非对称(a<b
和{{ 1}}永远都不是真的)。理想情况下,它应该排序所有元素(如果b>a
和a
不同于b
或a<b
),尽管你可以逃脱不真实(即strict weak ordering) - 虽然这相当技术性。
事实上,也许最明显的用途是极少数情况下完全无法订购物品 - 在这种情况下,您可以提供一个始终返回false的比较运算符。这很可能会导致性能不佳,但至少会正常运行。
答案 2 :(得分:2)
如果您没有严格的弱排序,则无法使用std::multiset
。您的选择是:
对您的数据施加严格弱的排序。如果您的密钥是“线性”数据结构,通常按字典顺序进行比较是个好主意。
使用等效的无序容器,例如boost::unordered_multiset
。为此,您需要使自定义数据类型可散列,这通常比强加某种订单更容易。
答案 3 :(得分:0)
因此,您列出了两个重要标准。
和一个假设,
multiset
这一事实意味着有很多实例那么,为什么不使用std::vector
或std::deque
或std::list
?那么你可以利用各种可以使用相等性检查的算法(例如count_if
等)。