【问题标题】:Invalid < operator assertion in sort排序中无效的 < 运算符断言
【发布时间】:2012-09-23 02:35:27
【问题描述】:

我正在尝试实现一个简单的比较器,用于根据数组“_vec”中的值对索引进行排序。我收到“无效的

class Compare{
vector<int>& _vec;
public:
    Compare(vector<int>& vec) : _vec(vec) {}
    bool operator()(size_t i, size_t j){
        if(_vec[i] != _vec[j])
        return _vec[i] < _vec[j];
        else
        return (double)rand()/RAND_MAX < 0.5; 
    }
};

我正在使用以下函数调用:

sort(inds.begin(),inds.end(),Compare(vals));

其中 inds 只是一个包含从 1 到 15(比如说)的索引的数组,而 vals 是长度为 15 的数组,其中包含一些我想要计算其排序索引的值。总体目标是在 vals 中的两个(或更多)条目相等时随机化排序顺序。有什么帮助吗?

【问题讨论】:

  • 您应该使用尾随下划线(或其他东西来区分这些)instead of leading underscores
  • @Brian:因为这些不是文件范围,并且下划线后面没有大写字符,所以只要不保留它们就可以了。尽管如此,这个领域还是会引起足够的混乱,以至于另一种命名约定可能会让一些人更开心。
  • 请注意 - 如果 vals 的长度为 15,那么 inds 最好包含 [0..14] 范围内的索引,而不是 [1..15]。
  • C++98 标准说:§17.4.3.1.2 全局名称 [lib.global.names] 某些名称和函数签名集总是保留给实现: - 每个包含双下划线 (__) 或以下划线开头后跟大写字母 (2.11) 的名称都保留给实现以供任何使用。 — 每个以下划线开头的名称都保留给实现用作全局命名空间中的名称。 最后一个项目符号后的脚注 165 说 此类名称也保留在命名空间 ::std (17.4 .3.1)。 我认为规则没有改变。

标签: c++ sorting operator-keyword assertion


【解决方案1】:

std::sort() 期望比较操作是稳定的 - 如果在比较两个项目时返回特定结果,如果稍后再次比较这些项目,则比较必须返回相同的结果。当你返回一个随机值时,显然这不一定会成立。

C++03 25.3/4《排序及相关操作》说:

如果我们将 equiv(a, b) 定义为 !comp(a, b) && !comp(b, a),那么 要求是 comp 和 equiv 都是传递关系:

  • comp(a, b) && comp(b, c) 隐含 comp(a, c)
  • equiv(a, b) && equiv(b, c) 隐含 equiv(a, c)

[注:在这些条件下,可以证明

  • equiv 是等价关系
  • comp 在由 equiv 确定的等价类上引入明确定义的关系
  • 诱导关系是严格的全序。

——尾注]

为了澄清,表 28 定义了一个等价关系:

==是等价关系,即满足如下 属性:

  • 对于所有 a,a == a。
  • 如果 a == b,则 b == a。

所以你的Compare() 操作不会产生等价关系。

获得断言而不是随机丢失数据是一种很好的方式。

_vec 中的两个(或更多)条目相等时,解决随机排序问题的一种方法是为这些索引组成一个随机值,并在 index = 的映射中跟踪这些随机值> 随机值什么的。只需确保您跟踪并使用这些随机值,使Compare() 的传递和等价属性保持不变。

【讨论】:

  • 谢谢迈克尔。我现在明白问题所在了。根据您的建议,我找到了一种解决方法:我现在将一个随机数向量(长度为 15)传递给 Compare(),用于在两个值相等时打破平局。这样,Compare() 的传递性和等价性就成立了。
【解决方案2】:

std::sort 期望您的小于运算符提供传递 关系,即当排序看到A &lt; B 为真且B &lt; C 为真时,它暗示 A &lt; C 也是如此。

在您的实现中,传递性规则不成立:当两个项目相等时,您随机告诉排序其中一个大于另一个。这会触发调试断言。

对于相等的值返回 false 来解决这个问题。

【讨论】:

  • 这可以使用standatd库提供的operator&lt; for std::vector轻松实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-21
  • 2012-07-19
  • 1970-01-01
  • 2013-04-11
  • 2021-06-03
  • 1970-01-01
相关资源
最近更新 更多