zoukankan      html  css  js  c++  java
  • python 归并排序

    归并排序仍然是利用完全二叉树实现,它是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列。

    基本过程:假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个长度为2或1的有序子序列,再两两归并,最终得到一个长度为n的有序序列为止,这称为2路归并排序。

    下面的截图来自《大话数据结构》相关章节,便于理解整个代码的实现过程。

                                   

    图中主要表明了实例代码中的两部分,分别为原始序列的拆分和合并两部分。

    下面是实例代码:

    # -*- coding:utf-8 -*-
    __author__ = 'webber'
    import random, time
    
    def merge_sort(lst):
        if len(lst) <= 1:
            return lst          # 从递归中返回长度为1的序列
    
        middle = len(lst) / 2
        left = merge_sort(lst[:middle])     # 通过不断递归,将原始序列拆分成n个小序列
        right = merge_sort(lst[middle:])
        return merge(left, right)
    
    def merge(left, right):
        i, j = 0, 0
        result = []
        while i < len(left) and j < len(right):  # 比较传入的两个子序列,对两个子序列进行排序
            if left[i] <= right[j]:
                result.append(left[i])
                i += 1
            else:
                result.append(right[j])
                j += 1
        result.extend(left[i:])         # 将排好序的子序列合并
        result.extend(right[j:])
        return result
    
    if __name__ == "__main__":
        start = time.clock()
    
        rand_lst = []
        for i in range(6):
            rand_lst.append(round(random.random()*100, 2))
        lst = merge_sort(rand_lst)
    
        end = time.clock()
        print lst
        print "done  ", (end-start)

    性能方面:

    由于和堆排序类似,都是利用完全二叉树的相关性质,所以它在时间复杂度方面,最好、最坏和平均的时间复杂度都是O(nlogn);但是,在空间复杂度方面,由于它开辟了一块新的内存空间用来存放left和right子序列,而两个子序列的总大小其实和lst是一样的,为n,所以它的空间复杂度为O(n),这是归并排序的主要弱点,牺牲了空间复杂度来换取时间复杂度的减少。稳定性方面,只要在关键码相同时采用左序列元素先行的原则,就能保证算法的稳定性,另一方面,归并排序算法没有适应性,无论对于什么样的序列它都要做logn遍的递归。在《大话数据结构》一书中,对于归并排序,作者提倡尽量考虑非递归的方法(在c中)。

    这里记录一下,python有一个模块,专门提供了归并排序的方法,叫做“heapq”模块,因此我们只要将分解后的结果导入该方法即可。例如:

    from heapq import merge
    
    def merge_sort(lst):
        if len(lst) <= 1:
            return lst          # 从递归中返回长度为1的序列
        middle = len(lst) / 2
        left = merge_sort(lst[:middle])     # 通过不断递归,将原始序列拆分成n个小序列
        right = merge_sort(lst[middle:])
        return list(merge(left, right))
  • 相关阅读:
    链家新房爬虫
    豆瓣电影爬虫
    电影天堂爬虫
    数组、数组和集合的区别
    Profile小试
    SQL中的case when使用小例
    使用AVAudioPlayer播放网络音乐
    播放器
    全排列问题
    由while(scanf("%d",&n)!=EOF)引出的小问题
  • 原文地址:https://www.cnblogs.com/webber1992/p/6142527.html
Copyright © 2011-2022 走看看