我正在制作10000,20000,40000,80000和160000名学生的名单,并根据他们的成绩快速排序(具有相同年级的学生将按学生编号排序)。与此同时,我正在运行秒表来查看执行时间。我正在使用Sedgewick他的快速搜索:http://algs4.cs.princeton.edu/23quicksort/
当我打印出来的学生时,他们都得到了完美的分类,但是我在执行时间里发现了一些奇怪的东西:
10000 0.015
20000 0.019
40000 0.096
80000 0.039
160000 0.109
例如,40.000获得一个高峰,然后再次以更大的数量下降。运行多个测试时,此行为是一致的,有时峰值为20.000。这是否是这些金额不幸分区的原因?我也很好奇如何通过执行时间来计算大O.
答案 0 :(得分:4)
我注意到你使用Java作为编程语言。在Java中获取可靠的时序数很难,因为JVM除了运行代码之外还做了很多工作 - 它将优化代码(通常对即时运行的代码进行即时编译或优化),执行垃圾收集(可以弄乱时间)等等。
在没有看到你的代码的情况下,我无法肯定地说出任何内容,但我认为在紧密循环中多次运行代码并计算运行时的中值可能是个好主意。中位数对异常值的敏感度低于均值,并且应该忽略由于垃圾收集等导致的任何异常高的运行时间。您可能还需要考虑使用高质量的Java分析器来更准确地估计时间。
关于你的第二个问题 - 你如何从运行时计算大O时间复杂度? - 答案是它很棘手。您可以通过查看代码随时间变化的增长情况来经验地估计代码的时间复杂度,通常查看不同大小的运行时之间的比率。有些工具可以自动为您执行此操作like this tool for finding empirical computational complexity。但是,你应该小心这些结果,因为它们不一定会给你正确的答案。例如,解决线性程序的单纯形方法在最坏情况下以指数时间运行,但触发该行为极其困难。只看经验行为可能会让你错过这一点。类似地,即使使用随机化,快速排序也可以在某些输入上退化为O(n 2 ),但除非您在疯狂的大量输入上运行算法,否则很难检测到它。