Python實現十大常用排序算法
一、冒泡排序
冒泡排序(Bubble Sort),是一種計算機科學領域的較簡單的排序算法。它重復地走訪過要排序的元素列,依次比較兩個相鄰的元素,一層一層的將較大的元素往后移動,其現象和氣泡在上升過程中慢慢變大類似,故成為冒泡排序。
1.過程圖解
2.算法思想
從第一個和第二個開始比較,如果第一個比第二個大,則交換位置,然后比較第二個和第三個,逐漸往后
經過第一輪后最大的元素已經排在最后,所以重復上述操作的話第二大的則會排在倒數第二的位置。
那重復上述操作n-1次即可完成排序,因為最后一次只有一個元素所以不需要比較
3.代碼實現
#冒泡排序
arr = [1,23,3,36,4,5,1.5]
#第一層for表示循環的遍數
for i in range(len(arr) - 1 ):
#第二層for表示具體比較哪兩個元素
for j in range(len(arr) -1 ):
if arr[j] > arr[j+1]:
arr[j],arr[j+1] = arr[j+1],arr[j]
print(arr) #[1, 1.5, 3, 4, 5, 23, 36]
4.算法分析**
冒泡排序是一種簡單直接暴力的排序算法,為什么說它暴力?因為每一輪比較可能多個元素移動位置,而元素位置的互換是需要消耗資源的,所以這是一種偏慢的排序算法,僅適用於對於含有較少元素的數列進行排序。
穩定性:我們從代碼中可以看出只有前一個元素大於后一個元素才可能交換位置,所以相同元素的相對順序不可能改變,所以它是穩定排序
比較性:因為排序時元素之間需要比較,所以是比較排序
時間復雜度:因為它需要雙層循環n*(n-1)),所以平均時間復雜度為O(n^2)
空間復雜度:只需要常數個輔助單元,所以空間復雜度為O(1),我們把空間復雜度為O(1)的排序成為原地排序(in-place)
記憶方法:想象成氣泡,一層一層的往上變大
二、選擇排序
選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理是每一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,所以稱為:選擇排序
1.過程圖解
2.算法思想
設第一個元素為比較元素,依次和后面的元素比較,比較完所有元素找到最小的元素,將它和第一個元素互換
重復上述操作,我們找出第二小的元素和第二個位置的元素互換,以此類推找出剩余最小元素將它換到前面,即完成排序
3.代碼實現
#選擇排序
for i in range(len(arr) -1 ):
#將起始元素設為最小元素
min_index = i
#第二層for循環表示最小原色和后面的元素逐個比較
for j in range(i+1 ,len(arr)):
if arr[j] < arr[min_index]:
min_index = j
arr[min_index],arr[i] = arr[i],arr[min_index]
print(arr)
4.算法分析**
選擇排序和冒泡排序很類似,但是選擇排序每輪比較只會有一次交換,而冒泡排序會有多次交換,交換次數比冒泡排序少,就減少cpu的消耗,所以在數據量小的時候可以用選擇排序,實際適用的場合非常少。
比較性:因為排序時元素之間需要比較,所以是比較排序
穩定性:因為存在任意位置的兩個元素交換,比如[5, 8, 5, 2],第一個5會和2交換位置,所以改變了兩個5原來的相對順序,所以為不穩定排序。
時間復雜度:我們看到選擇排序同樣是雙層循環n*(n-1)),所以時間復雜度也為:O(n^2)
空間復雜度:只需要常數個輔助單元,所以空間復雜度也為O(1)
記憶方法:選擇對象要先選最小的,因為嫩,哈哈
三、插入排序
插入排序(Insertion-Sort)的算法描述是一種簡單直觀的排序算法。它的工作原理是通過構建有序序列,對於未排序數據,在已排序序列中從后向前掃描,找到相應位置並插入。
1.過程圖解
2.算法思想
從第二個元素開始和前面的元素進行比較,如果前面的元素比當前元素大,則將前面元素 后移,當前元素依次往前,直到找到比它小或等於它的元素插入在其后面
然后選擇第三個元素,重復上述操作,進行插入
依次選擇到最后一個元素,插入后即完成所有排序
3.代碼實現
4.算法分析
插入排序的適用場景:一個新元素需要插入到一組已經是有序的數組中,或者是一組基本有序的數組排序。
比較性:排序時元素之間需要比較,所以為比較排序
穩定性:從代碼我們可以看出只有比較元素大於當前元素,比較元素才會往后移動,所以相同元素是不會改變相對順序
時間復雜度:插入排序同樣需要兩次循壞一個一個比較,故時間復雜度也為O(n^2)
空間復雜度:只需要常數個輔助單元,所以空間復雜度也為O(1)
記憶方法:想象成在書架中插書:先找到相應位置,將后面的書往后推,再將書插入
四、希爾排序
希爾排序(Shell’s Sort)是插入排序的一種又稱“縮小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一種更高效的改進版本,它與插入排序的不同之處在於,它會優先比較距離較遠的元素,該方法因D.L.Shell於1959年提出而得名。
1.過程圖解
2.算法思想
希爾排序的整體思想是將固定間隔的幾個元素之間排序,然后再縮小這個間隔。這樣到最后數列就成為了基本有序數列,而前面我們講過插入排序對基本有序數列排序效果較好。
計算一個增量(間隔)值
對元素進行增量元素進行比較,比如增量值為7,那么就對0,7,14,21…個元素進行插入排序
然后對1,8,15…進行排序,依次遞增進行排序
所有元素排序完后,縮小增量比如為3,然后又重復上述第2,3步
最后縮小增量至1時,數列已經基本有序,最后一遍普通插入即可
已知的最增量式是由 Sedgewick 提出的 (1, 5, 19, 41, 109,…),該步長的項來自 9 4^i - 9 2^i + 1 和 4^i - 3 2^i + 1 這兩個算式。這項研究也表明 “比較在希爾排序中是最主要的操作,而不是交換。 用這樣增量式的希爾排序比插入排序和堆排序都要快,甚至在小數組中比快速排序還快,但是在涉及大量數據時希爾排序還是比*快速排序慢。
3.代碼實現
4.算法分析
比較性:排序時元素之間需要比較,所以為比較排序
穩定性:因為希爾排序是間隔的插入,所以存在相同元素相對順序被打亂,所以是不穩定排序
時間復雜度: 最壞時間復雜度O(n2)平均復雜度為O(n1.3)
空間復雜度:只需要常數個輔助單元,所以空間復雜度也為O(1)
記憶方法:插入排序是每輪都是一小步,希爾排序是先大步后小步,它第一個突破O(n2)的排序算法。聯想起阿姆斯特朗登月之后說:這是我個人一小步,卻是人類邁出的一大步。
五、歸並排序
歸並排序(MERGE-SORT)是建立在歸並操作上的一種有效的排序算法,該算法是采用分治法(Divide and Conquer)的一個非常典型的應用。歸並排序適用於子序列有序的數據排序。
1.過程圖解
2.算法思想
歸並排序是分治法的典型應用。分治法(Divide-and-Conquer):將原問題划分成 n 個規模較小而結構與原問題相似的子問題;遞歸地解決這些問題,然后再合並其結果,就得到原問題的解。從上圖看分解后的數列很像一個二叉樹。
使用遞歸將源數列使用二分法分成多個子列
申請空間將兩個子列排序合並然后返回
將所有子列一步一步合並最后完成排序
3.代碼實現
4.算法分析
比較性:排序時元素之間需要比較,所以為比較排序
穩定性:我們從代碼中可以看到當左邊的元素小於等於右邊的元素就把左邊的排前面,而原本左邊的就是在前面,所以相同元素的相對順序不變,故為穩定排序
時間復雜度: 復雜度為O(nlog^n)
空間復雜度:在合並子列時需要申請臨時空間,而且空間大小隨數列的大小而變化,所以空間復雜度為O(n)
記憶方法:所謂歸並肯定是要先分解,再合並
總結
今天給大家介紹的五種排序是比較簡單的排序,建議大家自己動手敲幾遍代碼,書讀百遍,其義自現。要求大家必須理解&記住它們的算法原理,因為代碼是永遠記不住的,只要記住原理你就能用偽代碼實現。返回搜狐,查看更多
六、快速排序
def quick_sort(b):
"""快速排序"""
if len(b) < 2:
return arr
# 選取基准,隨便選哪個都可以,選中間的便於理解
mid = arr[len(b) // 2]
# 定義基准值左右兩個數列
left, right = [], []
# 從原始數組中移除基准值
b.remove(mid)
for item in b:
# 大於基准值放右邊
if item >= mid:
right.append(item)
else:
# 小於基准值放左邊
left.append(item)
# 使用迭代進行比較
return quick_sort(left) + [mid] + quick_sort(right)