python實現七大經典排序算法

本文主要使用python來實現七個經典的排序算法,分別是:冒泡排序、選擇排序,插入排序,快速排序,希爾排序,堆排序和歸併排序。


一、相關歸納總結



1、時間複雜度

O(N^2): 冒泡排序、選擇排序,插入排序

O(N*logN): 快速排序,希爾排序,堆排序和歸併排序

2、空間複雜度

O(1):插入排序,冒泡排序,選擇排序,堆排序,希爾排序

O(logN)~O(N):快速排序

O(N):歸併排序

3、穩定性:

若待排序的序列中,存在多個相同關鍵字的記錄,經過排序,這些記錄的相對次序保持不變,則稱該算法是穩定的;若經過排序後,記錄的相對次序發生了改變,則稱該算法是不穩定的

穩定的冒泡排序,插入排序、歸併排序和基數排序

不穩定的:選擇排序,快速排序,希爾排序,堆排序

不穩定舉例說明:

選擇排序:

  ---->   


快速排序:


希爾排序:

---->

堆排序:


4、使用場景:

設待排序的元素個數爲n:

當n較大,則應採用時間複雜度爲O(NlogN)的排序算法:快速排序,堆排序或者歸併排序

  • 快速排序:是目前基於比較的內部排序中被認爲是最好的方法,當待排序的關鍵字是隨機分佈時,快速排序的平均時間最短。
  • 堆排序:如果內存空間允許
  • 歸併排序:內存空間允許,且要求穩定性

當n較小,可採用直接插入和選擇排序

  • 直接插入排序:當元素分佈有序,且要求穩定性(優先)
  • 選擇排序:當元素分佈有序,且不要求穩定性

一般不使用或不直接使用傳統的冒泡排序。


二、算法實現


1、冒泡排序:

基本思想:

假設待排序表長爲n,從前往後(或從後往前)兩兩比較相鄰元素的值,若爲逆序(即A[i]>A[i+1]),則交換他們,直到序列比較完。我們稱它爲一趟冒泡,會將最大的元素交換到待排序的最後一個位置。下一趟冒泡時,前一趟確定的最大元素不再參加比較,待排序列減少一個元素,每趟冒泡的結果把序列中的最大元素方法了序列的最終位置。這樣最多做n-1趟冒泡就能把左右的元素排好序。

實現代碼:

def bubble_sort(list):
    for i in range(len(list)-1):
        for j in range(len(list)-i-1):
            if list[j]>list[j+1]:
                list[j+1],list[j] = list[j],list[j+1]
    return list
2、選擇排序:

基本思想:

每一趟(例如第i趟)在後面n-i+1(i=1,2,...,n-1)個待排序元素中選取關鍵字最小的元素,作爲有序子序列的第i個元素,直到n-1趟做完,就不用再選了。

實現代碼

def select_sort(list):
    for i in range(len(list)-1):
        min = i
        for j in range(i+1,len(list)):
            if list[j]<list[min]:
                min = j
        list[i],list[min] = list[min],list[i]
    return list
3、插入排序

基本思想:

將一個記錄插入到一排序好的有序表中,從而得到一個新的,記錄數增1的有序表。即:現將序列的第一個記錄看成是一個有序的子序列,然後從第二個記錄進行插入,直至整個序列有序爲止。

實現代碼:

def insert_sort(list):
    for i in range(1,len(list)):
        key = list[i]
        for j in range(i-1,-1,-1):
            if list[j]>key:
                list[j+1] = list[j]
                list[j] = key
    return list
4、快速排序

基本思想:

  1. 選擇一個基準元素,通常選擇第一個元素或者最後一個元素
  2. 通過一趟排序將待排序的記錄分割成獨立的兩部分,其中一部分的記錄值均比基準元素小,另一部分元素值均比基準元素大
  3. 此時基準元素在其排好序後的正確位置
  4. 然後分別堆這兩部分用同樣的方法繼續進行排序,直到整個序列有序

實現代碼:

def quick_sort(list,left,right):
    if left<right:
        mid = partition(list,left,right)
        quick_sort(list,0,mid-1)
        quick_sort(list,mid+1,right)
    return list

def partition(list,left,right):
    temp = list[left]
    while left<right:
        while left<right and list[right]>=temp:
            right -= 1
        list[left] = list[right]
        while left<right and list[left]<=temp:
            left += 1
        list[right] = list[left]
    list[left] = temp
    return left


5、希爾排序

希爾排序也叫縮小增量排序

基本思想:

  1. 首先取一個正數d1 = n/2,將元素分爲d1個組,每組相鄰元素之間的距離爲d1,在各組內進行直接插入排序
  2. 取第二個正數d2 = d1 / 2,重複上述分組排序過程,直到di = 1,即所有的元素都在同一組進行直接插入排序。
  3. 希爾排序每趟並不使某些元素有序,而是使整體數據越來越接近有序,最後一趟排序使得所有數據有序

實現代碼:

def shell_sort(list):
    #dk爲步長
    dk = len(list)/2
    while dk>=1:
        for i in range(dk,len(list)):
            temp = list[i]
            j = i-dk
            while j>=0 and temp<list[j]:
                list[j+dk] = list[j]
                j -= dk
            list[j+dk] = temp
        dk = dk/2
    return list


6、堆排序

堆排序是一種樹形選擇排序方法

基本思想

  1. 建立堆
  2. 得到堆頂元素,爲最大元素
  3. 去掉堆頂元素,將堆最後一個元素放到堆頂,此時可通過一次調整重新使堆有序
  4. 堆頂元素爲第二大元素
  5. 重複步驟3,直到堆變空

實現代碼:

#堆排序
def heap_sort(list):
    #初始建堆
    build_max_heap(list,len(list))
    #n-1趟的交換和建堆過程
    for i in range(1,len(list))[::-1]:
        #將堆頂元素list[0]和最後一個元素list[i]交換
        list[i],list[0] = list[0],list[i]
        #把剩餘的i-1個元素整理成堆
        adjust_down(list,0,i)
    return list

#創建堆
# n個節點的完全二叉樹,最後一個節點是第n/2個節點的孩子。
#對於大根堆,若根節點的關鍵字小於左右子女中關鍵字較大者,則交換,使該子樹成爲堆。
#之後向前依次對各節點((size/2)-1~1)爲根的子樹進行篩選。
def build_max_heap(list,size):
    #從size/2~1,反覆調整堆。
    for i in range(0,size/2)[::-1]:
        adjust_down(list,i,size)

#調整堆
def adjust_down(list,i,size):
    max= i
    lchild = 2*i + 1
    rchild = 2*i + 2
    if rchild < size :
        if lchild < size and list[lchild] > list[max]:
            max = lchild
        if rchild < size and list[rchild] > list[max]:
            max = rchild
        if max!= i:
            list[max],list[i] = list[i],list[max]
            #繼續向下調整堆
            adjust_down(list,max,size)


7、歸併排序
基本思想:

歸併排序是將兩個(或兩個以上)有序表合併成一個新的有序表,即把待排序序列分爲若干個子序列,每個子序列是有序的。然後再把有序子序列合併爲整體有序序列

圖例:


實現代碼:

def merge_sort(list):
    if len(list)<=1:
        return list
    mid = len(list)/2
    left = merge_sort(list[:mid])
    right = merge_sort(list[mid:])
    return merge(left,right)

def merge(left,right):
    i,j = 0,0
    #新建一個數組,用來存儲將left和right排好序的值
    result = []
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    result += left[i:]
    result += right[j:]
    return result






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