排序算法一直以来是我的心病,这次为了搞定这块内容,进行了一次系统的学习,结合大神的讲解以及个人的总结,梳理了以下的解决方案,顺便给出相关的迁移问题以及解决方案。
概况:
排序一般分为选择排序和插入排序这两大类,其余排序都是在这两块上的优化和深入。
这里不得不提到时间复杂度,虽然为O(n*2),可是在特定的场合下,插入排序还是比较快的,尤其是在近乎有序的情况下,一般在数据量比较小而接近的
情况下使用比较好。
插入排序衍生出冒泡排序和希尔排序
高级排序(O(nlogn)):
归并排序、快速排序、双路/三路快速排序、堆排序
下面给出相关的代码实例(python格式):
选择排序:
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:anacondpython.exe E:/cources_python/data_structure/algorithm/sort_demo.py mergeSort 时长15.77121s insertSort 时长7.39828s Process finished with exit code 0