十種常見排序算法能夠分爲兩大類:html
非線性時間比較類排序:經過比較來決定元素間的相對次序,因爲其時間複雜度不能突破O(nlogn),所以稱爲非線性時間比較類排序。包括:冒泡排序、選擇排序、歸併排序、快速排序、插入排序、希爾排序、堆排序等。python
線性時間非比較類排序:不經過比較來決定元素間的相對次序,它能夠突破基於比較排序的時間下界,以線性時間運行,所以稱爲線性時間非比較類排序。包括:計數排序、桶排序、基數排序等。算法
下面介紹各類算法的基本思想及python實現:shell
1 冒泡排序(Bubble Sort)數組
1.1 基本思想:數據結構
它重複地走訪過要排序的數列,一次比較兩個元素,若是它們的順序錯誤就把它們交換過來。走訪數列的工做是重複地進行直到沒有再須要交換,也就是說該數列已經排序完成。app
1.2 實現代碼:ide
1 def bubbleSort(arr): 2 n = len(arr) 3 for i in range(n-1): 4 for j in range(n-i-1): 5 if arr[j] > arr[j+1]: 6 arr[j], arr[j+1] = arr[j+1], arr[j] 7 return arr
2 選擇排序(Selection Sort)函數
2.1 基本思想:ui
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,而後,再從剩餘未排序元素中繼續尋找最小(大)元素,而後放到已排序序列的末尾。以此類推,直到全部元素均排序完畢。
2.2 實現代碼
1 def selectionSort(arr): 2 n = len(arr) 3 for i in range(n-1): 4 minIndex = i 5 for j in range(i+1, n, 1): 6 if arr[j] < arr[minIndex]: 7 minIndex = j 8 arr[i], arr[minIndex] = arr[minIndex], arr[i] 9 return arr
3 插入排序(Insertion Sort)
3.1 基本思想
經過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。
3.2 實現代碼
1 def insertionSort(arr): 2 n = len(arr) 3 for i in range(1, n): 4 for j in range(i, 0, -1): 5 if arr[j] < arr[j-1]: 6 arr[j-1], arr[j] = arr[j], arr[j-1] 7 return arr
4 希爾排序(Shell Sort)
4.1 基本思想
它是簡單插入排序的改進版。它與插入排序的不一樣之處在於,它會優先比較距離較遠的元素,將整個待排序的記錄序列分割成爲若干子序列分別進行直接插入排序。希爾排序又叫縮小增量排序。
4.2 實現代碼
1 def shellsort(arr): 2 n = len(arr) 3 group = 3 4 gap = n // group 5 while gap > 0: 6 for i in range(0, gap): 7 for j in range(i+gap, n, gap): 8 tmp = arr[j] 9 for k in range(j-gap, i-1, -gap): 10 if arr[k] >= arr[j]: 11 arr[k + gap], arr[k] = arr[k], tmp 12 gap //= group 13 return arr
5 歸併排序(Merge Sort)
5.1 基本思想
歸併排序是創建在歸併操做上的一種有效的排序算法。該算法是採用分治法(Divide and Conquer)的一個很是典型的應用。將已有序的子序列合併,獲得徹底有序的序列;即先使每一個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱爲2-路歸併。
5.2 實現代碼
1 def mergeSort(arr): 2 if len(arr) < 2: 3 return arr 4 middle = int(len(arr) / 2) 5 left = mergeSort(arr[:middle]) 6 right = mergeSort(arr[middle:]) 7 return merge(left, right) 8 def merge(left, right): 9 result = [] 10 leftindex = rightindex = 0 11 while leftindex < len(left) and rightindex < len(right): 12 if left[leftindex] <= right[rightindex]: 13 result.append(left[leftindex]) 14 leftindex += 1 15 else: 16 result.append(right[rightindex]) 17 rightindex += 1 18 if len(left): 19 for i in left[leftindex:]: 20 result.append(i) 21 if len(right): 22 for i in right[rightindex:]: 23 result.append(i) 24 return result
6 快速排序(Quick Sort)
6.1 基本思想
經過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另外一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。
6.2 實現代碼
1 def quickSort(arr, left, right): 2 if left < right: 3 partitionIndex = partition(arr, left, right) 4 quickSort(arr, left, partitionIndex - 1) 5 quickSort(arr, partitionIndex + 1, right) 6 return arr 7 def partition(arr, left ,right): 8 pivot = right 9 i = left - 1 10 for j in range(left, right): 11 if arr[j] <= arr[pivot]: 12 i += 1 13 arr[i], arr[j] = arr[j], arr[i] 14 arr[i+1], arr[pivot] = arr[pivot], arr[i+1] 15 # print(arr) 16 return i + 1
7 堆排序(Heap Sort)
7.1 基本思想
堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似徹底二叉樹的結構,並同時知足堆積的性質:即子結點的鍵值或索引老是小於(或者大於)它的父節點。
7.2 代碼實現
1 def adjust_heap(arr, i, n): 2 lchild = 2 * i + 1 3 rchild = 2 * i + 2 4 max = i 5 if i < n / 2: 6 if lchild < n and arr[lchild] > arr[max]: 7 max = lchild 8 if rchild < n and arr[rchild] > arr[max]: 9 max = rchild 10 if max != i: 11 arr[max], arr[i] = arr[i], arr[max] 12 adjust_heap(arr, max, n) # 下濾 13 def build_max_heap(arr, n): 14 for i in range(0, int(n // 2))[::-1]: 15 adjust_heap(arr, i, n) 16 def heap_sort(arr): 17 n = len(arr) 18 build_max_heap(arr, n) 19 for i in range(0, n)[::-1]: 20 arr[0], arr[i] = arr[i], arr[0] 21 adjust_heap(arr, 0, i) # 下濾 22 return arr
8 計數排序
8.1 基本思想
計數排序不是基於比較的排序算法,其核心在於將輸入的數據值轉化爲鍵存儲在額外開闢的數組空間中。 做爲一種線性時間複雜度的排序,計數排序要求輸入的數據必須是有肯定範圍的整數。
8.2 實現代碼
1 def countingSort(arr, maxValue): 2 bucket = np.array(np.zeros(maxValue + 1)) # 算上0,arr必須是正數 3 sortedIndex = 0 4 bucketLen = maxValue + 1 5 n = len(arr) 6 for i in range(0, n): 7 # if bucket[arr[i]]: 8 bucket[arr[i]] += 1 9 for j in range(0, bucketLen): 10 while bucket[j] > 0: 11 arr[sortedIndex] = j 12 sortedIndex += 1 13 bucket[j] -= 1 14 return arr
9 桶排序
9.1 基本思想
假設輸入數據服從均勻分佈,將數據分到有限數量的桶裏,每一個桶再分別排序(可使用別的排序算法或是以遞歸方式繼續使用桶排序進行排)。
9.2 實現代碼
1 def bucketSort(arr, bucketSize): 2 if len(arr) == 0: 3 return arr 4 minValue = min(arr) # 輸入數據的最小值 5 maxValue = max(arr) # 輸入數據的最大值 6 # 桶的初始化 7 DEFAULT_BUCKET_SIZE = 5 # 設置桶的默認數量爲5 8 bucketSize = bucketSize | DEFAULT_BUCKET_SIZE # 按照位或(二進制) 9 bucketCount = math.floor((maxValue - minValue) / bucketSize) + 1 10 buckets = [[] for i in range(bucketCount)] 11 12 # 利用映射函數將數據分配到各個桶中 13 for i in range(0, len(arr)): 14 (buckets[math.floor((arr[i] - minValue) / bucketSize)]).append(arr[i]) 15 arr = [] 16 for i in range(0, len(buckets)): 17 insertionSort(buckets[i]) # 對每一個桶進行排序,這裏使用了插入排序 18 for j in range(0, len(buckets[i])): 19 arr.append(buckets[i][j]) 20 return arr
10 基數排序
10.1 基本思想
基數排序是按照低位先排序,而後收集;再按照高位排序,而後再收集;依次類推,直到最高位。有時候有些屬性是有優先級順序的,先按低優先級排序,再按高優先級排序。最後的次序就是高優先級高的在前,高優先級相同的低優先級高的在前。
10.2 實現代碼
1 import math 2 def radix_sort(arr, radix=10): 3 k = int(math.ceil(math.log(max(arr), radix))) # 取得位數 4 bucket = [[] for i in range(radix)] # 初始化 bucket = [[],[],...] 5 for i in range(1, k+1): 6 for j in arr: 7 bucket[j % (radix ** i) // (radix ** (i - 1))].append(j) # 先截取元素的後k位數再取第k位上的數字(k=1,2...) 8 del arr[:] 9 for z in bucket: 10 arr += z 11 print(arr) 12 del z[:] 13 return arr
參考:https://www.cnblogs.com/onepixel/articles/7674659.html