赞
踩
原理就不在这里说了,好多大神肯定比我这个初学者讲的好很多,推荐去B站看视频讲解,跟着手敲代码
为什么选这三个排序呢?
算法 | 时间复杂度 | 空间复杂度 | 稳定性 | ||
平均 | 最好 | 最坏 | |||
冒泡排序 | O(n²) | O(n) | O(n²) | O(1) | 稳定 |
快速排序 | O(nlogn) | O(nlogn) | O(n²) | O(1)或O(n) | 不稳定 |
归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 稳定 |
- import random
- from copy import deepcopy
-
- arr0 = [random.randint(1, 100) for _ in range(1000)]
- # arr0 = [_ for _ in range(1000, 0, -1)]
- # print(arr0)
- for i in range(1, 11):
- exec(f'arr{i} = deepcopy(arr0)')
- def bubble_sort(arr):
- for i in range(len(arr) - 1):
- for j in range(len(arr) - 1 - i):
- if arr[j] >= arr[j + 1]:
- arr[j], arr[j + 1] = arr[j + 1], arr[j]
- return arr
- def merge_sort(arr):
- length = len(arr)
- if length <= 1:
- return arr
- mid = length // 2
- # 以下标mid为分界点,将arr的[:mid]给left,[mid:]给right
- left = merge_sort(arr[:mid])
- right = merge_sort(arr[mid:])
- lp = 0
- rp = 0
- res = []
- # 切记这里不是<=,因为数组的index一定是小于数组长度的
- while lp < len(left) and rp < len(right):
- if left[lp] <= right[rp]:
- res.append(left[lp])
- lp += 1
- else:
- res.append(right[rp])
- rp += 1
- # 这里要用extend. left,right切片后的值为一个list
- res.extend(left[lp:])
- res.extend(right[rp:])
- return res
- # 一句话快排
- qs = lambda arr: arr if len(arr) <= 1 else qs([it for it in arr[1:] if it <= arr[0]]) + [arr[0]] + \
- qs([it for it in arr[1:] if it > arr[0]])
-
- # 空间复杂度O(1)的快排
- def quick_sort_O1(arr, left, right):
- if left >= right:
- return
- base = arr[left]
- lp = left
- rp = right
- while lp < rp:
- while lp < rp and arr[rp] >= base:
- rp -= 1
- arr[lp] = arr[rp]
- while lp < rp and arr[lp] < base:
- lp += 1
- arr[rp] = arr[lp]
- arr[lp] = base
- quick_sort_O1(arr, left, lp - 1)
- quick_sort_O1(arr, lp + 1, right)
- return arr
-
- # 空间复杂度O(n)的快排
- def quick_sort_On(arr: list):
- if len(arr) <= 1:
- return arr
- left = []
- right = []
- base = arr.pop(0)
- for it in arr:
- if it <= base:
- left.append(it)
- else:
- right.append(it)
-
- return quick_sort_On(left) + [base] + quick_sort_On(right)
-
- # 空间复杂度O(n)的快排,引入随机处理,尝试规避快排的最坏风险
- def quick_sort_On_random(arr: list):
- if len(arr) <= 1:
- return arr
- left = []
- right = []
- base = arr.pop()
- while arr:
- tmp = arr.pop()
- if tmp <= base:
- left.append(tmp)
- else:
- right.append(tmp)
- return quick_sort_On(left) + [base] + quick_sort_On(right)
- 将arr0重新赋值如下:
- arr0 = [_ for _ in range(1000, 0, -1)]
- 将arr0重新赋值如下:
- arr0 = [_ for _ in range(1000)]
**内置函数那么快,学啥快排(捂脸)...
随机无序数组
反序数组
正序结果
先不总结了,大致情况就如上吧.希望大家看完后给些意见和建议.
不知道有什么地方没考虑进去,本来只是为了规避快排最坏情况的风险而实现的quick_sort_On_random,意外发现每次都是最快的???
2020-12-16:
查找了相关资料,找到了quick_sort_On_random速度最快的原因,在这里记录一下
1.从列表的末尾(右端)弹出在CPython中需要恒定的时间,但是从左端弹出(.pop(0))需要的时间与列表的长度成正比
2.所有the_list [1:]中的元素在物理上向左移动一个位置.
3.如果需要经常删除索引位置0,那么使用collections.deque的实例要好得多. Deques支持从两端有效推送和弹出.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。