排序算法總結-python實現

最近在複習軟考,把看到的排序算法整理了一下,之所以用python寫,是因爲python寫起來簡單....好吧,後來寫的時候發現有些地方用C寫還方便些。python雖然簡潔,但用起來效率感覺還是有些低,不過這不是重點啦。。。

1.代碼與說明

# -*- coding: utf-8 -*-

def bubbleSort(Data):
    '''冒泡排序: 時間複雜度最好O(n),平均O(n*n),最壞O(n*n),輔助空間 O(1),算法穩定
       n個數,每次從第一個數開始和相鄰的數比較,將大的冒泡到後面去。第一趟將最大的冒泡到最後,
       然後第二次只需比較0~n-1,將其中最大的冒泡到n-1,依次下去...總共進行n-1趟排序即可
    '''
    if Data:
        for i in range(len(Data)):
            for j in range(len(Data)-i-1):
                if Data[j]>Data[j+1]:
                    Data[j],Data[j+1]=Data[j+1],Data[j]
    return Data

def quickSort(Data,low,high):
    '''快速排序:O(n*logn),O(n*logn),O(n*n),O(n*logn),不穩定
        冒泡的改進,被認爲是當前最優秀的內部排序算法(當然這也不是絕對的,還要看具體情況)。實現基於分治法:分解-解決-合併。
        基本思想:
        1.從數列中取出一個基數,
        2.將數列中比他大的放在右邊,小的在左邊。
        3.兩邊區間重複2,直到各區間只有一個數。
        整個算法中的基數就是個坑,跳來跳去,總之比他小始終放一邊,大的放另一邊就行
        參考:http://blog.csdn.net/morewindows/article/details/6684558
    '''
    if low < high:
        left,right,base=low,high,Data[low]
        while left <right:
            #從後往前找比base小的數
            while left <right and Data[right] >=base:
                right-=1
            if left < right:
                Data[left]=Data[right]
                #left+=1 這裏直接+1更快,因爲Data[left]必然小於base,下次循環不用算
            #從前往後找比base大的數
            while left <right and Data[left] < base:
                left+=1
            if left <right:
                Data[right]=Data[left]
                #right-=1
        #left=right時一趟循環終止,base填回坑裏去
        Data[left]=base             
        quickSort(Data,low,left-1)  #遞歸左邊
        quickSort(Data,left+1,high) #遞歸右邊
        
def insertSort(Data):
    '''插入排序: 時間複雜度最好O(n),平均O(n*n),最壞O(n*n),輔助空間 O(1),算法穩定
        如果Data不爲空則開始比較。Data[0]~Data[j]是排好的序列L1,key是未排待插入數據
        如果key小於L1的最大值則將進行插入操作,while循環找到比key小的index並將key插入
        在index後面。while循環用來尋找插入位置並將比key大的數後移,如果key本身比L1的
        最大值還大則無需插入,直接for循環比較下一個
    '''
    if Data:
        for i in range(1,len(Data)):
            key,j = Data[i],i-1
            while j>=0 and Data[j] > key:
                Data[j+1]=Data[j]
                j-=1
            Data[j+1]=key
    return Data

def selectSort(Data):
    '''選擇排序: 時間複雜度最好O(n*n),平均O(n*n),最壞O(n*n),輔助空間 O(1),算法不穩定
        n個數,每一趟從待排序列L2中選擇最大(或最小)數順序放在已排好序列L1後面(或前面)
        總共經過n-1趟可排好,與插入排序相比,都是將數據分爲已排和未排序列並將未排元素整理
        到已排序列中,不同的是插入排序在未排序列中按序整理,選排則是按大小選擇整理。
    '''
    if Data:
        for i in range(len(Data)-1):
            minnum=i
            for j in range(i+1,len(Data)):#在L2中尋找最小值
                if Data[j]<Data[minnum]:
                    minnum=j
            if minnum != i:#如果找到直接交換,插入在L1後面
                Data[i],Data[minnum]=Data[minnum],Data[i]
    return Data
                    
