java - 插入和合并排序算法 - 异常计时结果

标签 java algorithm mergesort insertion-sort

我正在尝试获取 Java 中两种排序算法(插入排序和归并排序)的运行时间。 该程序多次对 433 个单词的未排序 ArrayList 运行两种排序,并存储 100、200、300、400 和 要排序的 433 个单词(整个数组),然后打印出每个单词所用的平均时间。

我相信我的代码没问题。但是,我遇到了一个奇怪的异常情况,我想知道是否有人可以帮助我理解。

以下是两种排序都执行一次时的结果:1

以下是两种排序都执行10,000 次时的结果:2

当运行一次时,我相信结果符合预期,即插入排序对于排序的元素数量越少,合并排序对于元素数量越多和整个数组越快。

但是,当运行 10,000 次时,平均时间有很大偏差,对于所有已排序的元素,插入排序要快得多。

好像每次迭代都在加速插入排序,这怎么可能?

用于运行所述排序算法的多次迭代的排序算法和方法的代码 - 在下面的评论中

感谢您提供的任何帮助。

最佳答案

这些算法的时间复杂度众所周知:O(N2) 用于插入排序,O(N.log(N)) 用于归并排序。

以下是您意外观察到的可能原因:

  • 400 个字符串的数据集不是很大,实现的质量可能比算法的复杂性更重要。

  • 您的插入排序实现效率不是很高,但至少它在原地运行,因此有效时间复杂度为 O(N2)。然而,您应该删除每 100 个元素执行一次的测量代码,其复杂性非常高。

  • 您的合并排序实现效率非常低:您为每个拆分和合并阶段一次分配多个动态数组一个元素。这是非常耗时的,并且会导致大量对象被分配并几乎立即悬空,以供垃圾收集器以巨大的代价回收。

  • 单次调用合并排序可能比插入排序执行得更好,如果时间有意义的话,但许多调用可能会触发垃圾收集器,带来大量开销,尽管您的时间没有显示出这一点的证据,可能是因为 10000 次迭代还不够。

  • 真正的解释实际上很简单:由于您的插入排序实现对数据集进行了就地排序,因此它已经为每个后续调用排序,这是具有线性复杂度的插入排序的最佳情况。

您应该对初始数据集的副本进行排序以获得更有意义的基准。并且还要寻找更好的合并排序实现,它使用单个临时数组并对元素进行适当的排序,并在事先知道大小时避免使用动态数组。

关于java - 插入和合并排序算法 - 异常计时结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55830851/

相关文章:

Java读取文件并发送到服务器

java - 致命异常 : main java. lang.NoClassDefFoundError : org. apache.commons.net.ftp.FTPClient Android Studio

java - LinkedList 上的递归合并排序

java - 递归打印电话号码中可能的单词

java - 从 lambda 表达式排序和子列表

ruby - 删除递归哈希数组中包含特定键=>值的哈希

algorithm - 有人可以向我解释每个循环和变量在自下而上合并排序中的含义吗?

javascript - 使用浮点源均匀分布整数

c - C 中使用数组和交换函数时的指针

c++ - 对结构进行合并排序不起作用