`

归并排序中对小数组采用插入排序

阅读更多

纯归并排序的复杂度为: 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/

分享到:
评论

相关推荐

    算法设计采用废分治策略进行归并排序

    归并排序正是通过将大数组拆分为小数组,对每个小数组进行排序,再合并已排序的小数组来实现整体的排序。 在**归并排序**中,我们首先将数组分为两个相等(或接近相等)的部分,分别对这两部分进行排序,然后将这两...

    归并排序C++实现的例子

    归并排序就是典型的分治法应用,它将一个大数组分为两个小数组,分别对这两个小数组进行排序,然后将排好序的小数组合并成一个大的有序数组。 2. **递归**:归并排序的实现通常用到递归。递归是指函数调用自身的...

    归并排序的插入排序优化1

    为了改善这一点,可以对归并排序进行插入排序的优化。 插入排序在处理小数组时有较好的性能,尤其是在数组已经部分有序的情况下。因此,当归并排序的子问题规模减小到一定程度,例如 k 个元素时,可以改用插入排序...

    归并排序源代码 可运行

    归并排序就是利用这种策略,将一个大数组分割成两个小数组,分别对这两个小数组进行排序,然后将排好序的两个小数组合并成一个大的有序数组。 首先,我们从分治的角度来理解归并排序的过程。假设有一个包含n个元素...

    归并和快速排序c程序实现

    在归并排序的实现中,如果数据结构是链表而非数组,那么需要采用链式归并的方法。链式归并排序涉及到链表节点的拆分、合并以及维护链表结构,相比数组,链表操作更加复杂,但依然可以实现高效的排序。 在实际编程中...

    非递归的归并排序(一种优排序)

    归并排序利用这一策略,将一个大数组分成两个小数组,分别对它们进行排序,然后将排好序的小数组合并成一个大的有序数组。 非递归的归并排序与传统的递归实现不同,它通过循环结构而不是函数调用来完成排序过程。...

    归并排序源代码 可直接执行

    在归并排序中,我们将一个大的数组分割成两个或多个小数组,对每个小数组进行排序,然后将它们合并成一个有序的大数组。 具体步骤如下: 1. **分割(Divide)**:将原始数组分为左右两个子数组。通常,我们会选择...

    归并排序,消除递归归并排序,快排,Java实现

    Java中,可以使用`java.util.Arrays.sort()`方法,它内部实现了高效的排序算法,对于小数组可能会使用插入排序,大数组则使用了Timsort,一种结合了归并排序和插入排序优点的混合排序算法。 以上就是关于归并排序、...

    算法 排序算法(插入 快速 归并)

    本文将重点讨论标题和描述中提及的几种排序算法:插入排序、快速排序、归并排序以及希尔排序。 **1. 插入排序** 插入排序是一种简单直观的排序算法,它的工作原理类似于我们平时整理扑克牌的方式。首先,数组被视...

    C语言实现归并排序算法

    函数首先检查子序列长度是否小于等于32,如果是,则调用`inssort1`函数进行插入排序(这是因为对于小数组,插入排序比归并排序更高效)。然后,计算中间索引,递归调用自身对左右两半进行排序,并在最后将两个已排序...

    算法-数据结构之归并排序.rar

    在归并排序中,我们将一个大的数组分割成两个或更多的小数组,对每个小数组进行排序,然后再将它们合并成一个有序的大数组。 1. **分治法**:归并排序是分治法的经典应用。分治法的基本步骤包括分解、解决和合并。...

    归并排序的java实现.docx

    在Java中实现归并排序,我们可以创建一个类`MergeSort1`,并在其中定义方法来完成排序过程。以下是对给定文件内容的详细解释: 1. **分治思想**: - 归并排序的核心在于将大问题分解成小问题,然后解决小问题再...

    cpp-八大排序插入shell选择堆冒泡快速归并基数

    希尔排序是插入排序的一种优化版本,通过设置间隔序列,将大数组分解成若干小数组进行排序,最后再进行一次插入排序。它的时间复杂度通常介于O(n)和O(n^2)之间,比原始插入排序更高效。 3. **选择排序(Selection ...

    C语言演示对归并排序算法的优化实现

    在归并排序中,我们将一个大数组分成两个或更多个小数组,然后对每个小数组进行排序,最后将这些小数组合并成一个大的有序数组。这个过程是递归的,直到每个小数组只有一个元素,此时它们已经是有序的,然后再逐步...

    归并排序mergesort

    归并排序就是将一个大数组分成两个或更多个小数组,对每个小数组进行排序,然后将排好序的小数组合并成一个大的有序数组。 2. **归并排序的基本步骤**: - **划分**(Divide):将原始数组划分为两个大小相等(或...

    5大排序算法

    堆排序分为建堆和调整堆两个步骤,时间复杂度为O(n log n),但在实际应用中可能会比归并排序慢,因为它对原始数组的元素顺序不敏感。 **快速排序** 快速排序是由C.A.R. Hoare提出的,也是基于分治策略的一种高效...

    归并排序

    归并排序利用了这一思想,将一个大数组分为两个或多个小数组,分别对它们进行排序,然后将排序后的子数组合并成一个完整的、有序的大数组。 **归并排序的基本步骤:** 1. **分割(Divide)**:将原始数组拆分为两半...

    java各种数组排序(插入,交换,选择,归类,基数排序).pdf

    在直接插入排序中,每次将一个待排序的元素插入到已经排序好的序列中的适当位置。折半插入排序则是通过二分查找来确定插入位置,提高了效率。希尔排序则是通过设置间隔序列,减少元素移动次数,从而提高整体效率。 ...

    c++实现的各种排序算法

    归并排序也是一种分治算法,将大数组分割成两个小数组,分别进行排序,再合并这两个已排序的子数组。C++实现中,一般用到两个辅助数组进行合并操作。归并排序的时间复杂度稳定为O(n log n),但额外空间复杂度为O(n)...

    排序算法全集锦(java代码实现)

    - **归并排序**:采用分治法的思想,将数组分成两半,递归地对每一半进行排序,然后合并这两个有序的数组。 - **快速排序**:同样采用分治法的思想,选择一个基准值,将数组分为小于基准值和大于基准值的两部分,...

Global site tag (gtag.js) - Google Analytics