人之所以痛苦,那是因为你在成长。--------magic_guo
代码:
#排序中的Nb三人组:快排、归并排序、堆排序
# 排序中的Nb三人组:快排、归并排序、堆排序
li = [5, 7, 3, 1, 9, 4, 6, 13, 11, 16, 15, 19]
# 快排
def partition(li, left, right):
tmp = li[left]
while left < right:
while left < right and li[right] >= tmp:
right -= 1
li[left] = li[right]
while left < right and li[left] <= tmp:
left += 1
li[right] = li[left]
li[left] = tmp
return left
def quick_sort(li, left, right):
if left < right:
mid = partition(li, left, right)
quick_sort(li, left, mid)
quick_sort(li, mid+1, right)
return li
# print(quick_sort(li, 0, len(li)-1))
# 归并排序
def merge(li, low, mid, high):
ltmp = []
i = low
j = mid + 1
while i <= mid and j <= high:
if li[i] < li[j]:
ltmp.append(li[i])
i += 1
else:
ltmp.append(li[j])
j += 1
while i <= mid:
ltmp.append(li[i])
i += 1
while j <= high:
ltmp.append(li[j])
j += 1
li[low:high+1] = ltmp
return li
def merge_sort(li, low, high):
if low < high:
mid = (low + high) // 2
merge_sort(li, low, mid)
merge_sort(li, mid+1, high)
merge(li, low, mid, high)
return li
# print(merge_sort(li, 0, len(li)-1))
# 堆排序
def sift(li, low, high):
"""
向下调整函数
:param li:列表
:param low:堆顶
:param high:堆的最后一个元素的位置
:return:
"""
# 指向堆顶元素
i = low
# 指向其左子节点,如果一个根节点的下标为i,则其做子节点下标为2i+1,右子节点下标为2i+2;
j = 2*i + 1
# 暂存其堆顶元素的值
tmp = li[low]
# 循环条件,当j大于high时,则表明堆的元素已经操作完毕
while j <= high:
# 比较其左右子节点的大小,取出最大值
if j+1 <= high and li[j+1] > li[j]:
# 使j的指向变为左右节点中最大的那个
j = j + 1
# 拿出左右子节点中最大的值与暂存的堆顶元素作比较
if li[j] > tmp:
# 如果大于堆顶元素,则意味着最大子节点上位堆顶
li[i] = li[j]
# 改变i的指向为j
i = j
# 重定向j的指向
j = 2*i + 1
else:
break
li[i] = tmp
# else:
# # 如果最大的元素比tmp还小,则tmp作为此时i指向的根节点,然后终止循环
# li[i] = tmp
# break
# # 循环条件结束,总要把tmp的值赋给i指向的节点
# else:
# li[i] = tmp
# 建堆与排序的函数
def heap_sort(li):
n = len(li)
# 一直父子节点的关系为:父节点为i,则左子节点为2*i+1,右子节点为2*i+2
# 反向推理,则一直子节点为i,则其父节点为(i-1)//2
# 此时子节点为n-1,则则其父节点为(n-2)//2
for i in range((n-2)//2, -1, -1):
# i代表了建堆的时候,调整的每个部分堆的父节点的位置
# 到n-1,只是一个表示是一个最大范围,防止越界
sift(li, i, n-1)
print(li)
# 在上面的过程中已经将堆建立好,我们建立的是一个大根堆
# 接下来我们对堆进行排序
# 此时的i表示堆的最后一个元素
for i in range(n-1, -1, -1):
# 因为每次调整完后,堆顶元素都是最大的,所以为了不浪费空间,直接将堆顶元素与最后一个与元素进行交换,再进行调整
li[0], li[i] = li[i], li[0]
# 因为i的位置已经成了最大元素的位置,因此我们做调整的时候,不必包括最后一个元素,所以i-1
sift(li, 0, i-1)
return li
import random
le = [i for i in range(100)]
random.shuffle(le)
print(le)
print(heap_sort(le))