最大堆、最小堆定义及其C++代码实现

资料:https://blog.csdn.net/guoweimelon/article/details/50904346
但是它的最大堆删除部分的代码有问题,详见链接里的评论区

定义
堆首先必须是一棵完全二叉树
最大堆:完全二叉树,父节点的值不小于子节点的值
最小堆:完全二叉树,父节点的值不大于子节点的值
在这里插入图片描述

用数组存储上图所示的最大堆
对于下标为 i ( 1 ≤ i ≤ n ) i (1 \leq i \leq n) i(1in)的节点:
父节点: i / 2 i/2 i/2,若 i = 1 i=1 i=1,则i是根节点
左子节点:2i,如果 2 i > n 2i > n 2i>n,则不存在左子节点
右子节点:2i+1,如果 2 i + 1 > n 2i+1 > n 2i+1>n,则不存在右子节点

最大堆的插入:时间复杂度O(logn)
肯定在数组末尾加入该数字,然后和父节点进行比较,balabala,也就是节点上浮操作。

最大堆的删除:时间复杂度O(logn)
删除根节点元素,用数组的最后一个元素来顶替,然后进行节点下沉

最大堆的创建:
方法一:可以通过最大堆的插入算法进行构建,即从空堆开始,依次插入数字。该方法的时间复杂度为O(n log n)
方法二:将时间复杂度降低到O(n),先将所有数据放入,然后逐个调整

struct MaxHeap{
    int heap[100];
    int currentSize=0;
    int maxSize=100;
    // 最大堆的创建,采用方法二
    void HeapInit(int a[],int n){
       currentSize = n;
       for(int i=0;i<n;i++)
        heap[i] = a[i];
       for(int i= (currentSize-2)/2; i>=0; i--){
         SiftDown(i);
       }
    }
    void SiftDown(int index){
         int cur = index;
         int son = 2*index+1;
         int tmp = heap[index];
         while(son < currentSize){
           if(son<currentSize-1 && heap[son]<heap[son+1])
                son++;
           if(tmp < heap[son]){
             heap[cur] = heap[son];
             cur = son;
             son = 2* cur + 1;
           }else
           break;

         }
         heap[cur] = tmp;

    }
  // 插入一个元素
    void HeapInsert(int value){
         if(currentSize == maxSize) return;
         currentSize++;
         int index = currentSize-1;
         while(index>0){
            if( heap[(index-1)/2] >= value) break;
            heap[index] = heap[(index-1)/2];
            index = (index-1)/2;
         }
         heap[index] = value;

    }
    // 删除一个元素
    int HeapDelete(){
         if(currentSize==0) return -1;
         int maxValue = heap[0];
         heap[0] = heap[currentSize-1];
         currentSize--;
         SiftDown(0);
         return maxValue;
    }
};
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值