《算法導論》提供的快速排序時而輸入數據有序時的化解方法(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次方

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章