C++ 当参数相等时,为什么std::sort compare函数必须返回false?
在std::sort中,您可以提供第三个参数,它是如何对列表进行排序的基础。如果希望第一个参数先出现,则返回true。如果希望第二个参数先出现,则返回false。我遇到了一个问题,即我的谓词函数被认为是一个“无效的比较器”,并且我已经将其缩小到不满足以下要求的事实:C++ 当参数相等时,为什么std::sort compare函数必须返回false?,c++,sorting,std,C++,Sorting,Std,在std::sort中,您可以提供第三个参数,它是如何对列表进行排序的基础。如果希望第一个参数先出现,则返回true。如果希望第二个参数先出现,则返回false。我遇到了一个问题,即我的谓词函数被认为是一个“无效的比较器”,并且我已经将其缩小到不满足以下要求的事实: if arg1 == arg2, compare function MUST return false. 我见过一些术语,比如std::sort要求“严格弱排序”。除了两个地方,我得到的关于这些主题的所有其他页面似乎都是技术论文,
if arg1 == arg2, compare function MUST return false.
我见过一些术语,比如std::sort要求“严格弱排序”。除了两个地方,我得到的关于这些主题的所有其他页面似乎都是技术论文,我无法理解。我能理解的是:
In weak ordering some elements "may be tied" with each other.
但对我来说,这也是“偏序集”的含义,即:
"there may be pairs of elements for which neither element precedes the other"
此外,我不明白“严格”在这两个词中意味着什么
撇开我对序理论术语的困惑不谈,我的问题是,在比较函数中,参数1和参数2是否相等,在这种情况下,我不在乎哪个在另一个之前(任何一个在前面都会让我高兴),为什么我不能返回true,让参数1先出现
我还想问我的程序如何知道它是一个无效的比较器,但我想它可能只是检查arg1和arg2在比较函数返回true时是否相等。比较函数只是模拟了一个“小于”运算符。考虑< <代码> 不深入数学,2个变量可以用“如果你愿意”来比较。但是,未指定
std::sort
使用的算法。通过使用不符合标准设置的要求的比较函数,您打破了算法的假设,并导致未定义的行为
< >看看在这个嘈杂的比较函数的输出中会发生什么,使用<代码> < P>解释Benjamin Lindley的答案,考虑STD::排序使用HORE类型分区方案的Quasr排序的典型情况。使用compare(value,pivot)扫描左侧的值
/// This is a helper function...
template<typename _RandomAccessIterator, typename _Tp, typename _Compare>
_RandomAccessIterator
__unguarded_partition(_RandomAccessIterator __first,
_RandomAccessIterator __last,
const _Tp& __pivot, _Compare __comp)
{
while (true)
{
while (__comp(*__first, __pivot))
++__first;
--__last;
while (__comp(__pivot, *__last))
--__last;
if (!(__first < __last))
return __first;
std::iter_swap(__first, __last);
++__first;
}
}
所以,若arg1==arg2,则compare函数必须返回false
您还可以看到>,Item21:总是让比较函数为相等值返回false。请注意,没有检查来验证您的比较器是否满足严格弱排序的要求。@raket1111:这是什么意思?如果实现愿意,可以自由地执行此类检查。事实上,一些现实生活中的实现确实做到了这一点。在我的VisualStudio中,它抛出一个异常,称为“无效的比较器”。我假设要么它显式地检查,要么排序算法中出现了错误并抛出它。@AnT真的吗?我的意思是,在一些实现中(比如gcc/clang),他们只是假设需求已经满足,如果没有满足,那么你会得到一些奇怪的顺序。@Rakete1111:不一定。如果未满足要求,则行为未定义。在现实生活中,它可以以多种方式表现出来,而不仅仅限于“某种奇怪的秩序”。它也很容易导致越界访问。为了防止这种情况,需要额外的检查,而AFAIK GCC/Clang并没有执行这些检查。所以我假设你观察到的那些“奇怪的命令”纯粹是运气造成的。在现实生活中,它也可能因为越界访问而崩溃。我不知道为什么这意味着我想要它。这是因为在下一步中,比较将基于相同的值,只是它们将被发送到参数相反的比较函数?@Zebrafish:这是定义上的。你似乎有点倒退:你不能按照你想要的方式实现它,然后告诉算法如何使用它——算法说“给我一个严格的排序谓词”,然后你实现它。在严格的排序中,当a==a时,f(a,a)==false。将比较改为
124: 2@12 <= 4@7
37: 0@0 <= 0@-1
38: 0@0 <= 144@-2
39: 0@0 <= 0@-3
40: 0@0 <= 192@-4
/// This is a helper function...
template<typename _RandomAccessIterator, typename _Tp, typename _Compare>
_RandomAccessIterator
__unguarded_partition(_RandomAccessIterator __first,
_RandomAccessIterator __last,
const _Tp& __pivot, _Compare __comp)
{
while (true)
{
while (__comp(*__first, __pivot))
++__first;
--__last;
while (__comp(__pivot, *__last))
--__last;
if (!(__first < __last))
return __first;
std::iter_swap(__first, __last);
++__first;
}
}
while (__comp(*__first, __pivot))
++__first;