数据结构——堆

      相较于其他数据结构,堆是新接触到的。那么就在今天仔细地研究一下。
      什么是堆?堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象(节选自百度百科)。简单点看,堆也是二叉树的一种。分为大顶堆(父节点大于子节点),小顶堆(子节点大于父节点)。堆是平衡的,但堆不是二叉平衡树。
      堆和二叉平衡树的区别:二叉平衡树,一定是二叉排序树。左节点一定大于右节点。对堆来说(以大顶堆为例),只是满足了父节点大于子节点而已。

本文讨论的堆都以大顶堆为例。

      堆有两个优势:插入元素,寻找最大元素。(具体细节见下文)
       对于堆来说,有两个最最基本的运算,那就是Sift-up和Sift-down。

Sift-up

       向上调整,当前值大于父节点值时,进行调整,将当前值和父节点进行交换。具体伪代码见下图:
在这里插入图片描述
时间复杂度分析:
      最坏情况是从最底层叶子交换至根,进行logn向下取整次交换,时间复杂度为O(logn)

Sift-down

      向下调整,当前值小于子节点值时,进行调整,选出左右节点较大的一个和父节点进行交换,具体伪代码见下图:
在这里插入图片描述
时间复杂度分析:
      最坏情况是从根交换至叶子,进行logn向下取整次交换,时间复杂度为O(logn)

由以上两个基本操作,可以构成额外四个操作:

Delete-max[H]:从一个非空的堆H中删除最大键值的数据项并将数据项返回

Insert[H, x]:插入项x到堆H中

Delete[H, i]:从堆H中删除第i项

Makeheap[A]:将数组A转换成堆

四个操作大致可分为两类,删除和插入

删除

      删除指定位置i的元素,可以选择用位置n的元素代替i处的元素再把堆进行调整。因为无法确定原位置n处元素和后来的父节点或者子节点的大小关系,所以要进行比较。根据结果选择Sift-up/Sift-down操作。具体伪代码见下图:
在这里插入图片描述
时间复杂度分析:
      删除操作,是将指定位置进行替换,替换操作时间复杂度为O(1)。后再进行sift-up或者sift-down操作。总时间复杂度:O(logn)。

插入

       插入操作先将要插入的数,放在数组末尾。然后再对末尾进行Sift-up操作即可。具体伪代码如图:
在这里插入图片描述
时间复杂度分析:
      将数插入末尾,时间复杂度为O(1)。再进行sift-up操作,时间复杂度为O(logn)。总时间复杂度为O(logn)。

Delete-max[H]:
      对于大顶堆来说,最大的值就是根节点的值。在数组中的位置是1。所以可以先将最大值保留下来,再调用删除(Delete函数)。具体伪代码如图:
在这里插入图片描述
Makeheap[A]
      创建堆的过程,可以转化为向堆中一个一个插入的过程。对Insert函数循环即可。但这种每插入一个值,都要对堆进行调整。选用另外一种方法:先将数组乱序摆放,再从最后一个有子节点的节点向上进行Sift-down操作。时间复杂度为O(n)。具体伪代码如图:
在这里插入图片描述
时间复杂度分析:
      第一种方法创建堆过程是对N个数字调用插入操作,总时间复杂度是O(nlogn)。第二种方法,调用sift-down操作中每次循环中进行两次比较操作(具体见上文sift-down部分)。同时循环执行总次数的上界小于2n(具体推导见下图)。所以第二种方法的时间复杂度是O(n)。
在这里插入图片描述
      另外关于堆的操作是堆排序,相较于其他排序来说,堆排序是一种较好的排序方法,时间复杂度是O(nlogn)。对于大顶堆来说,堆排序是将根节点的依次拿出,并在拿出后对堆进行重构。具体伪代码如图:
在这里插入图片描述

内存分配——堆

      在编写程序的过程中,对于内存的分配分为静态和动态。大多数情况下,编译器静态分配栈结构。堆是一种动态分配的结构,使用malloc函数调用(C语言中头文件为<stdlib.h>。在堆实现的最低层是数据结构链表。在此对于内存中的堆不做过多阐述,过后会补一篇讨论内存中各个结构分配专题博文。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值