Python經典排序算法

http://www.javashuo.com/article/p-apvjfrqu-dq.html這個文章很nicehtml

https://www.bilibili.com/video/av685670?from=search&seid=1637373535603658338這個動圖優秀算法

https://www.icourse163.org/course/ZJU-93001   MOOC浙大 數據結構 陳越、何欽銘shell


冒泡排序、選擇排序、插入排序這三個是最慢也是最經典的三個排序算法api

快速排序對於大的亂數串列通常相信是最快的已知排序數組

冒泡排序 bubble sort

最簡單的排序算法,也是效率最差的,由於它必須在最終位置知道前交換,浪費許多「交換操做」bash

若是列表已經排序,則是最好狀況,遍歷期間無需交換,若是發現已經排序,能夠提早終止,這種修改下的冒泡一般稱爲短冒泡排序數據結構


時間複雜度: 平均O(n^2)    最差O(n^2)     最好O(n)架構

空間複雜度:O(1)app

穩定less

#測試輸入數組
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#冒泡排序
for i in range(len(alist)-1):
    for j in range(len(alist)-1-i):
        if alist[j] > alist[j+1]:
            alist[j],alist[j+1] = alist[j+1],alist[j]
        
#排序結果輸出
print('sorted:',alist)

選擇排序 selection sort

選擇排序改進了冒泡排序,每次遍歷列表只作一次交換


時間複雜度:平均O(n^2)    最差O(n^2)    最好O(n^2)

空間複雜度:O(1)

不穩定

#測試輸入數組
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#選擇排序
for i in range(len(alist)-1):
    least = i
    for j in range(i+1,len(alist)):
        if alist[j] < alist[least]:
            least = j
    if least != i:
        alist[least],alist[i] = alist[i],alist[least]

#排序結果輸出
print('sorted:',alist)

插入排序 insertion sort

它始終在列表的較低位置維護一個排序的子列表,而後將每一個新項 「插入」 回先前的子列表,使得排序的子列表成爲較大的一個項


時間複雜度: 平均O(n^2)    最差O(n^2)     最好O(n)

空間複雜度:O(1)

穩定

#測試輸入數組
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#插入排序
for i in range(1,len(alist)):
    j = i;
    while j>0 and alist[j-1]>alist[j]:
        alist[j-1],alist[j] = alist[j],alist[j-1]
        j -= 1
        
#排序結果輸出
print('sorted:',alist)

希爾排序 shell sort

是1959年Shell發明,第一個突破O(n^2)的排序,是對簡單插入排序的改進,與插入排序不一樣的是它優先比較距離較遠的元素,又叫「遞減增量排序」

是針對插入排序如下2特色改進:在對幾乎已經排好序的數據操做時,效率高,便可以達到線性排序的效率;通常來講是低效的,由於插入排序每次只能將數據移動一位

希爾排序經過將比較的所有元素分爲幾個區域來提高插入排序的性能。這樣可讓一個元素能夠一次性地朝最終位置前進一大步

gap概念,gap遞減,最後一步就是插入排序,可是此時幾乎已經排好序了

gap是希爾排序核心

出名的gap設置Marcin Ciura's gap sequence ,gaps = [701, 301, 132, 57, 23, 10, 4, 1],不過下面例子用數組長度不斷整除2獲得的序列做爲gaps


時間複雜度:平均O(n(logn)^2)    最差O(n^2)    最好O(n)

空間複雜度:O(1)

不穩定

#測試輸入數組
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#希爾排序
gap = len(alist)//2
while gap>0:
    #對每一個gap作插入排序
    for i in range(gap,len(alist)):
        j = i
        while j>=gap and alist[j-gap]>alist[j]:
            alist[j-gap],alist[j] = alist[j],alist[j-gap]
            j -= gap           
    gap = gap//2

#排序結果輸出
print('sorted:',alist)

歸併排序 merge sort

分而治之的策略來提升性能,是分治法的典型應用

歸併排序是一種遞歸算法,不斷將列表拆分爲一半

二路歸併 多路歸併

缺點是在合併過程須要額外存儲空間


時間複雜度: 平均O(nlogn)    最差O(nlogn)      最好O(nlogn)

空間複雜度:O(n)

穩定

#測試輸入數組
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#歸併排序
def merge_sort(ilist):   
    def merge(left, right):
        result = []
        while left and right:
            result.append((left if left[0] <= right[0] else right).pop(0))
        return result + left + right
    
    if len(ilist) <= 1:
        return ilist
    mid = len(ilist) // 2
    return merge(merge_sort(ilist[:mid]), merge_sort(ilist[mid:]))

#排序結果輸出
print('sorted:',merge_sort(alist))

快速排序 quick sort

與歸併排序相同,採用分治法,而不使用額外存儲

是對冒泡排序的改進

一般明顯比其餘算法更快,由於它的內部循環能夠在大部分的架構上頗有效的達成

簡單的版本和歸併排序同樣很差,須要額外存儲空間,可是能夠改成in-place版本,也就不要額外空間了


時間複雜度: 平均O(nlogn)    最差O(n^2)      最好O(nlogn)

空間複雜度:O(nlogn)

不穩定

#測試輸入數組
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#快速排序
def quick_sort(ilist): 
    length = len(ilist)
    if length <= 1:
        return ilist
    else:
        # Use the last element as the first pivot
        pivot = ilist.pop()
        # Put elements greater than pivot in greater list
        # Put elements lesser than pivot in lesser list
        greater, lesser = [], []
        for element in ilist:
            if element > pivot:
                greater.append(element)
            else:
                lesser.append(element)
        return quick_sort(lesser) + [pivot] + quick_sort(greater)

#排序結果輸出
print('sorted:',quick_sort(alist))

堆排序 heap sort

是對選擇排序的一種改進

利用堆這種數據結構所設計的算法 近似徹底二叉樹

堆一般經過一維數組實  大根堆  小根堆


時間複雜度:平均O(nlogn)    最差O(nlogn)      最好O(nlogn)

空間複雜度:O(1)

不穩定

#測試輸入數組
alist = [27, 33, 28, 4, 2, 26, 13, 35, 8, 14]

#堆排序
def heapify(unsorted, index, heap_size):
    largest = index
    left_index = 2 * index + 1
    right_index = 2 * index + 2
    if left_index < heap_size and unsorted[left_index] > unsorted[largest]:
        largest = left_index

    if right_index < heap_size and unsorted[right_index] > unsorted[largest]:
        largest = right_index

    if largest != index:
        unsorted[largest], unsorted[index] = unsorted[index], unsorted[largest]
        heapify(unsorted, largest, heap_size)
        
def heap_sort(unsorted):
    n = len(unsorted)
    for i in range(n // 2 - 1, -1, -1):
        heapify(unsorted, i, n)
    for i in range(n - 1, 0, -1):
        unsorted[0], unsorted[i] = unsorted[i], unsorted[0]
        heapify(unsorted, 0, i)
    return unsorted

#排序結果輸出
print('sorted:',heap_sort(alist))
相關文章
相關標籤/搜索