堆的相关内容总结

堆的概念:
  堆实际是一棵完全二叉树,满足任意节点的值都大于(小于)其子树节点的值,称作大堆(小堆)
堆的存储结构:
  使用数组保存二叉树结构,方法即是将二叉树按层序遍历方式放入数组中
堆的下标关系:

  • 已知父节点的下标parent:左孩子(left)下标=parent2+1、右孩子(right)下标=parent2+2
  • 已知孩子下标(child)不分左右:父节点下标(parent)=(child-1)/2
    补充:

完全二叉树:对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树

满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树

堆的示意图:
在这里插入图片描述

堆的操作:
向下调整(注意只有当局部(即左右子树)为堆时,当前节点才能向下调整)
小堆:

 //向下调整(前提:左右子树必须是一个堆,才能向下调整
    public static void shifDownSmall(int[] array,int size,int parent){
        //此结点与其孩子结点进行比较,若孩子结点比父节点小,则交换,否则不变
        //交换节点后下标相应改变,被交换结点的下标继续作为父节点,与其双亲做比较
        int left=(parent*2)+1;
        while(left<size){
            //两个孩子结点中选一个最大的
            if(left+1<size&&array[left+1]<array[left]){
                left++;
            }
            if(array[left]<array[parent]){
                swap(array,left,parent);
                //更新,继续向下调整
                parent=left;
                left=(parent*2)+1;
            }else{
                break;
            }
        }
    }
    public static void swap(int[] arr,int x,int y){
        int temp=arr[x];
        arr[x]=arr[y];
        arr[y]=temp;
    }

大堆:

public static void  shiftDownBig(int[] array,int size,int parent){
        int left=(parent*2)+1;
        while(left<size){
            //两个孩子结点中选一个最大的
            if(left+1<size&&array[left+1]>array[left]){
                left++;
            }
            if(array[left]>array[parent]){
                swap(array,left,parent);
                parent=left;
                left=(parent*2)+1;
            }else{
                break;
            }
        }
    }

建堆
注意:
  此时堆的左右子树既不是大堆也不是小堆,若还是从根结点开始调整,则无法确定调整次数,以及具体算法
  因此要从最小子树开始调整,使局部调整为子树,然后再在局部的基础上才能对上面的结点实现向下调整
小堆:

public static void createSmallHeap(int[] array){
       for(int i=(array.length-2)/2;i>=0;i--){
           shifDownSmall(array,array.length,i);
       }
   }

大堆:

 public static void createBigHeap(int[] array){
        for(int i=(array.length-2)/2;i>=0;i--){
            shiftDownBig(array,array.length,i);
        }
    }

堆的应用—优先级队列:
优先级队列:
  数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列
  PriorityQueue pq=new PriorityQueue<>();
两个基本操作:
入队列(堆的向上调整):

  1. 首先按尾插方式放入数组
  2. 比较其和其双亲的值的大小,如果双亲的值大,则满足堆的性质,插入结束
  3. 否则,交换其和双亲位置的值,重新进行 2、3 步骤
  4. 直到根结点
    小堆
    //向上调整,例如在原有的堆中加入一个元素(实现优先级队列)可模仿入队过程
    //只需要和根节点比较
    //然后更新节点按位置
    public static void shitUpSmall(int[] array,int size,int child){
        int parent=(child-1)/2;
        while(child>0){
        //变换条件实现大堆:array[child]>array[parent]
            if(array[child]<array[parent]){
                swap(array,child,parent);
                child=parent;
                parent=(child-1)/2;
            }else{
                break;
            }
        }
    }

 public void offer(int value){
        if(sz==arr.length){
            arr=Arrays.copyOf(arr,arr.length*2);
        }
        //1.尾插
        //2.向上调整
        arr[sz++]=value;
        MyHeap.shifUpSmall(arr,sz,sz-1);
        //加入最后一个元素进行向上调整

    }

出队列:
  为了防止破坏堆的结构,删除时并不是直接将堆顶元素删除,而是用数组的最后一个元素替换堆顶元素,然后通过
向下调整方式重新调整成堆

public int poll(){
        if(sz>0){
            int tmp=arr[0];
            arr[0]=arr[sz-1];
            --sz;
            MyHeap.shifDownSmall(arr,sz,0);
            return tmp;
        }else{
            return -1;
        }
    }

返回队顶元素:

public int peek(){
        return arr[0];
    }

堆的应用还有堆排序,在海量元素中找前k个最大等应用,目前掌握还不是很好,在后期文章中会介绍。
  结语:如有不足,请多指教。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值