建堆与堆排序详细解析

本文深入解析了堆的特性,包括大根堆与小根堆的定义,以及堆作为完全二叉树的性质。接着,介绍了如何通过自底向上的方式构建堆,以小根堆为例,讲解了递归与非递归两种实现方式。然后,详细阐述了堆排序的过程,即不断调整堆并移除最小元素。最后,分析了建堆和堆排序的算法复杂度,分别为O(n)和O(nlogn)。
摘要由CSDN通过智能技术生成
1.堆的特性

堆有大根堆和小根堆,大根堆的子树,父结点比子结点都要大,小跟堆的子树,父节点都要比子结点小。

堆有这样的特性:

  • n个元素的堆的高度是 l o g n logn logn,因为堆是一棵完全二叉树或者近似一棵完全二叉树。
  • 堆中,如果父节点的index是n,那么这个结点的左右子结点的index 分别是 2 ∗ n + 1 ​ 2*n+1​ 2n+1 2 ∗ n + 2 ​ 2*n +2​ 2n+2,并且,如果堆总共有n个元素,并且根结点的index为0,堆中最后一个有子结点的父节点的index一定是 n / / 2 − 1 ​ n//2 -1​ n//21
  • 最大堆,最大的元素在根节点,最小堆,最小的元素在根节点。
2.如何建堆

如何从一个无序的列表建起起一个大根堆或者小根堆呢?利用堆的特性,我们从最后一个有子节点的父节点开始进行调整,也就是索引值为 n / / 2 − 1 n//2 -1 n//21的结点。下面以建立小跟堆为例讲解。

  • 首先我们拿到一个根节点root,检查结点root的两个子节点谁的值更小,注意需要保持两个子节点的索引值不超过堆的长度,超过了说明没有子节点

  • 比较较小的子节点和父节点谁的值小,如果子结点的值更小,则需要交换子结点和父节点。注意!!如果这里发生了交换,那么可能会影响原来较小子结点已经形成的堆,所以我们需要继续调整堆,所以这里我们可以用递归的写法。具体看代码中,如果用非递归的写法则是,我们要一直循环,向下找到这个父节点该插入的位置!!

这是递归写法

def sink(num_list, root, length):
    if 2 * root + 1 < length:
        child = 2 * root + 2 if 2 * root 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值