算法--堆

1 堆就是用数组实现的二叉树,所有它没有使用父指针或者子指针。堆根据“堆属性”来排序,“堆属性”决定了树中节点的位置。

堆属性:

堆分为两种:最大堆最小堆,两者的差别在于节点的排序方式。

在最大堆中,父节点的值比每一个子节点的值都要大。在最小堆中,父节点的值比每一个子节点的值都要小。这就是所谓的“堆属性”,并且这个属性对堆中的每一个节点都成立。

一个堆中的节点的高度为该节点到根节点最长简单路径上边的数目;

包含n个元素的堆的高度为θ(lgn);

PARENT(i) return Math.floor(i/2):求下标为i的元素的父节点的下标;

LEFT(i) return 2i:求下标为i元素的左子树的节点的下标;

RIGHT(i) return 2i+1:求下标为i元素的右子树的节点的下标;

2 含n个元素的堆的高度为floor(lgn)

假设n个元素的堆的高度为h。得2^h <= n <= 2^(h+1) - 1,因此h <= lgn < h+1。

3 当i>A.heap-size/2时,调用MAX-HEAPIFY(A,i)会有什么结果?

那么i都是叶子结点,所以原最大堆也不会改变。

对于一个树高为n的结点来说,MAX-HEAPIFY的时间复杂度是O(h)

MAX-HEAPIFY(A,i)

while (i<=A.heap-size/2)//由于6.2-4知道,i>A.heap-size/2以后,最大堆不会有任何改变。

{                       //这样也可以减少循环次数。

  l=LEFT(i)

  r=RIGHT(i)

  if l<=A.heap-size and A[l]>A[i]

     largest=l

  else largest=i

  if r<=A.heap-size and A[r]>A[largest]

     largest=r

  if largest!=i

     exchange A[i]<->A[largest]

  i=largest//把largest赋值给i,然后继续进行MAX-HEAPIFY(A,i)循环。

}

4 建堆方案:

总的时间复杂度为O(nlgn),但这个上界不是渐进紧确的,O(n)

由堆的性质可知,子数组A([n/2]+1..n)中元素都是树的叶节点。每个叶节点都可以看成只包含一个元素的堆;

BUILD-MAX-HEAP(A){

  A.heap-size=A.length;

  For I = [A.length/2] downto 1

     MAX-HEAPIFY(A,i);

}

5 堆排序:

时间复杂度为O(nlgn)

以最大堆为例,每次将第一个元素与最后一个元素交换,同时将堆的大小减一

HEAPSORT(A)

    BUILD-MAX-HEAP(A)

    for i = A.length downto 2

        exchange A[1] with A[i]

        A.head-size = A.head-size - 1

        MAX-HEAPIFY(A,1)

6 优先队列:

在一个包含n个元素的堆中,所有的优先队列的操作都可以在O(lgn)时间内完成

插入(INSERT(S,x)) 

取得最大值(MAXIMUM(S)) 

删除并返回最大值(EXTRACT-MAX(S)) 

将某一个元素key增大到制定的值(INCREASE-KEY(S,x,k))

HEAP-EXTRACT-MAX(S)

    if A.heap-size < 1

        error  "heap underflow"

    max = A[1]

    A[1] = A[A.heap-size]               # 将最后一个元素赋值给A[1],等同于删除最大值

    A.heap-size = A.heap-size - 1       # 通过减少堆数组的长度来‘删除’最后一个元素

    MAX-HEAPIFY(A,1)                    # 将A[1]中的元素放到恰当的位置

    return max

INSERT(S,x)

HEAP-INSERT(S,key) 

A.heap-size = A.heap-size - 1 

A[A.heap-size] = -∞ 

HEAP-INCREASE-KEY(A,A.heap-size,key)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值