纯归并排序的复杂度为: O(nlgn),而纯插入排序的时间复杂度为:O(n^2)。数据量很大的时候采用归并排序
但是在n较小的时候插入排序可能运行的会更快点。因此在归并排序中当子问题变得足够小时,采用插入排序来使得递归的叶子变粗可以加快排序速度。那么这个足够小到底怎么去衡量呢? 请看下面:
这么几个我不证明了,比较简单:
A,插入排序最坏情况下可以在O(nk)时间内排序每个长度为k的n/k个子列表
B,在最坏情况下可在O(nlg(n/k))的时间内合并这些子表
C,修订后的算法的最坏情况运行时间复杂度是O(nk + nlg(n/k))
那么,O(nk+nlg(n/k))=O(nlgn).只能最大是k=O(lgn).等式左边中第一项是高阶项。k如果大于lgn,则比归并排序复杂度大了。左边可以写成nk+nlgn-nlgk,k等于lgn时,就是2nlgn-nlglgn.忽略恒定系数,则与归并排序是一样的。
最后结论: k < lg(n)的时候,使用插入排序
from at003_insertsort import insertSort from math import log __author__ = 'Xiong Neng' def mergeSort(seq): mergeSortRange(seq, 0, len(seq) - 1, log(len(seq)) - 1) def mergeOrderedSeq(seq, left, middle, right): """ seq: 待排序序列 left <= middle <= right 子数组seq[left..middle]和seq[middle+1..right]都是排好序的 该排序的时间复杂度为O(n) """ tempSeq = [] i = left j = middle + 1 while i <= middle and j <= right: if seq[i] <= seq[j]: tempSeq.append(seq[i]) i += 1 else: tempSeq.append(seq[j]) j += 1 if i <= middle: tempSeq.extend(seq[i:middle + 1]) else: tempSeq.extend(seq[j:right + 1]) seq[left:right + 1] = tempSeq[:] def mergeSortRange(seq, start, end, threshold): """ 归并排序一个序列的子序列 start: 子序列的start下标 end: 子序列的end下标 threshold: 待排序长度低于这个值,就采用插入排序 """ if end - start < threshold: tempSeq = seq[start: end + 1] insertSort(tempSeq) seq[start: end + 1] = tempSeq[:] elif start < end: # 如果start >= end就终止递归调用 middle = (start + end) / 2 mergeSortRange(seq, start, middle, threshold) # 排好左边的一半 mergeSortRange(seq, middle + 1, end, threshold) # 再排好右边的一半 mergeOrderedSeq(seq, start, middle, end) # 最后合并排序结果 if __name__ == '__main__': aa = [4, 2, 5, 1, 6, 3, 7, 9, 8] mergeSort(aa) print(aa)
本人博客已搬家,新地址为:http://www.pycoding.com/
相关推荐
归并排序正是通过将大数组拆分为小数组,对每个小数组进行排序,再合并已排序的小数组来实现整体的排序。 在**归并排序**中,我们首先将数组分为两个相等(或接近相等)的部分,分别对这两部分进行排序,然后将这两...
归并排序就是典型的分治法应用,它将一个大数组分为两个小数组,分别对这两个小数组进行排序,然后将排好序的小数组合并成一个大的有序数组。 2. **递归**:归并排序的实现通常用到递归。递归是指函数调用自身的...
为了改善这一点,可以对归并排序进行插入排序的优化。 插入排序在处理小数组时有较好的性能,尤其是在数组已经部分有序的情况下。因此,当归并排序的子问题规模减小到一定程度,例如 k 个元素时,可以改用插入排序...
归并排序就是利用这种策略,将一个大数组分割成两个小数组,分别对这两个小数组进行排序,然后将排好序的两个小数组合并成一个大的有序数组。 首先,我们从分治的角度来理解归并排序的过程。假设有一个包含n个元素...
在归并排序的实现中,如果数据结构是链表而非数组,那么需要采用链式归并的方法。链式归并排序涉及到链表节点的拆分、合并以及维护链表结构,相比数组,链表操作更加复杂,但依然可以实现高效的排序。 在实际编程中...
归并排序利用这一策略,将一个大数组分成两个小数组,分别对它们进行排序,然后将排好序的小数组合并成一个大的有序数组。 非递归的归并排序与传统的递归实现不同,它通过循环结构而不是函数调用来完成排序过程。...
在归并排序中,我们将一个大的数组分割成两个或多个小数组,对每个小数组进行排序,然后将它们合并成一个有序的大数组。 具体步骤如下: 1. **分割(Divide)**:将原始数组分为左右两个子数组。通常,我们会选择...
Java中,可以使用`java.util.Arrays.sort()`方法,它内部实现了高效的排序算法,对于小数组可能会使用插入排序,大数组则使用了Timsort,一种结合了归并排序和插入排序优点的混合排序算法。 以上就是关于归并排序、...
本文将重点讨论标题和描述中提及的几种排序算法:插入排序、快速排序、归并排序以及希尔排序。 **1. 插入排序** 插入排序是一种简单直观的排序算法,它的工作原理类似于我们平时整理扑克牌的方式。首先,数组被视...
函数首先检查子序列长度是否小于等于32,如果是,则调用`inssort1`函数进行插入排序(这是因为对于小数组,插入排序比归并排序更高效)。然后,计算中间索引,递归调用自身对左右两半进行排序,并在最后将两个已排序...
在归并排序中,我们将一个大的数组分割成两个或更多的小数组,对每个小数组进行排序,然后再将它们合并成一个有序的大数组。 1. **分治法**:归并排序是分治法的经典应用。分治法的基本步骤包括分解、解决和合并。...
在Java中实现归并排序,我们可以创建一个类`MergeSort1`,并在其中定义方法来完成排序过程。以下是对给定文件内容的详细解释: 1. **分治思想**: - 归并排序的核心在于将大问题分解成小问题,然后解决小问题再...
希尔排序是插入排序的一种优化版本,通过设置间隔序列,将大数组分解成若干小数组进行排序,最后再进行一次插入排序。它的时间复杂度通常介于O(n)和O(n^2)之间,比原始插入排序更高效。 3. **选择排序(Selection ...
在归并排序中,我们将一个大数组分成两个或更多个小数组,然后对每个小数组进行排序,最后将这些小数组合并成一个大的有序数组。这个过程是递归的,直到每个小数组只有一个元素,此时它们已经是有序的,然后再逐步...
归并排序就是将一个大数组分成两个或更多个小数组,对每个小数组进行排序,然后将排好序的小数组合并成一个大的有序数组。 2. **归并排序的基本步骤**: - **划分**(Divide):将原始数组划分为两个大小相等(或...
堆排序分为建堆和调整堆两个步骤,时间复杂度为O(n log n),但在实际应用中可能会比归并排序慢,因为它对原始数组的元素顺序不敏感。 **快速排序** 快速排序是由C.A.R. Hoare提出的,也是基于分治策略的一种高效...
归并排序利用了这一思想,将一个大数组分为两个或多个小数组,分别对它们进行排序,然后将排序后的子数组合并成一个完整的、有序的大数组。 **归并排序的基本步骤:** 1. **分割(Divide)**:将原始数组拆分为两半...
在直接插入排序中,每次将一个待排序的元素插入到已经排序好的序列中的适当位置。折半插入排序则是通过二分查找来确定插入位置,提高了效率。希尔排序则是通过设置间隔序列,减少元素移动次数,从而提高整体效率。 ...
归并排序也是一种分治算法,将大数组分割成两个小数组,分别进行排序,再合并这两个已排序的子数组。C++实现中,一般用到两个辅助数组进行合并操作。归并排序的时间复杂度稳定为O(n log n),但额外空间复杂度为O(n)...
- **归并排序**:采用分治法的思想,将数组分成两半,递归地对每一半进行排序,然后合并这两个有序的数组。 - **快速排序**:同样采用分治法的思想,选择一个基准值,将数组分为小于基准值和大于基准值的两部分,...