手写堆排序
参考:https://zhongqiang.blog.csdn.net/article/details/115319669
class S():
def __init__(self) -> None:
pass
# 堆排序
def heapify(self, tree, n, i):
"""把父节点和最大子节点交换
:param n: 总共的节点个数
:param i: 元素的索引, 对第i个元素做heapify
"""
# if i >= n: # 递归出口 0 <= i <= (n-1),但是由于并不会越界,此处不需要递归出口
# return
c1 = 2 * i + 1 # 左边子节点
c2 = 2 * i + 2 # 右边子节点
# 找出父节点&两个子节点中最大的节点
max_ele = i # 假设父节点为最大值
if c1 < n and tree[c1] > tree[max_ele]: max_ele = c1
if c2 < n and tree[c2] > tree[max_ele]: max_ele = c2
if max_ele != i:
tree[max_ele], tree[i] = tree[i], tree[max_ele]
# 递归 如果原先是max_ele节点,这里会被调换过,就是比较大的值被拿到父节点,换来了一个比较小的数,需要往下递归下去
self.heapify(tree, n, max_ele)
def build_heap(self, tree, n):
"""建堆;
:param n: 数组的长度或者节点的个数
"""
last_node = n - 1 # 最后一个节点
parent = (last_node - 1) // 2 # 最后一个节点对应的父节点
# 从最后一个非叶子节点逆序遍历, 调整建堆
for i in range(parent, -1, -1):
self.heapify(tree, n, i)
def HeapSort(self, tree, n):
# tree 数组,n 长度
"""堆排序"""
self.build_heap(tree, n)
for i in range(n - 1, -1, -1):
# 最后一个节点和最顶上的节点交换
tree[0], tree[i] = tree[i], tree[0]
# 拿出(砍断)最后一个节点(上一步交换完后最大的数已经在最后了),
# 而后从最顶上节点开始 heapify,又往下递归,直到形成稳定堆
# 此处 heapify的参数是 i 而不是 n,因为不断砍断以后,整个数组长度从 n 变成了 i
self.heapify(tree, i, 0)
return tree
s = S()
nums = [1, 3, 2, 6, 2, 0, 4, 8, 1]
print(s.HeapSort(nums, len(nums)))
# [0, 1, 1, 2, 2, 3, 4, 6, 8]