一、冒泡排序
這個算法的名字由來是因為越大的元素會經由交換慢慢“浮”到數列的頂端(升序或降序排列),就如同碳酸飲料中二氧化碳的氣泡最終會上浮到頂端一樣,故名“冒泡排序”。
-
比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
-
對每一對相鄰元素做同樣的工作,從開始第一對到結尾的最后一對。在這一點,最后的元素應該會是最大的數。
-
針對所有的元素重復以上的步驟,除了最后一個。
-
持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。
#!/usr/bin/env python # -*- coding: utf-8 -*- li = [99, 0, -1, 46, -87, 7, 17, 20] le = len(li) # 長度8 for i in range(le): # [0,7] 持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。 for j in range(le - i - 1): # 針對所有的元素重復以上的步驟,除了最后一個。 if li[j + 1] > li[j]: # 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。 li[j], li[j + 1] = li[j + 1], li[j] # 這里不要break, print(li)
二、選擇排序
選擇排序是一種簡單直觀的排序算法。它的工作原理是每一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,然后,再從剩余未排序元素中繼續尋找最小(大)元素,然后放到已排序序列的末尾。以此類推,直到全部待排序的數據元素排完。 選擇排序是不穩定的排序方法。
#!/usr/bin/env python # -*- coding: utf-8 -*- li = [99, 0, -1, 46, -87, 7, 17, 20] le = len(li) # 長度8 for i in range(le): # [0,7] max_val = i # 記錄最大值的角標,我們先假設i為最大值 for j in range(i + 1, le): # 再去循環我們假設的最大值和其它值去逐個比較 if li[j] > li[max_val]: # 當有值比我們假設的最大值大時,我們記錄角標 max_val = j li[i], li[max_val] = li[max_val], li[i] # 這樣我們循環i次以后,我們就可以得到集合內的最大值,然后我們放在第i個位置, print(li)
為什么我們回收選擇排序是不穩定的排序呢?簡單地說就是所有相等的數經過某種排序方法后,仍能保持它們在排序之前的相對次序,我們就
說這種排序方法是穩定的。反之,就是非穩定的。例如我們要排序[1,1,1,1,1,1,1],實則我們排序之后,每一個1的順序是不會變化的,還是按照原來的顏色放置就是穩定排序。也就是說排序以后還是這樣的[1,1,1,1,1,1,1]
三、插入排序
插入排序是一種簡單直觀且穩定的排序算法。如果有一個已經有序的數據序列,要求在這個已經排好的數據序列中插入一個數,但要求插入后此數據序列仍然有序,這個時候就要用到一種新的排序方法——插入排序法,插入排序的基本操作就是將一個數據插入到已經排好序的有序數據中,從而得到一個新的、個數加一的有序數據,算法適用於少量數據的排序,時間復雜度為O(n^2)。是穩定的排序方法。插入算法把要排序的數組分成兩部分:第一部分包含了這個數組的所有元素,但將最后一個元素除外(讓數組多一個空間才有插入的位置),而第二部分就只包含這一個元素(即待插入元素)。在第一部分排序完成后,再將這個最后元素插入到已排好序的第一部分中。
插入排序的基本思想是:每步將一個待排序的記錄,按其關鍵碼值的大小插入前面已經排序的文件中適當位置上,直到全部插入完為止。
#!/usr/bin/env python # -*- coding: utf-8 -*- li = [9, 0, -1, 46, -87, 7, 17, 20] le = len(li) # 長度8 k = 0 # 記錄交換次數 for i in range(1, le): val = li[i] # 先記下每次大循環走到的第幾個元素的值 j = i while j > 0 and li[j - 1] < val: # 循環次數j大於0 and 前一位數大於后一位數 li[j] = li[j - 1] # 將后一位數放到前面,根據值的大小排序 j -= 1 # 把前面的數放到后面 k += 1 li[j] = val # 已經找到了左邊排序好的列表里不小於val的元素的位置,把val放在這里 print(li) print(k)
四、快速排序
快速排序是對冒泡排序的一種改進。
通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然后再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 1)設置兩個變量i、j,排序開始的時候:i=0,j=N-1; 2)以第一個數組元素作為關鍵數據,賦值給key,即key=A[0]; 3)從j開始向前搜索,即由后開始向前搜索(j--),找到第一個小於key的值A[j],將A[j]和A[i]互換; 4)從i開始向后搜索,即由前開始向后搜索(i++),找到第一個大於key的A[i],將A[i]和A[j]互換; 5)重復第3、4步,直到i=j; (3,4步中,沒找到符合條件的值,即3中A[j]不小於key,4中A[i]不大於key的時候改變j、i的值,使得j=j-1,i=i+1, 直至找到為止。找到符合條件的值,進行交換的時候i, j指針位置不變。另外,i==j這一過程一定正好是i+或j-完成的時候,此時令循環結束)。 """ li = [9, 0, -1, 46, -87, 7, 17, 20] le = len(li) def QuickSort(li, start, end): # 判斷end結束是否小於start開始,如果為false,直接返回 if start < end: i, j = start, end # 設置基准數 base = li[i] while i < j: # 如果列表后邊的數,比基准數大或相等,則前移一位直到有比基准數小的數出現 while (i < j) and (li[j] >= base): j = j - 1 # 如找到,則把第j個元素賦值給第個元素i,此時表中i,j個元素相等 li[i] = li[j] # 同樣的方式比較前半區 while (i < j) and (li[i] <= base): i = i + 1 li[j] = li[i] # 做完第一輪比較之后,列表被分成了兩個半區,並且i=j,需要將這個數設置回base li[i] = base # 遞歸前后半區 QuickSort(li, start, i - 1) QuickSort(li, j + 1, end) return li sortli = QuickSort(li, 0, le - 1) print(sortli)
五、歸並排序
歸並排序是建立在歸並操作上的一種有效的排序算法,該算法是采用分治法的一個非常典型的應用。將已有序的子序列合並,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合並成一個有序表,稱為二路歸並。
#!/usr/bin/env python # -*- coding: utf-8 -*- def merge(a, b): c = [] h = j = 0 while j < len(a) and h < len(b): if a[j] < b[h]: c.append(a[j]) j += 1 else: c.append(b[h]) h += 1 if j == len(a): for i in b[h:]: c.append(i) else: for i in a[j:]: c.append(i) return c def merge_sort(lists): if len(lists) <= 1: return lists middle = int(len(lists) / 2) left = merge_sort(lists[:middle]) right = merge_sort(lists[middle:]) return merge(left, right) if __name__ == '__main__': li = [9, 0, -1, 46, -87, 7, 17, 20, 2] print(merge_sort(li))
