从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
不相等。他们有秩序。但是从引用的文字和输出来看,这似乎表明它只是保留了所有原始顺序。
我是不是误会了什么,或者教科书在这里是错误的,输出恰好遵循先前的排序顺序?
答案 0 :(得分:3)
fox
而言, red
,the
和stable_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"
都为假,因此isShorter
和isShorter("fox", "red")
等效于isShorter("red", "fox")
。因此,使用stable_sort
进行的isShorter
调用必须保留"fox"
在"red"
之前的事实。但同样,这两个词显然不相同。是的,fox red the
的顺序是固定的,因为排序必须保留来自相同对等类的所有这些单词的相对顺序。另一方面,"red"
和"jumps"
不相等,因为isShorter("red", "jumps")
为真,所以排序需要交换顺序,以便"red"
早于{{ 1}}。
实际上,对于任何范围和有效的严格弱排序比较,"jumps"
仅允许一个结果(与std::stable_sort
不同,鉴于对元素中每个等价类的重新排序,此结果是正确的顺序)。