归并排序和逆序列算法

概述

排序问题是数据处理中常会遇到的问题,通常是解决相关问题的前处理过程。这类算法目前有很多,比如相对暴力的冒泡排序和插入排序法。这类暴力求解算法的时间复杂度一般为O(n2),显然这个时间复杂度无法满足工程的应用。所以,在暴力求解的基础上发展出了归并排序、堆排序以及快速排序,这类排序算法时间复杂度为O(nlog2n)。上述算法都是基于比较法去实现排序,还有部分算法并未采用比较法,这部分算法排序速度要更快一些,这类算法会在后面介绍。
本博客中展示了插入排序、归并排序以及基于归并排序算法衍生出的查找逆序列算法代码。

代码

插入排序

def InserSort(my_list):
    for i in range(1,len(my_list)):
        key=my_list[i]
        j=i-1
        while j>=0 and key<my_list[j]:
            my_list[j+1]=my_list[j]
            j-=1
        my_list[j+1]=key

归并排序

def Merge(leftList,rightList):
    tmpList=[]
    i=0
    j=0
    while i<len(leftList) and j<len(rightList):
        
        if leftList[i]<=rightList[j]:
            tmpList.append(leftList[i])
            i+=1
        else:
            tmpList.append(rightList[j])
            j+=1
    if j==len(rightList):
        for k in leftList[i:]:
            tmpList.append(k)
    else:
        for k in rightList[j:]:
            tmpList.append(k)
    return tmpList

def MergeSort(my_list):
    if len(my_list)<=1:
        return my_list
    middle=int(len(my_list)/2)
    left=MergeSort(my_list[:middle])
    right=MergeSort(my_list[middle:])
    
    return Merge(left,right)

if __name__=='__main__':
    TestList=[5,8,24,1,44,0]
   
    print(MergeSort(TestList))

查找逆序列

def GetPair(left,right,PairList):
    
    TmpList=[]#返回排序好的列表
    
    i=j=0
    
    while i<len(left) and j<len(right):
        if left[i]<=right[j]:
            TmpList.append(left[i])
            i+=1
        else:
            TmpList.append(right[j])
            for z in left[i:]:
                PairList.append(z)
                PairList.append(right[j])
            j+=1
    if i==len(left):
        for k in right[j:]:
            TmpList.append(k)
    else:
        for k in left[i:]:
            TmpList.append(k)
    return TmpList

def ReverseOrderPair(my_list,myPair):   
    if len(my_list)<=1:    
        return my_list
    mid=int(len(my_list)/2)
    LeftList=ReverseOrderPair(my_list[:mid],myPair)
    RightList=ReverseOrderPair(my_list[mid:],myPair)
    return GetPair(LeftList,RightList,myPair)
    
if __name__=='__main__':
    Pair=[]
    TestList=[1,2,3,4,5,6,7,0,12,2,4,7,66,45,85,14,2,5,8,6,5,12,44,3,5]
    print(ReverseOrderPair(TestList,Pair))
    print(Pair)
    print(len(Pair)/2)

说明

插入排序比较简单,只有两次循环嵌套,可以看出一共遍历了n-1 + n-2 + … + 2 + 1 = n * (n-1) / 2 = 0.5 * n ^ 2 - 0.5 * n,所以时间复杂度是O(n2)。

归并算法主要是考虑两个函数的时间花销:一、数组划分函数MergeSort();二、有序数组归并函数Merge()。
Merge()函数的时间复杂度为O(n),因为该函数代码中有2个长度为n的循环。
MergeSort()在计算长度为n的归并排序所消耗的时间 T[n],那么调用MergeSort()函数划分两部分,那每一小部分排序好所花时间则为 T[n/2],而最后把这两部分有序的数组合并成一个有序的数组Merge()函数所花的时间为 O(n),最后时间复杂度的计算公式为:
T [ n ] = 2 T [ n / 2 ] + O ( n ) T[n] = 2T[n/2] + O(n) T[n]=2T[n/2]+O(n)
这种递归调用函数时间复杂度的计算可以使用主方法或者枚举法。归并算法的整个过程展开来就是一个具有n个根节点的二叉树结构,共有log2n个层,每一层都需要进行时间复杂度为 O(n)的Merge()函数,所以归并算法时间复杂度为O(nlog2n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值