使用std :: sort稳定对向量进行排序

时间:2018-10-10 03:11:54

标签: c++

所以我有这样的代码,我想基于id对向量进行排序,然后将最后一个覆盖的元素放在第一位:

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;
});

由于向量是连续的,因此&a > &b应该可以将附加的替代项首先放在已排序的向量中,这等效于使用std::stable_sort,但是我不确定在向量中是否存在状态std::sort实现,其中将交换相等的值,以使出现在原始矢量后面的元素的地址现在更早。我不想使用stable_sort,因为对于我的用例而言,它要慢得多。我还考虑过在结构中添加一个字段以跟踪原始索引,但是我需要为此复制向量。

它似乎在这里起作用:https://onlinegdb.com/Hk8z1giqX

1 个答案:

答案 0 :(得分:4)

std::sort在比较元素时不提供任何保证,在实践中,我强烈怀疑大多数实现都会对您的比较器产生不良影响。

常见的std::sort实现是普通的快速排序或混合排序(对于小范围,快速排序切换到其他排序),它们是就地实现的,以避免使用额外的内存。这样,随着排序的进行,比较器将在不同的存储器地址处使用相同的元素来调用;您不能使用内存地址来实现稳定的排序。

要么添加必要的信息以使排序固有地稳定(例如建议的初始索引值),要么使用std::stable_sort。使用内存地址来稳定排序是行不通的。

出于记录,经过一些试验,我怀疑您的测试用例太小而无法触发问题。猜测一下,混合排序策略在较小的vector上可以同时工作,但是在vector变得足够大到可以进行实际的快速排序时会崩溃。一旦我增加vector的大小并添加了更多填充符,稳定性就会消失,Try it online!