问题描述
我正在尝试用 C++ 编写一个自定义比较器来对向量进行排序。为了简单起见,我会说我的排序标准是所有偶数值都应该在所有奇数值之前,我正在尝试为此编写一个自定义比较器。但我需要确保保留所有偶数元素和所有奇数元素的相对顺序。
我正在使用此代码:
bool mysort(int arg1,int arg2){
return arg1%2==0;
}
int main(){
vector<int> v({1,3,2,4,5,7,9,6,8,11,10,12});
stable_sort(v.begin(),v.end(),mysort);
for(int i=0;i<v.size();i++){
cout<<v[i]<<" ";
}
return 0;
}
根据我的理解,当 mysort() 返回 true 时,这意味着允许第一个参数 (arg1
) 在第二个参数 (arg2
) 之前。这就是我在比较器中使用 return arg1%2==0;
的原因。
但我得到的输出是 12 10 8 6 4 2 1 3 5 7 9 11
。这意味着,偶数元素的相对顺序是相反的。同时,保留奇数元素的相对顺序。
相反,如果我在 return i%2==0 && j%2!=0;
比较器中使用 mysort()
,我得到的输出是 2 4 6 8 10 12 1 3 5 7 9 11
。它保留了所有奇数和偶数元素的相对顺序。
为什么会出现这种行为?编写自定义比较器并保留相似元素的相对顺序的最佳方法是什么?提前致谢。
解决方法
我相信您知道,stable_sort
保留比较相等的元素的顺序。为此,当 mysort (i,j)
和 mysort (j,i)
比较相等时,false
和 i
都必须返回 j
。 (当然,它也必须在 true
时返回 i < j
。)
因此,您必须在 arg1 % 2
中同时测试 arg2 % 2
和 mysort
才能履行此合约,而 return arg1 % 2 == 0 && arg2 % 2 != 0;
正是您想要的:它将返回 {{ 1}} 当 false
和 arg1 % 2
比较相等时,无论参数传递给它的顺序如何。
sort
和 stable_sort
的比较器必须引入一个严格弱序。您的比较器不满足此条件。
严格弱顺序的一个属性是,对于 i
和 j
的任何允许值,至多 mysort(i,j)
和 {{ 1}} 可以返回 mysort(j,i)
。您的比较器在两种情况下都返回 true
,例如,true
和 i=2
。
要解决此问题,您必须修改比较器。 j=4
何时“小于”arg1
?只有一种情况:当 arg2
为偶数而 arg1
为奇数时。因此,一个可用的定义是:
arg2
顺便说一句,当您定义一个比较器时,您没有时间考虑算法将按什么顺序传递参数。所有(之前,之后)的讨论都是无关紧要的。该算法将按照它喜欢的顺序传递参数。没有任何保证。
,STL 使用小于比较,这意味着 std::stable_sort() 将以相反的顺序传递参数,它将调用 mysort(later_object,early object),因此如果 later_object = early_object 则为 false(将 early_object 复制到合并输出)。