《算法导论》提供的快速排序时而输入数据有序时的化解方法(5分法取中位数)

自己本来照着《算法导论》提供的思路折腾了一个函数,可是,一经10w数据测试,就发现自己还是太年轻,too yong,too simple,慢得掉渣。只得去找因特网上先行者们留下的代码了,算法导论之...,再次膜拜大牛们

不经优化的方法:

sys.setrecursionlimit(1000000000)   
def quick_sort(array, l, r):  
    if l < r:  
        q =partition(array, l, r)
        quick_sort(array, l, q - 1)  
        quick_sort(array, q + 1, r)

def partition(array, l, r):  
    x = array[r]  
    i = l - 1  
    for j in range(l, r):  
        if array[j] <= x:  
            i += 1  
            array[i], array[j] = array[j], array[i]  
    array[i + 1], array[r] = array[r], array[i+1] 
    return i + 1  

经5分法取中位数优化后:

def insertion_sort(a_list):     
    last=len(a_list)-1
    if last>0:
        a_list1=insertion_sort(a_list[:last])
        i=len(a_list1)-1
        temp=a_list[last]
        while i>=0:
            if temp<=a_list1[i]:
                i-=1
            else:
                break
        for pos in range(last,i+1,-1):
            a_list[pos]=a_list1[pos-1]
        a_list[i+1]=temp
        a_list[:i+1]=a_list1[:i+1]
    return a_list   

def partition2(a_list,key):  
    p=a_list.index(key)      #Question: such an enbarrasing thing to find the key from a_list, how to do?
    pivot=a_list[p]
    a_list[p]=a_list[0]
    a_list[0]=pivot
    i=0
    j=1
    while j<len(a_list):
        if a_list[j]<pivot:
            i+=1
            a_list[i],a_list[j]=a_list[j],a_list[i]
        j+=1
    a_list[0],a_list[i]=a_list[i],a_list[0]
    return (i+1,a_list[:i],a_list[i+1:])


def mid_select(a_list):
    if len(a_list)>5:
        k=(len(a_list)+1)//2
        a_list_next=a_list[:]
        base=0
        while a_list_next !=[]:
            a_list_mid =[]
            for i in range(len(a_list_next)//5):  
                a_list_part=a_list_next[5*i:5*(i+1)]
                a_list_order=insertion_sort(a_list_part)
                mid_part=a_list_order[2]
                a_list_mid.append(mid_part)
            if len(a_list_next)%5 !=0:
                a_list_part=a_list_next[5*(len(a_list_next)//5):]
                a_list_order=insertion_sort(a_list_part)
                mid_part =a_list_order[(len(a_list_order)+1)//2-1]
                a_list_mid.append(mid_part)
            mid= mid_select(a_list_mid)
            i,a_list_left,a_list_right = partition2(a_list_next,mid)  

            i =base +i                      # revise the index of mid in the original a_list
            if i==k:
                return mid 
            elif i <k:
                a_list_next=a_list_right
                base =i
            else:
                a_list_next=a_list_left
        return False
    else:
        a_list_order=insertion_sort(a_list)
        return a_list_order[(len(a_list)+1)//2-1]

经主函数调用:

if __name__=='__main__':
    N=100000
    nums=[]
    for i in range(N,0,-1):#随机序列输入就不Demon了,性能差不多;这里就设下最坏情况下的序列之一了---有序序列
        #n=random.randint(1,100000000)
        nums.append(i)
  
    start=time.clock()
    mid_select(nums)
    #quick_sort(nums,0,len(nums)-1)
    end=time.clock()
    print('time is',end-start)

Demon:

10w有序输入数据:


结果是:经优化后快排处理10w有序输入数据仍然性能未减,而未经优化下算得计算机死机,n^2的复杂度,10w的平方为10的12次方

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值