快速排序
快速排序在排序时主要进行两部操作。
- 随机选取一个基准值,随机值可以选择第一个值,但建议从中间选择减少遇到最坏状况的概率(随机值选取到最大值或者最小值时最坏状况)
- 将所有数据和基准值对比,将大于基准值的数据放入基准值右侧,小于基准值的数据放入基准值左侧
- 在左右两侧再次选择基准值重复上述操作。(可选择递归或栈的方式)
快速排序对元素交互有单边循环法和双边循环法两种方法,下图所示为单边循环法,而代码使用的则是双边循环法。
def quick(data, start, end):
"""用递归的方式进行快速排序"""
# 判断是否需要跳出递归
if start >= end:
return
print(start, end)
# 先选择一个需要排序的元素
n = data[start]
# 从列表左右两边分别向列表中心寻找
left = start
right = end
while left != right:
while data[right] >= n and left < right:
right -= 1
data[left] = data[right]
while data[left] < n and left < right:
left += 1
data[right] = data[left]
data[right] = n
# 左右分支分别开始递归
# 左子支递归
quick(data, start, left-1)
# 右子支递归
quick(data, left+1, end)
归并排序
归并排序采用了分治法的思想。
- 将序列分解为单个元素的序列
- 将序列逐对合并,从头开始比较序列中的元素,将最小的元素取出放入新序列,然后对比下一个,直到其中一个序列为空,把另一个序列剩余部分放入新序列即可。
- 用递归或者栈来重复上述操作
归并排序中递归比较复杂。.如果不清楚代码执行过程可以尝试使用断点调试来查看。
# 归并排序
def merge(data):
# 递归退出条件(列表长度小于等于1)
if len(data) <= 1:
return data
# 二分分解法
middie = len(data)//2
left = merge(data[:middie])
right = merge(data[middie:])
# 左右列表的游标
left_cur = 0
right_cur = 0
# 将当前left于right排序后放入新列表\
new = []
# 判断是否有列表已经全部取出
while left_cur < len(left) and right_cur < len(right):
# 如果左列表比右列表大就将右列表中的值给新列表
if left[left_cur] > right[right_cur]:
new.append(right[right_cur])
right_cur += 1
# 否则执行相反操作
else:
new.append(left[left_cur])
left_cur += 1
# 将列表中剩余的元素给新列表
new += left[left_cur:]
new += right[right_cur:]
# 返回新列表
return new