最小堆建立和堆排序

堆树的定义:

(1)堆树是一颗完全二叉树;

(2)堆树中某个节点的值总是不大于或不小于其孩子节点的值;

(3)堆树中每个节点的子树都是堆树。

当父节点的键值总是大于或等于任何一个子节点的键值时为最大堆。 当父节点的键值总是小于或等于任何一个子节点的键值时为最小堆。如下图所示,左边为最小堆,右边为最大堆。

 

数组与堆

无序数组转化成原始的二叉堆:

453261

 

构建最小堆:

元素下沉思想:从无序数组的最后往前遍历,堆树从下层到上层依次搭建完成

1 从叶子节点(无序数组的最后一个元素)出发,把当前的parent设置为无序数组中的最后一个数(也就是叶子节点),依次往前遍历,当parent是叶子节点,就不做操作

2 当parent遍历到非叶子节点,此时,它就有左子节点和右子节点或者只有左子节点。需要做的操作:先在左右子节点中找到最小元素所在的索引,然后将左右子节点中的最小元素与parent的节点,进行比较,如果小于,则交换,同时更新parent和child的位置。否则不交换,退出当前循环。

3 “元素下沉”的终止条件就是父节点的元素值不大于其任意左右子节点的元素值,或者当前父节点无子节点(即当前节点为叶子节点)。

def heap_min(heap):
    for parent in range(len(heap)-1,-1,-1):
        child = 2*parent+1
        while child <len(heap):
            if child+1<len(heap) and heap[child+1]<heap[child]:
                child += 1
            if heap[parent]<= heap[child]:
                break
            heap[parent],heap[child] = heap[child],heap[parent]
            parent,child = child,2*child+1
    return heap
    
    
print(heap_min([4,5,3,2,6,1]))

输出结果是:构建了最小堆

堆排序:

是指利用堆(最大堆、最小堆)这种数据结构所设计的一种排序算法。堆是一个完全二叉树的结构,并同时满足如下性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

def sift_down(arr, start, end):
    root = start
    while True:
        # 从root开始对最大堆调整
        child = 2 * root + 1
        if child > end:
            break
        # 找出两个child中交大的一个
        if child + 1 <= end and arr[child] < arr[child + 1]:
            child += 1
        if arr[root] < arr[child]:
            # 最大堆小于较大的child, 交换顺序
            arr[root], arr[child] = arr[child], arr[root]
            # 正在调整的节点设置为root
            root = child
        else:
            # 无需调整的时候, 退出
            break


def heap_sort(arr):
    # 从最后一个有子节点的孩子还是调整最大堆
    first = len(arr) // 2 - 1
    for start in range(first, -1, -1):
        sift_down(arr, start, len(arr) - 1)
    # 将最大的放到堆的最后一个, 堆-1, 继续调整排序
    for end in range(len(arr) -1, 0, -1):
        arr[0], arr[end] = arr[end], arr[0]
        sift_down(arr, 0, end - 1)

def main():
    # [7, 95, 73, 65, 60, 77, 28, 62, 43]
    # [3, 1, 4, 9, 6, 7, 5, 8, 2, 10]
    l = [3, 1, 4, 9, 6, 7, 5, 8, 2, 10]
    print (l)
    heap_sort(l)
    print (l)


if __name__ == "__main__":
    main()

 

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值