算法 - 排序

冒泡排序 O(n2)

思想

重複地走訪過要排序的數列,一次比較兩個元素,若是他們的順序錯誤就把他們交換過來。走訪數列的工做是重複地進行直到沒有再須要交換,也就是說該數列已經排序完成。這個算法的名字由來是由於越小(大)的元素會經由交換慢慢"浮"到數列的頂端。html

圖示

代碼

 

def bubbleSort(arr):
    n = len(arr)
 
    # 遍歷全部數組元素
    for i in range(n):
        # 這裏的 -1 很精髓,恰好循環到倒數第二項,倒數第二項這一輪的時候會跟最後一項作比較,不須要再多走最後一遍了,沒有意義了
        # 不必定要 n-i-1 或者 n-i,哪怕是n都行,這樣就實打實的循環了n^2次了而已,也是能正常排序的,n-i-1或者n-i的目的是爲了優化而已
        for j in range(0, n-i-1):
            if arr[j] > arr[j+1] :
                arr[j], arr[j+1] = arr[j+1], arr[j]
 
arr = [64, 34, 25, 12, 22, 11, 90]
 
bubbleSort(arr)
 
print ("排序後的數組:")
for i in range(len(arr)):
    print ("%d" %arr[i]),

 

   

選擇排序 O(n2)

思想

遍歷無序列表,從中選出最小的元素,依次添加到新的列表中。算法

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,而後,再從剩餘未排序元素中繼續尋找最小(大)元素,而後放到已排序序列的末尾。以此類推,直到全部元素均排序完畢。數組

實操

實際操做的時候,並非真的建立一個新的列表用來有序的存放數據,由於那樣會形成額外的空間消耗,空間複雜度加大,因此其實通常都是用一個雙層循環作遍歷,在列表本地操做。ide

代碼

 

"""
外層循環從0~length,內層循環從i+1~length
比較兩個數的大小,若是後面的數比前面的小,則互換位置
"""

A = [64, 25, 12, 22, 11] 
  
for i in range(len(A)): 
    # 定義一個變量,用來存最小元素的下標,默認從i開始
    min_idx = i 
    for j in range(i+1, len(A)): 
        # 從第i+1處開始,跟原來最小數比較
        if A[min_idx] > A[j]: 
            # 若是當前j的元素比原來的最小數更小,則將當前元素的下標給到min_idx
            min_idx = j 
     # 將找出來的最小數和第i個位置的數進行交換
    A[i], A[min_idx] = A[min_idx], A[i] 
  
print ("排序後的數組:") 
for i in range(len(A)): 
    print("%d" %A[i]),        

 

 

插入排序 O(n2)

思想

經過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。 函數

從第二位數字開始,每個數字都試圖跟它前一個數字進行比較並作交換,重複該動做,直到前一個數字不存在或者小於等於當前數字時爲止。性能

實操

圖示難以理解,這裏有視頻地址:https://v.qq.com/x/page/p05308yhnyp.html優化

代碼

def insertionSort(arr): 
    for i in range(1, len(arr)):
        j = i - 1
        while j >= 0 and arr[j] > arr[j+1]:
            arr[j], arr[j+1] = arr[j+1], arr[j]
            j -= 1
  
  
arr = [12, 11, 13, 5, 6] 
insertionSort(arr) 
print ("排序後的數組:") 
for i in range(len(arr)): 
    print ("%d" %arr[i])

 

 

 

 

快速排序 O(n*log2n)

思想

快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分爲較小和較大的2個子序列,而後遞歸地排序兩個子序列。ui

步驟爲:spa

  • 挑選基準值:從數列中挑出一個元素,稱爲"基準"(pivot);
  • 分割:從新排序數列,全部比基準值小的元素擺放在基準前面,全部比基準值大的元素擺在基準後面(與基準值相等的數能夠到任何一邊)。在這個分割結束以後,對基準值的排序就已經完成;
  • 遞歸排序子序列:遞歸地將小於基準值元素的子序列和大於基準值元素的子序列排序。

遞歸到最底部的判斷條件是數列的大小是零或一,此時該數列顯然已經有序。code

選取基準值有數種具體方法,此選取方法對排序的時間性能有決定性影響。

圖示

代碼

def partition(arr,low,high): 
    i = ( low-1 )         # 最小元素索引
    pivot = arr[high]     
  
    for j in range(low , high): 
  
        # 當前元素小於或等於 pivot 
        if   arr[j] <= pivot: 
          
            i = i+1 
            arr[i],arr[j] = arr[j],arr[i] 
  
    arr[i+1],arr[high] = arr[high],arr[i+1] 
    return ( i+1 ) 
  
 
# arr[] --> 排序數組
# low  --> 起始索引
# high  --> 結束索引
  
# 快速排序函數
def quickSort(arr,low,high): 
    if low < high: 
  
        pi = partition(arr,low,high) 
  
        quickSort(arr, low, pi-1) 
        quickSort(arr, pi+1, high) 
  
arr = [10, 7, 8, 9, 1, 5] 
n = len(arr) 
quickSort(arr,0,n-1) 
print ("排序後的數組:") 
for i in range(n): 
    print ("%d" %arr[i]),

 

歸併排序

堆排序

希爾排序

相關文章
相關標籤/搜索