排序算法一直以來是個人心病,此次爲了搞定這塊內容,進行了一次系統的學習,結合大神的講解以及我的的總結,梳理了如下的解決方案,順便給出相關的遷移問題以及解決方案。python
概況:算法
排序通常分爲選擇排序和插入排序這兩大類,其他排序都是在這兩塊上的優化和深刻。api
這裏不得不提到時間複雜度,雖然爲O(n*2),但是在特定的場合下,插入排序仍是比較快的,尤爲是在近乎有序的狀況下,通常在數據量比較小而接近的dom
狀況下使用比較好。函數
插入排序衍生出冒泡排序和希爾排序學習
高級排序(O(nlogn)):測試
歸併排序、快速排序、雙路/三路快速排序、堆排序優化
下面給出相關的代碼實例(python格式):ui
選擇排序:spa
def selectSort(arr): """ 選擇排序 """ for i in range(0,len(arr)): # 在[i,n)中選擇最小的索引 min_index = i for j in range(i+1,len(arr)): if arr[j] < arr[min_index]: min_index = j # 交換i與min_index的位置 # swap(arr[i], arr[min_index]) python中不須要使用這個,內存空間中局部變量無效 arr[i], arr[min_index] = arr[min_index], arr[i]
插入排序:
def insertSort(arr): """ 插入排序 """ for i in range(1, len(arr)): # 選擇arr[i]的位置 a = arr[i] j = i for j in range(1, i+1)[::-1]: # if arr[j-1] > arr[j]: # arr[j-1], arr[j] = arr[j], arr[j-1] if arr[j-1] > a: arr[j] = arr[j-1] else: break arr[j] = a
快速排序:
def _parition(arr, s, e): """ 找拆分位置 arr[s...index -1]<arr[index] arr[index+1....e]> arr[index] """ #初始第一個 base = arr[s] j = s #使得 arr[i+1....j-1]< base and arr[j+1....e]>base for i in range(s+1, e+1): if arr[i] < base: arr[j+1], arr[i] = arr[i], arr[j+1] j += 1 arr[s], arr[j] = arr[j], arr[s] return j def _quickSort(arr, l, r, n): """ 進行快排 """ if r < l: return index = _parition(arr, l, r) if index == n: return index _quickSort(arr, l, index-1, n) _quickSort(arr, index+1, r, n) def quickSort(arr, n): """ 快速排序 """ return _quickSort(arr, 0, len(arr)-1, n)
歸併排序:
def __merge_sort(arr, s, mid, e): """ 歸併arr[s...mid] arr[mid+1....e] """ #初始化歸併空間 merge_arr = [0] * (e-s+1) #賦值 for i in range(s, e+1): merge_arr[i-s] = arr[i] i = s j = mid+1 #歸併 for k in range(s, e+1): if i > mid: arr[k] = merge_arr[j-s] j += 1 elif j > e: arr[k] = merge_arr[i-s] i += 1 elif merge_arr[i-s] <merge_arr[j-s]: arr[k] = merge_arr[i-s] i += 1 else: arr[k] = merge_arr[j-s] j += 1 def _mergeSort(arr, s, e): if s >= e: return #改進數據量小的時候,用插入排序 if e-s <20: insertSort(arr) return #中間位置 mid = s + (e-s)//2 _mergeSort(arr, s, mid) _mergeSort(arr, mid+1, e) if arr[mid] < arr[mid+1]: __merge_sort(arr, s, mid, e) def mergeSort(arr): """ 歸併排序 """ _mergeSort(arr, 0, len(arr)-1)
堆排序:
def MAX_Heapify(heap, HeapSize, root): left = 2*root + 1 right = left + 1 larger = root if left < HeapSize and heap[larger] < heap[left]: larger = left if right < HeapSize and heap[larger] < heap[right]: larger = right if larger != root:#若是作了堆調整則larger的值等於左節點或者右節點的,這個時候作對調值操做 heap[larger],heap[root] = heap[root],heap[larger] MAX_Heapify(heap, HeapSize, larger) def Build_MAX_Heap(heap): HeapSize = len(heap)#將堆的長度當獨拿出來方便 for i in range((HeapSize -2)//2,-1,-1):#從後往前出數 MAX_Heapify(heap,HeapSize,i) def heapSort(arr): Build_MAX_Heap(arr) for i in range(len(arr)-1,-1,-1): arr[0],arr[i] = arr[i],arr[0] MAX_Heapify(arr, i, 0) return arr
如下是隨機生成測試數據和計算排序時長的方式:
def generArr(l, r, n): arr = [0] * n for i in range(0, n): arr[i] = random.randint(l,n) return arr def countTime(arr, func = None): """ 計算時長 """ start = time.time() func(arr) end = time.time() print(func.__name__, '時長{}s'.format(round((end-start), 5)))
計算結果以下:
def main(): """ 主函數 """ arr = generArr(0, 100, 10000) arrs = generArr(0, 100, 10000) countTime(arr, mergeSort) countTime(arrs, insertSort) if __name__ == '__main__': main() D:\anacond\python.exe E:/cources_python/data_structure/algorithm/sort_demo.py mergeSort 時長15.77121s insertSort 時長7.39828s Process finished with exit code 0