1. 程式人生 > >Python排序演算法:插入排序

Python排序演算法:插入排序

什麼是插入排序

插入排序(Insertion Sort)是一種簡單直觀的排序演算法。
通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃描,找到相應位置並插入。
插入排序在實現上,在從後向前的掃描過程中,需要把已排序元素逐步向後挪位,為最新元素提供插入空間。

插入排序動圖

(用MD寫的,插入的動圖貌似是不會動了。。。。)
從第二位開始,依次和前面的數進行比較,第一位預設已經是有序的了;
第三位和前兩位依次比較,第四位和前三位依次比較;
前面的元素均為有序,後面為無序;
即:
先將前兩個排序
再將前三個排序
前四個

一直到最末尾

程式碼實現

def insertion_sort(list):
    n = len(list)
    for i in range(1,n):
        for j in range(i,0,-1):
            if list[j] < list[j-1]:
                list[j],list[j-1] = list[j-1],list[j]
            else:
                break
    return list

解析

def insertion_sort(list):
    n = len(list)
    for
i in range(1,n):

首先,得到資料的長度後,開始從 1 遍歷整個資料(從 1 開始而不是從 0 開始),因為第一個元素已經是有序的了,所以不用再排序了。

def insertion_sort(list):
    n = len(list)
    for i in range(1,n):
        for j in range(i,0,-1):
            if list[j] < list[j-1]
                list[j],list[j-1] = list[j-1],list[j]

從當前元素開始依次往前掃描
判斷與前一位相比大小

優化插入排序

上面的程式碼中,交換操作很費操作步驟,因為一次交換,相當於 3 次複製,這還不包括內部的函式過程。所以我們可以根據這點進行優化,把原本交換操作,改成賦值語句。

def insertion_sort(list):
    n = len(list)
    for i in range(1, n):
        key = list[i]
        j = i - 1
        while j >= 0 and list[j] > key:
            list[j+1] = list[j]
            j -= 1
        list[j+1] = key
    return list

list1 = [5,6,2,7,9,0,1,3,8,4]
print("原列表:%s" %list1)
insertion_sort(list1)
print("排序後列表:%s" %list1)

>> 原列表:[5, 6, 2, 7, 9, 0, 1, 3, 8, 4]
   排序後列表:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

優化後代碼解析

def insertion_sort(list):
    n = len(list)
    for i in range(1, n):
        key = list[i]
        j = i - 1

首先,遍歷列表每一位,然後用 key 儲存當前位置的值; j 表示前一位;

def insertion_sort(list):
    n = len(list)
    for i in range(1, n):
        key = list[i]
        j = i - 1
        while j >= 0 and list[j] > key:

然後,使用 while 條件迴圈,判斷前一位的元素是否比當前位的大,並且前一位的下標 >= 0(即最小到第一位)
這樣就可以有條件的進行迴圈,而不像原來的寫法那樣一個個迴圈遍歷。

def insertion_sort(list):
    n = len(list)
    for i in range(1, n):
        key = list[i]
        j = i - 1
        while j >= 0 and list[j] > key:
            list[j+1] = list[j]
            j -= 1
        list[j+1] = key
    return list

符合條件後,就可以把原來的元素位進行賦值操作,賦值成較大的元素;然後依次將較大的元素賦值給相比較的兩位中的後面一位。直至比較到第一位或比較到某位元素小於當前元素的值。將儲存起來的該位的值插入即可。

例:list = [1,4,5,3]
- 1迴圈 i 到第四位了 (i = 3)
- key儲存 list[3] 的值,即 key = 3
- 然後將 list[2] 與 key = 3 比較,5>3,則將5的值賦給後面那位,即[1,4,5,5]
- 再將 list[1] 與 key = 3 比較 ,4>3,則將4的值賦給後面那位,即[1,4,4,5]
- 再將 list[0] 與 key = 3 比較 ,1<3,不符合迴圈條件
- 於是執行後面的語句,將 key = 3 值賦給 list[0+1] 即list[1],即[1,3,4,5]

補小知識點

range()函式

補個range()函式小知識點:

生成順序的:

for i in range(1,10,1)
    print(i)

>> 1,2,3,4,5,6,7,8,9

生成倒序的:

for i in range(10,0,-1)
    print(i)

>> 10,9,8,7,6,5,4,3,2,1

因為 顧頭不顧尾 ,所以生成的數減到 1 即停止了,不包括 0 。

& 和 and

優化後的程式碼,while 條件使用了兩個條件與的判斷
最初使用了 & 運算子,結果導致始終進不了迴圈,然後改為 and 即正常

運算子 名稱 說明 例子
& 按位與 數的按位與 5&3 得1
and 布林“與” 如果x為False,x and y返回False,否則它返回y的計算值 x = False; y = True; x and y,由於x是False,返回False。在這裡,Python不會計算y,因為它知道這個表示式的值肯定是False(因為x是False)。這個現象稱為短路計算