主要排序演算法總結
阿新 • • 發佈:2018-12-07
一、穩定排序與不穩定排序
相等的元素排序之後相對位置不變就是穩定排序,反之就是不穩定排序。
二、主要排序演算法
1、氣泡排序
思想:遍歷列表裡的每個元素,每趟遍歷的元素都與後面的元素進行比較,
如果大於下一個元素就交換位置,如果小於下一個元素就不交換,最終都找到最大的放在列表最後,遍歷的趟數就是列表長度減1。
# 最小比較次數 C = n - 1
# 最小交換移動次數 M = 0
# 時間複雜度為 O(n)
# 最大比較次數 C = n*(n-1)/2
# 最大交換移動次數 M = 3n*(n-1)/2
# 時間複雜度為 O(n**2)
# 總的平均時間複雜度為O(n**2)
程式碼:
def bubble_sort(l):
for i in range(len(l)-1):
for j in range(0, len(l)-i-1):
if l[j] > l[j+1]:
l[j], l[j+1] = l[j+1], l[j]
print(l)
import random
l = random.sample(range(1, 100), 20)
print(l)
bubble_sort(l)
2、直接插入排序
思想: # 把列表看成是有序列表和無序列表的組合,剛開始有序列表是第一個元素,然後從第二個元素開始遍歷列表,即遍歷無序列表,讓無序列表中的每一個元素都跟有序列表的元素進行比較
# 所以第一個for迴圈就是遍歷無序列表,第二個for迴圈就是倒序遍歷有序列表,然無序列表的元素與有序列表的元素進行比較,如果小於有序列表的元素就交換位置,反之就退出有序列表
的比較迴圈,進行下一個無序列表元素與有序列表的的比較迴圈
程式碼:
1 import random 2View Code3 l = random.sample(range(1, 101), 20) 4 print(l) 5 6 for i in range(0, len(l)-1): 7 for j in range(i+1, 0, -1): 8 if l[j] < l[j-1]: 9 l[j], l[j-1] = l[j-1], l[j] 10 else: 11 break 12 print(l)
3、希爾排序
思想:按照一定的步長把列表分組,然後每組列表再按照插入排序演算法排序,步長就是列表的長度整除2,直到步長小於1結束分組。
程式碼:
1 import random 2 3 l = random.sample(range(1, 101), 20) 4 print(l) 5 d = len(l)//2 # 步長 6 while d >= 1: 7 for i in range(d): # 分了d組新列表 8 # 每個新列表使用直接插入法排序 9 for j in range(i, ((len(l)//d)-1)*d, d): # 遍歷新列表(無序列表),最後一個元素不用遍歷 10 for k in range(j+d, i, -d): # 遍歷有序列表,依次比較 11 if l[k] < l[k-d]: # 從小到大排序 12 l[k], l[k-d] = l[k-d], l[k] 13 else: 14 break 15 d = d // 2 16 print(l)View Code
4、選擇排序
思想:# 把整個列表看成是有序列表和無序列表的組合,剛開始有序列表為空,每次從無序列表中選出最小的值放在有序列表末尾,有序列元素增加一個無序就減少一個
# 具體的交換就是遍歷列表len(l)-1趟,沒趟都選出最小的值然後與無序列表的第一個元素交換
程式碼:
1 import random 2 l = random.sample(range(1, 100), 20) 3 print(l) 4 5 for i in range(len(l)-1): 6 min = i 7 for j in range(i+1, len(l)): 8 if l[j] < l[min]: 9 min = j 10 l[i], l[min] = l[min], l[i] 11 print(l)View Code
5、基數排序
思想:
# 外邊的while迴圈就是遍歷最大元素的位數,先從各位開始比較,然後遍歷陣列,把對應位數的值放在對應值編號的桶裡,即由字典包含的列表,
# 字典的鍵就是從0到9,列表就相當於桶用來放位數值與鍵相同的元素,元素遍歷結束後就把字典所有的值都相加成一個大列表,
# 然後再重複迴圈,整個迴圈順序:個--->十--->百---->.....,直到位數最高的元素的位數迴圈完了就結束
程式碼:
1 import random 2 3 arr = random.sample(range(1, 2000), 10) 4 print(arr) 5 6 d = 0 7 while True: 8 tag = 0 9 bucket = {0:[], 1:[], 2:[], 3:[], 4:[], 5:[], 6:[], 7:[], 8:[], 9:[]} 10 for i in arr: 11 k = i // 10 ** d 12 tag += k 13 bucket[k % 10].append(i) 14 if tag == 0: 15 print(arr) 16 break 17 arr = [] 18 for v in bucket.values(): 19 arr += v 20 d += 1 21 22 # 外邊的while迴圈就是遍歷最大元素的位數,先從各位開始比較,然後遍歷陣列,把對應位數的值放在對應值編號的桶裡,即由字典包含的列表, 23 # 字典的鍵就是從0到9,列表就相當於桶用來放位數值與鍵相同的元素,元素遍歷結束後就把字典所有的值都相加成一個大列表, 24 # 然後再重複迴圈,整個迴圈順序:個--->十--->百---->.....,直到位數最高的元素的位數迴圈完了就結束View Code
6、快速排序
思想:
# 每一趟都選出一個基準值,一般選取第一個為基準值,然後相當於把基準值的位置挖個坑,用兩個指標分別從最開始與最末尾移動
# 先從最右開始,高位指標指到的值與基準值比較,如果大指標就往下走,如果比基準值小,就與坑的位置交換,高位指標此時就指到坑的位置
# 然後低位指標從最左邊開始,低位指標指到的值與基準值比較,如果比基準值小就,就繼續往下一個走,如果比基準值大就與坑的位置交換,低位指標就指到坑的位置
# 重複上述步驟,如果低位指標與高位指標位置重合,就終止此次趟比較,返回低位指標的位置,並把基準值賦值給低位指標
# 然後按照低位指標的位置分割為兩個新列表,低位指標位置的值不在兩個列表之內
# 每個列表重複上述步驟進行排序,此處使用的是遞迴實現
# 最終終止條件是低位指標大於等於高位指標
程式碼:
1 import random 2 3 arr = random.sample(range(1, 101), 10) 4 print(arr) 5 6 7 def yitang(low, high): 8 basevalue = arr[low] 9 while low < high: 10 while arr[high] >= basevalue and low < high: 11 high -= 1 12 arr[low] = arr[high] 13 while arr[low] <= basevalue and low < high: 14 low += 1 15 arr[high] = arr[low] 16 arr[low] = basevalue 17 return low 18 19 20 def fast_sort(low, high): 21 if low < high: 22 mid = yitang(low, high) 23 fast_sort(low, mid-1) 24 fast_sort(mid+1, high) 25 26 27 fast_sort(0, len(arr)-1) 28 print(arr) 29 30 # 每一趟都選出一個基準值,一般選取第一個為基準值,然後相當於把基準值的位置挖個坑,用兩個指標分別從最開始與最末尾移動 31 # 先從最右開始,高位指標指到的值與基準值比較,如果大指標就往下走,如果比基準值小,就與坑的位置交換,高位指標此時就指到坑的位置 32 # 然後低位指標從最左邊開始,低位指標指到的值與基準值比較,如果比基準值小就,就繼續往下一個走,如果比基準值大就與坑的位置交換,低位指標就指到坑的位置 33 # 重複上述步驟,如果低位指標與高位指標位置重合,就終止此次趟比較,返回低位指標的位置,並把基準值賦值給低位指標 34 # 然後按照低位指標的位置分割為兩個新列表,低位指標位置的值不在兩個列表之內 35 # 每個列表重複上述步驟進行排序,此處使用的是遞迴實現 36 # 最終終止條件是低位指標大於等於高位指標View Code
7、歸併排序
程式碼:
1 import random 2 3 arr = random.sample(range(1, 101), 20) 4 print(arr) 5 6 7 def mergeSort(arr): 8 if len(arr) <= 1: 9 return arr 10 num = int(len(arr) // 2) 11 left = mergeSort(arr[:num]) 12 right = mergeSort(arr[num:]) 13 return merge(left, right) 14 15 16 def merge(left, right): 17 l, r = 0, 0 18 result = [] 19 while l < len(left) and r < len(right): 20 if left[l] < right[r]: 21 result.append(left[l]) 22 l += 1 23 else: 24 result.append(right[r]) 25 r += 1 26 result += left[l:] 27 result += right[r:] 28 return result 29 30 31 print(mergeSort(arr)) 32 print(arr)View Code
8、堆排序
程式碼:
1 import random 2 3 4 def big_endian(arr, start, end): 5 root = start 6 while True: 7 child = root * 2 + 1 8 if child > end: 9 break 10 if child + 1 <= end and arr[child] < arr[child + 1]: 11 child += 1 12 if arr[root] < arr[child]: 13 arr[root], arr[child] = arr[child], arr[root] 14 root = child 15 else: 16 break 17 18 19 def head_sort(arr): 20 first = len(arr) // 2 - 1 21 for start in range(first, -1, -1): 22 big_endian(arr, start, len(arr)-1) 23 for end in range(len(arr) - 1, 0, -1): 24 arr[0], arr[end] = arr[end], arr[0] 25 big_endian(arr, 0, end - 1) 26 return arr 27 28 29 def main(): 30 arr = random.sample(range(1, 200), 10) 31 print(arr) 32 print(head_sort(arr)) 33 34 35 if __name__ == '__main__': 36 main()View Code