python基礎——15.十大排序演算法&九九乘法表
-
九九乘法表
for i in range(1, 10): for j in range(1, i+1): print("{}*{}={}".format(j, i, i*i), end="\t") print("")
-
一句程式碼寫九九乘法表
print("\n".join([" ".join(["{}*{}={}".format(j, i, format(i*j, "<3d")) for j in range(1, i+1)]) for i in range(1, 10)]))
-
氣泡排序
def bubbleSort(lst): for i in range(0, len(lst)-1): result = False for j in range(0, len(lst)-1-i): if lst[j] > lst[j+1]: lst[j], lst[j+1] = lst[j+1], lst[j] result = True if not result: return lst return lst print(bubbleSort(lst))
演算法分析
氣泡排序是一種簡單直接暴力的排序演算法,為什麼說它暴力?因為每一輪比較可能多個元素移動位置,而元素位置的互換是需要消耗資源的,所以這是一種偏慢的排序演算法,僅適用於對於含有較少元素的數列進行排序。
穩定性:我們從程式碼中可以看出只有前一個元素大於後一個元素才可能交換位置,所以相同元素的相對順序不可能改變,所以它是穩定排序
比較性:因為排序時元素之間需要比較,所以是比較排序
時間複雜度:因為它需要雙層迴圈n*(n-1)),所以平均時間複雜度為O(n^2)
空間複雜度:只需要常數個輔助單元,所以空間複雜度為O(1),我們把空間複雜度為O(1)的排序成為原地排序(in-place)
記憶方法:想象成氣泡,一層一層的往上變大
-
選擇排序
lst = [4, 5, 3, 2, 6, 1, 8, 9] def SelectionSort(lst): for i in range(len(lst)-1): lst_min_index = i print("第{}個數作為最小數".format(i)) for j in range(i+1, len(lst)): if lst[j] < lst[lst_min_index]: print("第{}個數比第{}個數小".format(j, i)) lst_min_index = j print("第{}個數替換第{}個數作為最小數".format(j, i)) if i != lst_min_index: print("第{}個數替換第{}個數變為最小數".format(lst_min_index, i)) lst[lst_min_index], lst[i] = lst[i], lst[lst_min_index] return lst print(SelectionSort(lst))
演算法分析
選擇排序和氣泡排序很類似,但是選擇排序每輪比較只會有一次交換,而氣泡排序會有多次交換,交換次數比氣泡排序少,就減少cpu的消耗,所以在資料量小的時候可以用選擇排序,實際適用的場合非常少。
比較性:因為排序時元素之間需要比較,所以是比較排序
穩定性:因為存在任意位置的兩個元素交換,比如[5, 8, 5, 2],第一個5會和2交換位置,所以改變了兩個5原來的相對順序,所以為不穩定排序。
時間複雜度:我們看到選擇排序同樣是雙層迴圈n*(n-1)),所以時間複雜度也為:O(n^2)
空間複雜度:只需要常數個輔助單元,所以空間複雜度也為O(1)
記憶方法:選擇物件要先選最小的,因為嫩,哈哈
-
插入排序
lst = [5, 4, 3, 2, 6, 1, 8, 9] def insertionSort(lst): for i in range(1, len(lst)): # 要插入的數, range從1開始,就是第2個數是要插入的數 current = lst[i] current_index = i # 要比較的數是要插入的數的前一個數, 這裡就是從0個開始 present_index = i - 1 while present_index >= 0 and lst[present_index] > current: """ 比較的數大於要插入的數,那麼把比較的數賦值給下一個數 往前再選擇下一個比較的數,第一個迴圈比較的是第0個數, 前邊無數了,present_index - 1 = -1了, 不會再比, 跳出當前迴圈 """ lst[present_index+1] = lst[present_index] present_index -= 1 # 這一步要+1的原因是上一步多減了一個1,其實結果是把第1個元素的值賦值給第0個元素了 lst[present_index + 1] = current # 到這裡第1個元素和第0個元素比完了, 要從2個元素開始比了 return lst print(insertionSort(lst))
演算法分析
插入排序的適用場景:一個新元素需要插入到一組已經是有序的陣列中,或者是一組基本有序的陣列排序。
比較性:排序時元素之間需要比較,所以為比較排序
穩定性:從程式碼我們可以看出只有比較元素大於當前元素,比較元素才會往後移動,所以相同元素是不會改變相對順序
時間複雜度:插入排序同樣需要兩次循壞一個一個比較,故時間複雜度也為O(n^2)
空間複雜度:只需要常數個輔助單元,所以空間複雜度也為O(1)
記憶方法:想象成在書架中插書:先找到相應位置,將後面的書往後推,再將書插入
-
希爾排序
def shellSort(): gap = len(lst) // 2 while gap > 0: for i in range(gap, len(lst)): j = i current = lst[i] while j - gap >= 0 and current < lst[j - gap]: lst[j] = lst[j-gap] j -= gap lst[j] = current gap //= 2 return lst
演算法分析
比較性:排序時元素之間需要比較,所以為比較排序
穩定性:因為希爾排序是間隔的插入,所以存在相同元素相對順序被打亂,所以是不穩定排序
時間複雜度: 最壞時間複雜度O(n2)平均複雜度為O(n1.3)
空間複雜度:只需要常數個輔助單元,所以空間複雜度也為O(1)
記憶方法:插入排序是每輪都是一小步,希爾排序是先大步後小步,它第一個突破O(n2)的排序演算法。聯想起阿姆斯特朗登月之後說:這是我個人一小步,卻是人類邁出的一大步。