I am trying to write a custom comparator in C++ to sort a vector. For the sake of simplicity, I will say my sorting criteria is that all even values should come before all odd values and I am trying to write a custom comparator for this. But I need to make sure that the relative order of all even elements and all odd elements is preserved.
I am using this code:
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;
}
Based on what I understand, when mysort() returns true, it means first argument (arg1
) is allowed to be before the second argument (arg2
). That why I have used return arg1%2==0;
in the comparator.
But the output I get is 12 10 8 6 4 2 1 3 5 7 9 11
. Which means, relative order of even elements is reversed. While, relative order of odd elements is preserved.
Instead, if I use return i%2==0 && j%2!=0;
in mysort()
comparator, the output I get is 2 4 6 8 10 12 1 3 5 7 9 11
. Which preserves the relative order of all odd and even elements.
Why is this behavior? And what is the best way to write a custom comparator with preserving relative order of similar elements? Thank you in advance.
The comparator for
sort
andstable_sort
must induce a strict weak order. Your comparator does not satisfy this condition.One of the properties of a strict weak order is that for any permitted values of
i
andj
, at most one ofmysort(i,j)
andmysort(j,i)
can returntrue
. Your comparator returnstrue
for both cases when, e.g.,i=2
andj=4
.To fix that, you must modify your comparator. When is
arg1
"less" thanarg2
? There is only one case: Whenarg1
is even andarg2
is odd. Hence, a usable definition would be:BTW, when you define a comparator, you have at no time to think about in which order the algorithm will pass the parameters. All the (earlier, later) discussions are irrelevant. The algorithm will pass parameters in which ever order it likes. There are no guarantees.