【问题标题】:Why is insertion sort so fast compared to other sorting algorithms?与其他排序算法相比,为什么插入排序如此之快?
【发布时间】:2017-07-30 14:07:22
【问题描述】:

我一直在测试各种其他排序算法(Selection、Quick、Bubble、Shell、Radix 等)以及插入排序的速度。然而,插入排序似乎是迄今为止最快的算法。我一直认为快速排序会是最快的。

这是我在 Python 3 中的插入排序和计时器函数的代码。

def InsertionSort(argShuffledList):
    for index in range(1,len(argShuffledList)):

        currentvalue = argShuffledList[index]
        position = index

        while position>0 and argShuffledList[position-1]>currentvalue:
            argShuffledList[position]=argShuffledList[position-1]
            position = position-1

        argShuffledList[position]=currentvalue
    return argShuffledList

def Timer(argFunction, *args): ## function for timing functions
    dblStart = time.clock()
    argFunction(*args)
    intTime = "%.2f" % ((time.clock() - dblStart) * 1000000)
    message = "Elasped Time: " + str(intTime) + " microseconds"
    return message

insertionSortList = InsertionSort(insertionCopyList) 
timeInsertionSortList = Timer(InsertionSort, insertionCopyList)

【问题讨论】:

  • 列表有多长?此外,使用time 计时并不理想,请使用timeit 模块。大家可以看看不同排序算法的复杂度here
  • 不要将 O(n^2) 算法与 O(n log n) 算法进行比较。它使比较毫无用处,除非您的目标是非常具体的 n 大小。
  • 实际上,更详细一点,您只需为未指定大小的列表调用一次排序算法。即使您不想使用timeit,您的测试用例也非常有限,您不可能使用这种方法对您的算法进行基准测试。
  • 看起来您正在对列表进行排序,然后再次定时排序。但是第二次,列表已经排序,这是插入排序的绝对最佳情况。您确定对InsertionSort(insertionCopyList) 的第一次调用没有对insertionCopyList 进行排序吗?

标签: python algorithm sorting quicksort insertion-sort


【解决方案1】:

您在计时之前对列表进行排序。因此,当您计时时,列表已经排序,并且您的插入排序不需要进行任何插入,因此以线性时间运行。

insertionSortList = InsertionSort(insertionCopyList) 
timeInsertionSortList = Timer(InsertionSort, insertionCopyList)

目前尚不清楚第一次调用 InsertionSort 的目的是什么,除非您尝试对已排序的列表进行计时。

【讨论】:

    【解决方案2】:

    任务的“最佳”排序取决于许多标准,包括数据类型、项目数、数据分布等。

    项目的数量很重要,因为更简单的 O(n^2) 排序算法的开销比处理效率更高的 O(n lg n) 算法的开销要少得多,但是你需要的项目越多,开销就越不重要种类。这就是为什么至少有一个qsort 的实现(微软随 Visual C++ 一起提供)使用快速排序,直到给定的分区有七个或更少的项目,此时分区使用插入排序进行排序。

    插入排序比其他一些 O(n^2) 排序算法更快,因为它的开销更少(尤其是与冒泡排序相比)。

    还有各种排序算法。例如,与更复杂的三分区快速排序相比,两分区快速排序在最坏情况下的性能更差,尤其是在数据已经按逆序排序的情况下。

    基数排序是一种特殊排序,其性能很大程度上取决于数据类型。当数据项是固定宽度并且可以利用这一事实时,最好使用它,这使得它非常适合对整数列表进行排序,但不适用于对一般字符串列表进行排序。我见过有人为提高排序(32 位)浮点数的效率所做的工作,但它确实大量利用了浮点数的内部存储。

    【讨论】:

    • 假设没有特殊的浮点数,如 NAN、+/- 无穷大,浮点数可以被视为符号 + 幅度整数以进行比较或映射(如果 >= 0 则切换符号位,如果
    • 我似乎找不到 9 年前发现的参考资料,但我确实找到了其他几个很好的参考资料:one(参考自 here)和 two。跨度>
    【解决方案3】:

    这实际上取决于您使用的列表类型:即使Insetrion Sort's 最坏情况时间是 O(n2) 它是一个近似值,这意味着它不适用于小型或几乎排序的列表。

    Quick sort 由于所有递归函数而使用了额外的开销。这就是为什么您应该在问题较小时授予Insertion sort 的特权,而不是像merge sortquick sort 这样的分而治之的排序算法。

    【讨论】:

      猜你喜欢
      • 2016-02-01
      • 1970-01-01
      • 2011-12-03
      • 2011-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-05
      相关资源
      最近更新 更多