我正在尝试获取Java中两种排序算法(插入和合并排序)的运行时。 该程序会在433个单词的未排序ArrayList上多次运行两种排序,并存储100、200、300、400和100的耗用时间 将要排序的433个单词(整个数组),然后打印出每个单词的平均时间。
我相信我的代码还可以。但是,我遇到了一个奇怪的异常,我想知道是否有人可以帮助我理解。
这是同时执行两种排序一次的结果:
以下是两种排序 10,000次执行的结果:
运行一次结果如预期的那样,即插入排序对于较少数量的元素排序更快,而合并排序对于较高数量和整个数组而言更快。
但是,当运行10,000次时,平均计时却遥遥无期,对于所有排序的元素,插入排序都快得多。
好像插入排序随着每次迭代而加快,这怎么可能?
排序算法和用于运行所述排序算法多次迭代的方法的代码-在下面的注释中
感谢您提供的任何帮助。
答案 0 :(得分:2)
这些算法的时间复杂度众所周知: O(N 2 )用于插入排序, O(N.log(N))用于合并排序。
以下是您意外观察的可能原因:
400个字符串的数据集不是很大,实现的质量可能比算法的复杂性更为重要。
您的插入排序实现效率不是很高,但至少可以在原地运行,因此有效时间复杂度为 O(N 2 )。但是,您应该删除执行每100个元素的度量代码,而这些代码的复杂度却不高。
您的合并排序实现效率很低:您为每个拆分和合并阶段一次分配多个动态数组一个元素。这非常耗时,并且会导致大量对象被分配并几乎立即悬空,以使垃圾收集器能够回收大量资源。
如果时序很有意义,那么一次合并排序的调用可能比插入排序的性能更好,但是许多调用可能会触发垃圾回收器,但会产生大量开销,尽管您的时序并未显示出这种情况的证据。 ,可能是因为10000次迭代是不够的。
真正的解释实际上很简单:由于插入排序实现对数据集进行了排序,因此已经为每个后续调用进行了排序,这是线性复杂度插入排序的最佳情况。
< / li>您应该对初始数据集的副本进行排序,以获得更有意义的基准。并且还寻找一种更好的合并排序实现,该实现使用单个临时数组并对元素进行排序,并在事先知道大小的情况下避免使用动态数组。