简体   繁体   中英

Stable sorting a vector using std::sort

So I have some code like this, I want to sort the vector based on id and put the last overridden element first:

struct Data {
  int64_t id;
  double value;
};
std::vector<Data> v;

// add some Datas to v
// add some 'override' Datas with duplicated `id`s

std::sort(v.begin(), v.end(),
  [](const Data& a, const Data& b) {
    if (a.id < b.id) {
      return true;
    } else if (b.id < a.id) {
      return false;
    }
    return &a > &b;
});

Since vectors are contiguous, &a > &b should work to put the appended overrides first in the sorted vector, which should be equivalent to using std::stable_sort , but I am not sure if there is a state in the std::sort implementation where the equal values would be swapped such that the address of an element that appeared later in the original vector is earlier now. I don't want to use stable_sort because it is significantly slower for my use case. I have also considered adding a field to the struct that keeps track of the original index, but I will need to copy the vector for that.

It seems to work here: https://onlinegdb.com/Hk8z1giqX

std::sort gives no guarantees whatsoever on when elements are compared, and in practice, I strongly suspect most implementations will misbehave for your comparator.

The common std::sort implementation is either plain quicksort or a hybrid sort (quicksort switching to a different sort for small ranges), implemented in-place to avoid using extra memory. As such, the comparator will be invoked with the same element at different memory addresses as the sort progresses; you can't use memory addresses to implement a stable sort.

Either add the necessary info to make the sort innately stable (eg the suggested initial index value) or use std::stable_sort . Using memory addresses to stabilize the sort won't work.

For the record, having experimented a bit, I suspect your test case is too small to trigger the issue. At a guess, the hybrid sorting strategy works coincidentally for smallish vector s, but breaks down when the vector gets large enough for an actual quicksort to occur. Once I increase your vector size with some more filler, the stability disappears, Try it online!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM