数据结构:堆——概念、代码实现

1.概念:二叉堆是经常被提到的堆, 堆满足:
堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全二叉树

2.分类:堆具体分为大根堆和小根堆。大根堆的父节点一定是比子节点的value大的,小根堆的父节点一定是比子节点的value小的。
父节点和子节点的关系,已知父节点为k,则左孩子为2k+1,右孩子为2k+2,且都应该小于等于总结点个数。根节点从0开始,因为底层是数组。
已知子节点位置为k,则父节点位置为(k-1)/2,向下取整
(以大根堆为例) 向下调整:
整体思想: 从最后一个子树开始调整。如果字节比父节点大,则交换。每一棵树都是向下调整。
在这里插入图片描述3.创建堆

public class Heap {
    public int []elem;//底层是一个数组
    public  int  usedSize;//存放数据个数

    public Heap() {
        this.elem = new int[10];
    }
    public void creatHeap(int[] arr){
        for (int i = 0; i <arr.length; i++) {
            this.elem[i]=arr[i];
            this.usedSize++;
        }
        //从最后一个子树开始调整
        for (int i = (this.usedSize-1-1)/2; i >=0 ; i--) {//this.usedSize-1代表最后一个节点,(this.usedSize-1-1)/2每颗子树的根节点
                adjustDown(i,this.usedSize);
        }
    }
    public  void  adjustDown(int root,int len){//root代表每个子树的开始位置,len代表的是结束位置。
       int parent=root;
       int child=2*parent+1;//左孩子
       while (child<len){//孩子节点的下标一定会小于等总节点的数量-1。
           if(child+1<len){
               //有右孩子
               if (elem[child]<elem[child+1]){//找到左右孩子的最大值,child保存最大孩子的坐标
                   child=child+1;
               }
           }
           //比较child节点和父节点的值,如果大则交换
           if (elem[child]>elem[parent]){
               int tmp=elem[child];
               elem[child]=elem[parent];
               elem[parent]=tmp;
               parent=child;
               child=2*parent+1;
           }else {//如果小则不用交换,说明已经调整好了
               break;
           }
       }
    }
    public void show(){
        for (int i = 0; i <this.usedSize ; i++) {
            System.out.print(elem[i]+" ");
        }
    }
}

在这里插入图片描述最终的堆:
在这里插入图片描述

创建堆的时间复杂度:O(n),调整一次堆的时间复杂度O(log n)
4.给堆里插入元素

新增时,在数组尾部增添元素,并且调整堆。向上调整

    public void  push(int value){
        //0.判断是否扩容
        if (this.elem.length==this.usedSize){

            this.elem= Arrays.copyOf(this.elem,elem.length*2);
        }
        elem[this.usedSize]=value;
        this.usedSize++;
        adjustUp(this.usedSize-1);
    }

    private void adjustUp(int child) {
        int parent=(child-1)/2;
        while (child>0){
            if (elem[parent]<elem[child]){
                int tmp=elem[parent];
                elem[parent]=elem[child];
                elem[child]=tmp;
                child=parent;
                parent=(child-1)/2;
            }else {
                break;
            }
        }

    }

5.堆删除元素

  public void pop(){//每次移除的都是堆的元素
        if (this.usedSize==0){//是否为空
            return;
        }
        int tmp=this.elem[this.usedSize-1];
        this.elem[this.usedSize-1]=this.elem[0];
        this.elem[0]=tmp;
        this.usedSize--;//删除这个元素
        adjustDown(0,this.usedSize);

  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值