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)。這個現象稱為短路計算 |