美文网首页
python归并排序

python归并排序

作者: 修行的修行 | 来源:发表于2021-02-05 14:44 被阅读0次

    归并排序分为自底向上(迭代)和自顶向下(递归)
    两者皆对15个元素的小区块使用插入排序,不再进行分治操作。
    测试下来,自底向上的归并排序速度更加快

    from functools import wraps
    import time,random
    
    def timeer(name):
        def decorator(func):
            @wraps(func)
            def wrapper(*args,**kwargs):
                start = time.time()
                result = func(*args,**kwargs)
                end = time.time()
                print(name+'耗时:',end-start)
                test(result)
                return result
            return wrapper
        return decorator
    
    def test(arr):
        for i in range(0, len(arr) - 1):
            if not arr[i] <= arr[i + 1]:
                print('错误排序')
                return
        print('正确排序')
    
    class MergeSort():
        def __init__(self,arr):  #arr[l,...,r]
            self.arr = arr
            self.l = 0
            self.r = len(arr)-1
    
        @timeer('自顶向下归并排序')
        def mergeSort(self):
            self._mergeSort(self.arr,self.l,self.r)
            return self.arr
    
        @timeer('自底向上归并排序')
        def mergeSort_advance(self):
            self._mergeSort_advance(self.arr,self.l,self.r)
            return self.arr
    
        def _mergeSort(self,arr, l, r):
            if r - l <= 15:
                insertionSort(arr, l, r)
                return
            m = l + int((r - l)/2)
            self._mergeSort(arr, l, m)
            self._mergeSort(arr, m + 1, r)
            if arr[m]>arr[m+1]:
                self._merge(arr, l, m, r)
    
        def _mergeSort_advance(self,arr,l,r):
            for  i in range(l,r+1,16):  #先对每15个数一个区块进行排序
                insertionSort(arr, i, min(i + 15, r))
            sz = 16
            for  sz in range(16,r+1,sz): #从小范围开始merge,不断扩大范围
                for i in range(0,r+1-sz,2*sz): ##对arr[i..i+sz-1]和arr[i+sz...+i+2*sz-1]进行归并
                    if arr[i+sz-1]>arr[i+sz]:
                        self._merge(arr,i,i+sz-1,min(i+sz+sz-1,r))
    
        def _merge(self, arr, l, m, r):
            n1 = m - l + 1
            n2 = r - m
            # 创建临时数组
            L = [0] * (n1)
            R = [0] * (n2)
            # 拷贝数据到临时数组 arrays L[] 和 R[]
            for i in range(0, n1):
                L[i] = arr[l + i]
            for j in range(0, n2):
                R[j] = arr[m + 1 + j]
            # 归并临时数组到 arr[l..r]
            i = 0  # 初始化第一个子数组的索引
            j = 0  # 初始化第二个子数组的索引
            k = l  # 初始归并子数组的索引
            while i < n1 and j < n2:
                if L[i] <= R[j]:
                    arr[k] = L[i]
                    i += 1
                else:
                    arr[k] = R[j]
                    j += 1
                k += 1
            # 拷贝 L[] 的保留元素
            while i < n1:
                arr[k] = L[i]
                i += 1
                k += 1
            # 拷贝 R[] 的保留元素
            while j < n2:
                arr[k] = R[j]
                j += 1
                k += 1
    
    
    def insertionSort(arr,l,r):  ##对arr[l...r]范围的数组进行插入排序
        for i in range(l+1,r+1):
            key = arr[i]
            j = i - 1
            while j >= l and key < arr[j]:
                arr[j + 1] = arr[j]
                j -= 1
            arr[j + 1] = key
    
    
    if __name__=="__main__":
        n = 1000000
        import sys
        sys.setrecursionlimit(100000)  # 增加递归上限
    
        print('正常乱序列表')
        arr = [random.randint(1, n) for i in range(0, n)]
        merge = MergeSort(arr)
        merge_advance = MergeSort(arr)
        merge.mergeSort()
        merge_advance.mergeSort_advance()
    
    output:
    正常乱序列表
    自顶向下归并排序耗时: 10.93750810623169
    正确排序
    自底向上归并排序耗时: 0.6875119209289551
    正确排序
    

    相关文章

      网友评论

          本文标题:python归并排序

          本文链接:https://www.haomeiwen.com/subject/qrzwtltx.html