python收入排序_python排序算法速度比较:快速排序,归并排序,冒泡排序

前言

原理就不在这里说了,好多大神肯定比我这个初学者讲的好很多,推荐去B站看视频讲解,跟着手敲代码

为什么选这三个排序呢?

首先快排是必须掌握的

看看快排在最坏的情况下(O(n²)),且不使用辅助空间,与冒泡(O(n²))的比较

由于快排是不稳定的排序算法,且平均时间复杂度为O(nlogn),那找一个时间复杂度为O(nlogn)且稳定排序算法,那么就非归并排序莫属了.

一、快速排序,归并排序,冒泡排序比较

算法时间复杂度空间复杂度稳定性

平均最好最坏

冒泡排序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)稳定

二、源码

引入库,并生成1000个随机数,然后深拷贝若干份.

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)')

1.冒泡

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

2.归并

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

3.快排

# 一句话快排

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)

三、创建长度为1000的list,在jupyter notebook上运行,观察结果

1.随机无序数组结果

a782474838417f82cb878a9963eb4181.png

空间换时间的做法明显让快排效率提高了一个数量级~

2.反序数组结果

将arr0重新赋值如下:

arr0 = [_ for _ in range(1000, 0, -1)]

1d286c1b3c64c4bcc8f0f969b9aa1e44.png

3.正序数组结果

将arr0重新赋值如下:

arr0 = [_ for _ in range(1000)]

9053eb3297eec1faebcae3b06bc57cd4.png

4.内置函数--遥遥领先

**内置函数那么快,学啥快排(捂脸)...

随机无序数组

4c44e65a8f944b49d44cf93c1a7e27a5.png

反序数组

ea06039f23c825de90bd5a154859ead1.png

正序结果

f33b43da4a8acd5a7fd0b8427c250c2f.png

总结

先不总结了,大致情况就如上吧.希望大家看完后给些意见和建议.

不知道有什么地方没考虑进去,本来只是为了规避快排最坏情况的风险而实现的quick_sort_On_random,意外发现每次都是最快的???

2020-12-16:

查找了相关资料,找到了quick_sort_On_random速度最快的原因,在这里记录一下

1.从列表的末尾(右端)弹出在CPython中需要恒定的时间,但是从左端弹出(.pop(0))需要的时间与列表的长度成正比

2.所有the_list [1:]中的元素在物理上向左移动一个位置.

3.如果需要经常删除索引位置0,那么使用collections.deque的实例要好得多. Deques支持从两端有效推送和弹出.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值