def shellSort(Data):
    '''希爾排序: 時間複雜度最好未知,平均O(pow(n,1.25),最壞未知,輔助空間 O(1),不穩定
        插入排序的改進,將數據分組,每組m個(m叫步長)每次對每組的第i個元素排序,
        然後再分組,再排序,直到步長爲1.至於分組的方法需要理論推導,此處每次步長都取n/2減半
        更好的步長選擇方法見wiki:http://zh.wikipedia.org/wiki/希爾排序
        其他實現方法:http://blog.csdn.net/morewindows/article/details/6668714
    '''
    n=len(Data)
    if  n > 1:
        gap=n/2 
        while gap > 0:   
            for i in range(gap):#按步長插入排序
                for j in range(i+gap,n,gap):
                    if Data[j] < Data[j-gap]:
                        key = Data[j]
                        k=j-gap
                        while k >=0 and Data[k] > key:
                            Data[k+gap]=Data[k]
                            k-=gap
                        Data[k+gap]=key
            gap/=2
    return Data
                    
        
if __name__ =="__main__":
    Data=[3,5,1,56,3,7,34,21,8]
    print Data
    #insertSort(Data)
    #bubbleSort(Data)
    #selectSort(Data)
    #shellSort(Data)
    quickSort(Data,0,len(Data)-1)
    print Data 
            
            
            
            

2.python內置排序

實際上python列表內置了排序算法。sort和sorted。

3.瞎扯

1.內部排序是指待排序列完全存放在內存中進行的排序,適合不太大的序列。包括

插入排序(直接插入排序)

快速排序

選擇排序(簡單選擇排序)

冒泡排序

希爾排序

堆排序

歸併排序

2.外部排序指能處理大量數據的排序算法,數據不能一次裝入內存,通常要藉助外存儲器。常採用排序-歸併策略,比如外歸併排序。詳情參考wiki:http://zh.wikipedia.org/wiki/外排序 

3.python中沒有自增和自減運算,這在寫代碼的時候異常不方便。當然咯,這也與python的設計目標有關係。python的設計哲學是優雅,明確、簡單。他們可能認爲這樣不太優雅,不利於代碼的可讀性,譬如js也不推薦使用++和--。另外一個原因,那就是python不提供像C那樣直接操作內存的功能。當執行a+=1時,C會直接修改a在內存中的值,而python則會在內存中新建一個整型變量(也不完全這樣,有些小數據python會複用,見下面第4點),然後讓a指向它。所以如果要執行a++,C語言中a還是那個a,而python中的a已經不是原來的a了,這樣就亂套了!

說到這裏,再扯一下python中的可變對象和不可變對象。python中所有對象都是值的引用。不可變指的是值不可變。要修改變量的值就要在內存中新建一個值並讓變量指向它,原來的如果不用就會被GC回收。可變對象不需要在其他地方申請內存,直接在自己後面申請/釋放空間即可,原地址不變。

4.對於小數值整型對象,比如1~100,python虛擬機在啓動時會先在內存中生成好,放在緩衝區以便於快速調用。看下面的例子:

開始a,b爲100,a is b是True,說明a,b指向內存中同一個對象,後面值變大了,a=100000時python會在內存中新建一個對象,b=100000也會新建一個對象,所以a,b指向不同對象,故爲False。id(a)是查看a的地址。

5.有關for循環,實質上是一個遍歷,for i in range(0,10),range()會生成一個0到9的list讓i遍歷。這樣就有一個缺陷:i在循環前每一步的值是確定的,不能動態改變。而在C語言中,for(int i=n/2,i>0,i=i/2),i是隨着循環每次都會改變的。不過事實上,i的值在循環前也是可以推算出來的,因此肯定是可以用python的for循環代替C的for(int i=n/2,i>0,i=i/2),只不過LZ還沒想到,誰知道還麻煩說一聲,哈哈!

發佈了48 篇原創文章 · 獲贊 13 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章