快速排序和歸併排序都使用了分治思想. 分治算法通常都用遞歸來實現python
分治: 分而治之, 將一個大問題不斷的分解爲小問題來解決, 小的問題解決了, 大的問題也就解決了.算法
思想: 將原數組不斷分解爲先後兩部分, 直到每一個數組內只有一個元素, 而後不斷進行排序合併, 最後合併爲一個有序數組數組
O(logn)
次, 每次都須要對n個元素排序, 因此須要O(nlogn)
# coding:utf-8 def merge(left, right): res = [] while left and right: # 此處決定了排序是否穩定. 須要保證針對相等的元素排序後按照出現的前後順序進行排列 if left[0] < right[0]: res.append(left.pop(0)) else: res.append(right.pop(0)) if left: res.extend(left) if right: res.extend(right) return res def merge_sort(nums): length = len(nums) if length <= 1: return nums middle = int(length / 2) left = merge_sort(nums[:middle]) right = merge_sort(nums[middle:]) return merge(left, right) if __name__ == "__main__": nums = [4, 3, 6, 9, 7, 0, 1, 9, 3] assert merge_sort(nums) == [0, 1, 3, 3, 4, 6, 7, 9, 9]
使用了分治思想. 以數組中的一個數key爲基準, 把小於key的數放到左邊, 把大於key的數放到右邊, 而後使用一樣的方法做用於key兩邊的區間數據結構
O(n**2)
# coding:utf-8 """ 空間複雜度: O(n) """ def quick_sort(nums): if len(nums) <= 1: return nums key = nums.pop() # 不考慮空間消耗 less, over = [], [] for i in nums: if i < key: less.append(i) else: over.append(i) return quick_sort(less) + [key] + quick_sort(over) if __name__ == "__main__": nums_1 = [4, 3, 6, 9, 7, 0, 1, 9, 3] assert quick_sort(nums_1) == [0, 1, 3, 3, 4, 6, 7, 9, 9]
# coding:utf-8 """ 空間複雜度: O(1) """ def partition(nums, low, high): key_index = high key = nums[key_index] while low < high: while low < high and nums[low] <= key: low += 1 while low < high and nums[high] >= key: high -= 1 nums[low], nums[high] = nums[high], nums[low] nums[low], nums[key_index] = nums[key_index], nums[low] return low def interval(nums, low, high): if low < high: new_index = partition(nums, low, high) interval(nums, 0, new_index - 1) interval(nums, new_index + 1, high) return nums def quick_sort(nums): res = interval(nums, 0, len(nums) - 1) return res if __name__ == "__main__": nums_2 = [4, 3, 6, 9, 7, 0, 1, 9, 3] assert quick_sort(nums_2) == [0, 1, 3, 3, 4, 6, 7, 9, 9]
O(n**2)
快速排序中最壞狀況是分區後一個分區是空, 另外一個分區全滿, 這種通常是key的選擇不當致使的, 好比一個有序數組選擇了第一個或最後一個元素爲key, 能夠採用如下方法優化app