手写堆排序

参考: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]
posted @ 2022-05-11 19:00  麦克斯的园丁  阅读(73)  评论(0编辑  收藏  举报