heap-堆

  • 主要要解决的问题( O(logn) ):

    • insert
    • extract_min
  • 1.二叉树的形式呈现

    • 条件:

      • Heap Property:子节点大于父节点
      • Shape property:每一层一定是从左到右
    • insert(假设最开始是这样的)

            1
          5  2
        6 8 7 4
      10
      
      • 这时候假设要插入3,那首先位置一定是在10右边,然后再看条件Heap Property,那那么只需要跟父节点比就行,到比父节点大就行了
      • 最坏的结果也就是 O(logn)
    • 考虑树的h(高度)与n(总节点个数)

      1 + 2 + 2^2 + ... + 2^(h-2)
      < n
      <= 1 + 2 + 2^2 + ... + 2^(h-1)
      --------->
      2^(h-1)-1 < n <= 2^(h)-1
      --------->
      h < log(n+1)+1 <= h+1
      
    • extract_min

      • 1.把根结点取出后,用最右下角的的结点放到根结点
      • 2.跟两个子结点中较小的一个交换,直到两个子结点比它大或者或者为空
      • 最坏的结果也就是 O(logn)
  • 1.数组的形式呈现

    • 1.假设最开始堆是这样的:

           2
         3   4
        5 8 7 6
      10 9
      
    • 2.那么在数组中应该是这样存储的:

      index 1 2 3 4 5 6 7 8  9
      value 2 3 4 5 8 7 6 10 9
      
    • 3.以extract_min为例,第一步交换到根结点:

      index 1 2 3 4 5 6 7 8  9
      value 9 3 4 5 8 7 6 10 -  
      
    • 4.第一次交换后为:

      index 1 2 3 4 5 6 7 8  9
      value 3 9 4 5 8 7 6 10 - 
      
    • 5.第二次交换后为:

      index 1 2 3 4 5 6 7 8  9
      value 3 5 4 9 8 7 6 10 - 
      
    • 6.再来回顾交换的过程:

      • A[1]与min(A[2],A[3])交换,A[2]与min(A[4],A[5])交换,很明显可以看到我们可以在constant time内找到应该比较的两个下标,并且交换的次数最多也只是log(n)
      • insert过程差不过,假设我们要插入结点的index是k,那么我们也很容易在constant time内找到父结点的index=k/2
    • 7.堆排序

      • 1.就是n词call insert,n次call extract_min,那么按理说时间复杂度就是O(2*n*logn)

      • 2.其实insert可以优化成O(n),做法很简单,就最开始全部随便填进array

            1
          4   5
         8 3 2 9
        7 6
        
        • 从最下层往上(从右往左)交换就行了,8跟6换,5跟2换,3跟4换
      • 复杂度O(n)的证明:

        2^h                  2^h      2^h           2^h
        ---(个结点)*0(次交换)+----x1 + ---x2 + ... + ---*(h-1)
         2                    4        8            2^h
        
        ------------------->
        2^(h-2)x1 + 2^(h-3)x2 + 2^(h-4)x3 + ... + 1x(h-1)
        -------------------
        因为:1+c+c^2+c^3+...=1/(1-c)
        求导:1+2c+3c^2+3c^2+...=1/(1-c)^2
        -------------------
        对比上式,把2^(h-2)提出来,容易计算出<2^(h-2)*4=2^h=n
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值