std :: sort和std :: stable_sort有什么区别?

时间:2014-06-02 00:33:30

标签: c++

我想知道std :: sort和std :: stable_sort有什么区别,关于内存和硬件? Stable_sort保留具有等效值的元素的相对顺序?

4 个答案:

答案 0 :(得分:16)

是的,就像你说的那样,这不是C ++独有的概念。

稳定排序保留语义等效值的物理顺序。


std::sort

  

不保证保留相等元素的顺序   复杂性: O(N·log(N)),其中N = std::distance(first, last)比较

std::stable_sort

  

保证保持相等元素的顺序   复杂性: O(N·log^2(N)),其中N = std::distance(first, last) cmp的应用程序。如果有额外的内存,则复杂度为O(N·log(N))

这意味着std::stable_sort在执行时间方面不能非常有效地执行,除非“额外的内存可用”,在这种情况下,它在内存消耗方面没有得到有效执行。

答案 1 :(得分:10)

如上所述,标准只注意到std :: stable_sort保留了相等元素的原始顺序,而std :: sort则没有。

对于HP / Microsoft STL,std :: sort通常是快速排序,除非嵌套变得太深,在这种情况下它会切换到堆排序。快速排序时间复杂度通常为O(n log(n)),但最坏的情况是O(n ^ 2),这可以通过切换到堆排序来避免,因为堆排序总是为O(n log) (n))(但比快速排序慢,所以它只用于避免O(n ^ 2))。

对于HP / Microsoft STL,std :: stable_sort是一种混合式自下而上合并排序,使用插入排序创建32个元素的已排序组,然后对这些组进行自下而上的合并排序。数组(或向量)被分成两个,一个临时数组(或向量),分配要排序的数组大小的1/2,并用于对数组的两半进行合并排序。然后将其中一个半数组移动到临时数组以进行最终合并传递。合并排序也是O(n log n),对于排序对象数组需要更长的时间,但是如果对指向调用中包含比较函数的对象的指针数组进行排序,则合并排序通常会更快。这是因为合并排序涉及更多移动,但比快速排序更少。

对于整数数组,基数排序更快。如果按字节排序,则需要4次传递来对32位整数数组进行排序,8次传递以对64位整数数组进行排序。

答案 2 :(得分:5)

正如您所知,std::stable_sort()保留了被认为等效的对象的相对顺序。 std::sort()没有此要求。因此,std::stable_sort()可能更需要资源:它可能会更慢并且可能会使用更多临时内存,因为它必须遵守更多约束。我不知道任何算法可以进行就地稳定排序和排序一样有效。

答案 3 :(得分:2)

我认为,对结构进行排序而不是对整数列表进行排序的示例有助于阐明两者之间的区别。

想象一下建筑物中的邻居列表,这些邻居是按他们居住的楼层顺序构建的。

struct Neighbour
{
   int floor;
   string name;
   Neighbour(int f, string n) : floor(f), name(n) {}
};

std::vector<Neighbour> vec = {Neighbour(1,Bob), Neighbour(2,Anna), ... };
  • 1个鲍勃
  • 2安娜
  • 3彼得
  • 4个鲍勃
  • 5劳拉

如果您现在想按字母顺序对列表进行排序,并且使用

std::sort(vec.begin(), vec.end(), [](Neighbour a, Neighbour b){ return a.name < b.name; }

结果可能是:

  • 2安娜
  • 1个鲍勃
  • 4个鲍勃
  • 5劳拉
  • 3彼得

或:

  • 2安娜
  • 4个鲍勃
  • 1个鲍勃
  • 5劳拉
  • 3彼得

使用stable_sort可以确保始终获得第一结果。重复项的顺序相同,它们在初始列表中。