1、排序算法稳定性及其汇总
定义:排序过程保证相同元素次序不发生改变。
意义:业务需求,三个属性(name, age, height)的时候, height排序的时候,原始顺序age不会发送改变(按照height和age排序)。
稳定性排序:
- 冒泡排序、插入排序、归并排序
不稳定性排序:
- 选择排序:[4,4,4,3],第1个4和3交换位置,发送变化
- 快排:[4,4,4,5], 随机选择的4跟5交换发生变化(“01 stable sort”可以保证稳定性,很难)
- 堆排: [4,4,4,5], 实现大根堆过程, 第二四元素交换位置,发送变化
2、工程上综合排序(综合使用多种排序)
- 快排:样本量大,类型为基础类型,int、double、float等
- 归并:样本量大、类型为class、按照对象某个字段排序,常和插排一起使用
- 插入:样本量很短,长度模式小于60左右,常数项很低
3、比较器
定义:快速实现排序等操作。
- python对应list的sort方法和sorted()函数,参数key保证排序字段
- python复杂的比较器实现,多个字段比较
4、桶排序、计数排序、基数排序
桶排序定义: 计数排序的升级版,将数组分到有限数量的桶里。每个桶再个别排序
- 1,非基于比较的排序,与被排序的样本的实际数据状况很有关系,所以实际中并不经常使用
- 2,时间复杂度O(N),额外空间复杂度O(N)
- 3,稳定的排序
题目
给定一个数组, 求如果排序之后, 相邻的最大差值, 要求时间复杂度O(N), 且要求不能用非基于比较的排序。
思路:
- 创建N+1个桶,创建一个对象三个属性has, max_v, min_v,判断第一个和最后一个数是否相等,相等直接结束
- 1号桶放最小值,N+1号桶放最大值,然后将数组中值依次放入对应桶
- 最后肯定存在一个空桶,用来保证桶内不会存在最大值(过滤掉桶中变量的比较)
- 比较相邻桶的差值,就可以找出最大值
def max_gap(nums):
if nums is None or len(nums)<2:
return 0
nums_len = len(nums)
nums_min = min(nums)
nums_max = max(nums)
if nums_min == nums_max:
return 0
# 将数据依次入桶
has_list = [False for _ in range(nums_len+1)]
max_list = [i for i in range(nums_len+1)]
min_list = [i for i in range(nums_len+1)]
for i in range(nums_len):
bid = int((i - nums_min)*nums_len / nums_max-nums_min)
max_list[bid] = max(max_list[bid], nums[i]) if has_list[bid] else nums[i]
min_list[bid] = min(min_list[bid], nums[i]) if has_list[bid] else nums[i]
has_list[bid] = True
# 比较桶之间的最大值
res = 0
last_max = max_list[0]
for i in range(1, nums_len):
if has_list[i]:
res = max(res, min_list[i]-last_max)
last_max = max_list[i]
return res
print(max_gap([0,5,8,10,14,30,31]))
# 疑惑,这种不也是O(N)的复杂度吗?
def bucket_sort(arr):
max_v = 0
for i in range(len(arr)-1):
border_dif = abs(arr[i] - arr[i+1])
if border_dif > max_v:
max_v = border_dif
return max_v
bucket_sort([1,4,9,20,21])