使用自定义比较器时如何在 C++ 中执行稳定排序?

问题描述

我正在尝试用 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) 比较相等时,falsei 都必须返回 j。 (当然,它也必须在 true 时返回 i < j。)

因此,您必须在 arg1 % 2 中同时测试 arg2 % 2mysort 才能履行此合约,而 return arg1 % 2 == 0 && arg2 % 2 != 0; 正是您想要的:它将返回 {{ 1}} 当 falsearg1 % 2 比较相等时,无论参数传递给它的顺序如何。

,

sortstable_sort 的比较器必须引入一个严格弱序。您的比较器不满足此条件。

严格弱顺序的一个属性是,对于 ij 的任何允许值,至多 mysort(i,j) 和 {{ 1}} 可以返回 mysort(j,i)。您的比较器在两种情况下都返回 true,例如,truei=2

要解决此问题,您必须修改比较器。 j=4 何时“小于”arg1?只有一种情况:当 arg2 为偶数而 arg1 为奇数时。因此,一个可用的定义是:

arg2

顺便说一句,当您定义一个比较器时,您没有时间考虑算法将按什么顺序传递参数。所有(之前,之后)的讨论都是无关紧要的。该算法将按照它喜欢的顺序传递参数。没有任何保证。

,

STL 使用小于比较,这意味着 std::stable_sort() 将以相反的顺序传递参数,它将调用 mysort(later_object,early object),因此如果 later_object = early_object 则为 false(将 early_object 复制到合并输出)。