stable_sort()是否还会保留不相等元素的顺序?

时间:2018-06-27 02:38:11

标签: c++

cppreference,我知道对于stable_sort

  

保证相等元素的顺序被保留。

我还阅读了What is stability in sorting algorithms and why is it important?这个问题,并了解了稳定性的概念和基本用法。

这是我对稳定排序的理解:
假设我有无序的航班出发时间目的地

首先,我按时间对其进行排序。就像

d-time dest
   1     A
   2     B
   3     C
   4     A
   5     B

然后按目标进行稳定排序。就像

 dest   d-time
   A     1   (stable sort guarantee that [A,1] comes before [A,4])
   A     4
   B     2   (stable sort guarantee that [B,2] comes before [B,5])
   B     5
   C     3

但是示例 C ++ Primer 似乎表明stable_sort也保证了以前的不相等元素的顺序(如果是这样,则意味着stable_sort保留所有原始顺序。

示例代码:

#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;

bool isShorter(const string &s1, const string &s2)
{
    return s1.size() < s2.size();
}

int main(int args, char *argv[])
{
    vector<string> words;
    string in_word;
    istringstream isin("the quick red fox jumps over slow turtles");
    while (isin >> in_word) {
        words.push_back(in_word);
    }
    sort(words.begin(), words.end());
    auto end_unique = unique(words.begin(), words.end());
    words.erase(end_unique, words.end());

    stable_sort(words.begin(), words.end(), isShorter);

    for (auto &s : words) {
        cout << s << " ";
    }
    cout << endl;
} 

这里的文字使我感到疑问,stable_sort是否保持所有原始元素的顺序。

  

假设words在此调用之前(按首个排序和擦除函数调用)按字母顺序排列,则在调用之后,words将按元素大小以及每个单词的进行排序长度保持字母顺序。如果我们在原始矢量上运行此代码,输出将为
  fox red the over slow jumps quick turtle

经过第一次分类和擦除,我得到了:
fox jumps over quick red slow the turtles

经过稳定排序后,我得到了:
fox red the over slow jumps quick turtle


所以我的问题是:

对于stable_sort,只需查看前三个元素:

fox red the,此顺序是否固定?或只是安排中的一种可能的顺序:

fox red the fox the red the red fox the fox red ...(6个结果)

我的意思是,文档中仅 stable_sort保留了相等元素的原始顺序。 fox red the不相等。他们有秩序。但是从引用的文字和输出来看,这似乎表明它只是保留了所有原始顺序

我是不是误会了什么,或者教科书在这里是错误的,输出恰好遵循先前的排序顺序?

2 个答案:

答案 0 :(得分:3)

fox而言,

redthestable_sort相等。您的cppreference链接说:

  

使用给定的比较函数comp对元素进行比较。

因此,是的,fox red the的顺序在您的示例中是固定的,因为stable_sort不会更改这三个(相等短)项目的相对顺序。

答案 1 :(得分:2)

更确切地说,可以保证等效元素的顺序得以保留。甚至更确切地说,stable_sort保留与用于排序的排序比较相对应的元素顺序。

与许多标准算法一样,std::stable_sort要求比较方法对范围内的元素使用严格的弱排序。对于使用operator<的版本和使用传递的Compare对象的版本都是如此。严格弱排序的部分定义是,由!(x<y || y<x)!(comp(x,y) || comp(y,x))确定的二进制关系是等价关系。

因此,在您的第一个示例中,您的两个元素是[A,1][A,4]。在按目的地进行稳定排序的情况下,假定您的比较函子对于comp([A,1], [A,4])comp([A,4], [A,1])都将返回false,因此元素是等效的。但是从它们不相同的意义上说,它们是不相等的。 (请注意,这甚至完全定义了元素类型,而这完全与元素类型的任何operator==operator!=函数的含义无关。)

在单词排序示例中,"fox""red"都为假,因此isShorterisShorter("fox", "red")等效于isShorter("red", "fox")。因此,使用stable_sort进行的isShorter调用必须保留"fox""red"之前的事实。但同样,这两个词显然不相同。是的,fox red the的顺序是固定的,因为排序必须保留来自相同对等类的所有这些单词的相对顺序。另一方面,"red""jumps"不相等,因为isShorter("red", "jumps")为真,所以排序需要交换顺序,以便"red"早于{{ 1}}。

实际上,对于任何范围和有效的严格弱排序比较,"jumps"仅允许一个结果(与std::stable_sort不同,鉴于对元素中每个等价类的重新排序,此结果是正确的顺序)。