std :: is_sorted和比较器要求有误导性吗?

时间:2019-04-27 09:24:30

标签: c++ std

我在is_sorted上遇到了一个古老的问题:std::is_sorted and strictly less comparison?

在遇到用对比较器进行单调性检查未能通过测试的用例时,

。我以为如下所示的lambda符合要求:(仅当lhs和rhs的两个元素都已排序时)它会返回true

bool 
check_pair_sorted(std::vector<std::pair<int, int>>& vec)
{
    return std::is_sorted(vec.begin(), vec.end(),[](auto& lhs, auto& rhs){
            return (lhs.first < rhs.first) && (lhs.second < rhs.second);
            });
}

但是,如果我像这样分割支票,那么真正的预期功能是可能的

bool check_separate_sorted(std::vector<std::pair<int, int>>& vec)
{
    return std::is_sorted(vec.begin(), vec.end(),[](auto& lhs, auto& rhs){
           return (lhs.first < rhs.first) ; })
        && std::is_sorted(vec.begin(), vec.end(),[](auto& lhs, auto& rhs){ 
           return (lhs.second < rhs.second) ; });
}

看看上面的问题的答案,即建议较早返回false可能是首选的实现方式,是否也应同样提出要求?

  

comp-比较函数对象(即满足Compare要求的对象),如果第一个参数小于或等于(即,则返回 false ) (不是之前)。

我在这里订购时可能会遗漏一些东西,但目前似乎无法将其包裹住。

3 个答案:

答案 0 :(得分:2)

您的check_pair_sortedcheck_separate_sorted所做的事情有所不同,我想这就是混乱的根源。

这取决于std::is_sorted的定义方式。对于每两个元素a[i]a[j],其中i <j

  • 它检查a[j] < a[i]永远不是真的
  • 它不会检查a[i] < a[j]始终为真

(自然,聪明的算法可以避免进行所有O(n ^ 2)比较)

上面的两颗子弹不一样!

对于简单数字,如在另一个SO问题中一样,序列1 2 3 3 4 5满足第一个点,但不满足后者。

您的情况类似的情况。考虑两对的序列:{ {1,2}, {2,1} }。序列的元素不同,但是第一个lambda比较器无法比较它们-双向返回false。因此,出于该算法的目的,即使这两个元素不是严格相等的,也将它们视为等效

因此,is_sorted内的check_pair_sorted序列{ {1,2}, {2,1} } 返回true,因为它检查的是第一个项目符号点,而不是第二。

请注意,相同的等效问题可能会影响其他STL结构和算法。例如,如果您有一个std::set,则无法使用第一个Lambda作为比较器同时包含{1,2}{2,1}元素。

答案 1 :(得分:1)

std::is_sorted在比较函数-运算符<()或某些功能对象-在TS的示例中为lambda明确定义。

但是,如果以这种方式构造比较函数,则两个元素之间没有明确的关联-即 a b 都是 true -无法完全定义任何排序或排序操作的结果。

这是造成混乱的真正原因。

答案 2 :(得分:0)

对于词汇排序,您需要:

return (lhs.first < rhs.first) || ((lhs.first == rhs.first) && lhs.second < rhs.second));