【发布时间】:2019-11-19 00:11:36
【问题描述】:
在下面的sn -p中消耗std::sort的时间。这应该花费O(nlog(n)) 时间。 std::chrono 仅用于测量 std::sort。
我使用英特尔编译器 18.0.3 编译了以下代码,优化级别为 -O3。我用的是 Redhat6。
#include <vector>
#include <random>
#include <limits>
#include <iostream>
#include <chrono>
#include <algorithm>
int main() {
std::random_device dev;
std::mt19937 rng(dev());
std::uniform_int_distribution<std::mt19937::result_type> dist(std::numeric_limits<int>::min(),
std::numeric_limits<int>::max());
int ret = 0;
const unsigned int max = std::numeric_limits<unsigned int>::max();
for (auto j = 1u; j < max; j *= 10) {
std::vector<int> vec;
vec.reserve(j);
for (int i = 0; i < j; ++i) {
vec.push_back(dist(rng));
}
auto t_start = std::chrono::system_clock::now();
std::sort(vec.begin(), vec.end());
const auto t_end = std::chrono::system_clock::now();
const auto duration = std::chrono::duration_cast<std::chrono::duration<double>>(t_end - t_start).count();
std::cout << "Time measurement: j= " << j << " took " << duration << " seconds.\n";
ret + vec[0];
}
return ret;
}
这个程序的输出是
Time measurement: j= 1 took 1.236e-06 seconds.
Time measurement: j= 10 took 5.583e-06 seconds.
Time measurement: j= 100 took 1.0145e-05 seconds.
Time measurement: j= 1000 took 0.000110649 seconds.
Time measurement: j= 10000 took 0.00142651 seconds.
Time measurement: j= 100000 took 0.00834339 seconds.
Time measurement: j= 1000000 took 0.098939 seconds.
Time measurement: j= 10000000 took 0.938253 seconds.
Time measurement: j= 100000000 took 10.2398 seconds.
Time measurement: j= 1000000000 took 114.214 seconds.
Time measurement: j= 1410065408 took 163.824 seconds.
这似乎非常接近线性行为。
为什么std::sort 需要O(n) 而不是O(nlog(n))?
【问题讨论】:
-
Big-O 表示法是关于复杂性,而不是具体的时间。
-
O(n*log(n)) 是标准允许的最坏情况。仍然允许标准库实现进行优化。一些排序算法(尤其是那些处理数字的算法)接近 O(n)。
-
在
n log n的大比例图中看起来像线性函数:wolframalpha.com/input/?i=x+log+x+from+2+to+100000 -
@LightnessRacesinOrbit:写得很好,测试用例很好,图表很漂亮。您还想要什么问题?
-
@LightnessRacesinOrbit:除非你有一个扭曲的童年,否则你会认为 x log (x) 比实际更弯曲是可以原谅的。
标签: c++ sorting time performance-testing