我有以下代码,我尝试两个简单向量的词典比较
class ExpensiveClass {
public:
static int increment;
std::vector<int> bigVector;
ExpensiveClass() {
for (int j = 0; j < 1 + increment; ++j)
bigVector.emplace_back(j);
++increment;
}
ExpensiveClass(const ExpensiveClass& other) {
std::cout << "Expensive copy constructor called!" << std::endl;
this->bigVector = other.bigVector;
}
};
int ExpensiveClass::increment = 0;
bool sortFunc(const ExpensiveClass& a, const ExpensiveClass& b) {
bool ret = a.bigVector < b.bigVector;
if (ret == false)
std::cout << "Need to swap" << std::endl;
return ret;
}
int main()
{
std::vector<ExpensiveClass> vectorOfVectors;
vectorOfVectors.reserve(100);
for (int i = 0; i < 100; ++i)
vectorOfVectors.emplace_back();
std::cout << "Start sorting.." << std::endl;
std::sort(vectorOfVectors.begin(), vectorOfVectors.end(), sortFunc);
}
我想知道为什么std::sort
甚至在排序后的矢量上进行大量交换?
答案 0 :(得分:1)
我认为我们正在进入STL的黑暗角落。我使用了您的代码,发现您的sortFunc()
并不总是返回true
。这是因为传递的参数不是有序的。 std::sort
算法会从您的vectorOfVectors
中选择无序的元素,即a
中vectorOfVectors
的索引不能保证高于b
的索引1}}。但我不知道如何深入研究这一点,所以我创建了一个单独的问题:https://stackoverflow.com/questions/30539898/counter-intuitive-behavior-of-stdsort
无论如何,我的观点是你对std::sort
的行为做了一些假设,但这取决于实现。
答案 1 :(得分:1)
许多排序算法平均表现良好,比较输入容器元素不是出于各种原因而排序,例如随机化各种输入以产生良好的平均时间复杂度,或围绕中位数阈值转换互换等。
还有一些其他算法(例如mergesort和heapsort)通过复制元素和创建辅助结构开始;对于它们,您可以依赖至少复制一次的每个数组元素。这些算法以低于平均情况的性能为代价产生保证渐近最优的最坏情况性能。
stl :: sort不保证它将使用哪种排序算法。实际上,一些STL实现使用两种不同的算法:从具有良好平均情况性能的算法开始(但是糟糕的最坏情况),并且如果算法没有足够快地完成,则stl :: sort切换到较慢的平均情况算法保证渐近最优的最坏情况。
另一方面,STL为您提供了关于如何对容器进行排序的多个选项:除了stl :: sort(设计为表现良好)之外,还有stl :: stable_sort(保留等效元素的相对顺序), stl :: partial_sort等。
我认为在你的情况下你可能更喜欢stl :: stable_sort。这个保证了已经按正确顺序排列的元素之间没有交换。我怀疑stl :: stable_sort实际上最小化了交换次数,但它应该比stl :: sort更换。