Python 归并排序的代码实现

归并排序简介

        归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

        将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。


算法步骤及原理

作为一种典型的分而治之思想的算法应用,归并排序的实现由两种方法:

  • 自上而下的递归(所有递归的方法都可以用迭代重写,所以就有了第 2 种方法);
  • 自下而上的迭代;

        在《数据结构与算法 JavaScript 描述》中,作者给出了自下而上的迭代方法。但是对于递归法,作者却认为:

        However, it is not possible to do so in JavaScript, as the recursion goes too deep for the language to handle.

        译:然而,在 JavaScript 中这种方式不太可行,因为这个算法的递归深度对它来讲太深了。

        和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是 O(nlogn) 的时间复杂度。代价是需要额外的内存空间。


算法步骤

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置;

  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;

  4. 重复步骤 3 直到某一指针达到序列尾;

    扫描二维码关注公众号,回复: 15015037 查看本文章
  5. 将另一序列剩下的所有元素直接复制到合并序列尾。


归并排序动图演示

看不懂的读者可以看下面的图片文字,可以帮您更好的理解归并排序。

 

        可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现)。阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n。

合并相邻有序子序列

        再来看看阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤。


Python 代码实现 

def mergeSort(arr):
    import math
    if(len(arr)<2):
        return arr
    middle = math.floor(len(arr)/2)
    left, right = arr[0:middle], arr[middle:]
    return merge(mergeSort(left), mergeSort(right))

def merge(left,right):
    result = []
    while left and right:
        if left[0] <= right[0]:
            result.append(left.pop(0))
        else:
            result.append(right.pop(0));
    while left:
        result.append(left.pop(0))
    while right:
        result.append(right.pop(0));
    return result

小结 —— 归并排序的时间复杂度、稳定性和空间复杂度

最好时间复杂度 最坏时间复杂度 平均时间复杂度 空间复杂度 稳定性
传统归并排序 O(nlogn) O(nlogn) O(nlogn) T(n) 稳定
改进归并排序 O(n) O(nlogn) O(nlogn) T(n) 稳定
TimSort O(n) O(nlogn) O(nlogn) T(n) 稳定

猜你喜欢

转载自blog.csdn.net/leyang0910/article/details/130470967