数据结构之堆底层实现的循序渐进

题外话

把没写的都补回来!

正题

堆

概念

堆是一棵完全二叉树,因此可以层序的规则采用顺序的方式来高效存储,

大根堆:指根结点比左右孩子都大的堆

小根堆:指根结点比左右孩子都小的堆

性质

1.堆中某个节点的值总是不大于或不小于其父节点的值

2.堆总是一棵完全二叉树。

向下调整

将数组调整为大根堆:

1.从最后一颗子树开始调整,利用二叉树的性质找到最后一颗树的父亲节点 (i-1)/2

2.获取左右孩子的最大值和根节点比较,如果比根节点大就交换,并且继续向下调整

3.调整完结点之后,让结点下标减1,即可从下往上调整为大根堆,一直调整到0下标

底层代码实现及详解

复制代码
public class HeapBottom {
//创建数组
    private int[] elem;
//计数数组元素个数
    public int usedSize;
    public HeapBottom()
    {
        this.elem=new int[10];
    }
    //初始化elem数组
     public void intElem(int[] array)
     {
         for (int i = 0; i < array.length; i++) {
             elem[i]=array[i];
             usedSize++;
         }
     }
    //创建大根堆
     public void createHeap()
     {

         for (int parent = (elem.length-1)/2; parent>=0 ; parent--) {
//向下调整
        siftDown(parent,usedSize);

         }
     }
     //向下调整
    private void siftDown(int parent,int len)
    {
//创建child为parent左子树
        int child=parent*2+1;
//child小于数组长度时
        while (child<len)
        {
//如果child+1也小于数组长度,并且左子树小于右子树
            if (child+1<len&&elem[child]<elem[child+1])
            {
//将右子树下标赋给左子树,此时child相当于右子树
                child=child+1;
            }
//如果右子树大于父亲结点
            if (elem[child]>elem[parent])
            {
//交换元素值
                
复制代码
                swap(parent,child);
复制代码
//并继续向下调整(因为刚交换完的结点不一定是交换后的最大值),将交换完的子树下标给到parent
                parent=child;
//让child为parent左孩子
                child=parent*2+1;
            }
//如果右子树不大于父亲节点,则退出
            else {
                break;
            }

        }

    }

//交换代码

private void swap(int i,int j)

{

int temp=elemi;

elemi=elemj;

elemj=temp;

}

}

添加元素

//添加元素,是在最后一个位置添加元素,然后再向上调整

public void push(int val)

{

//判断是否满了,满了扩容

if (isFull())

{

Arrays.copyOf(elem,elem.length*2);

}

//赋值给最后一个元素

elemusedSize=val;

//向上调整

siftUp(usedSize);

usedSize++;

}public boolean isFull()

{

return usedSize==elem.length;

}

//向上调整

public void siftUp(int child)

{

int parent=(child-1)/2;

while (child>0) {

if (elemchild > elemparent) {

swap(child, parent);

child = parent;

parent = (child - 1) / 2;

}

else {

break;

}

}

}

删除元素

//删除元素(数组0下标位置元素和最后一个元素互换位置,然后向下调整即可)

public int pop() {

//判断是否为空数组,空了返回-1(自定义异常也可以)

if (empty())

{

return -1;

}

//将删除元素记录下来

int tmp=elem0;

//互换位置

swap(0,usedSize-1);

//数组元素数量-1

usedSize--;

// 向下调整

siftDown(0,usedSize);

return tmp;

}

//判断是否为空

public boolean empty() {

return usedSize==0;

}

}

小结

今天还没吃饭,先去吃饭休息休息!!

相关推荐
谢亮_vipxieliang39 分钟前
泛型擦除、通配符与 PECS 一次讲透
java·面试
八解毒剂1 小时前
【计组】中央处理器CPU
java·开发语言·计算机组成原理
乐迪信息1 小时前
港口船舶逆行怎么管?AI防爆摄像机搭载智能检测算法
大数据·人工智能·深度学习·算法·计算机视觉
打工仔折腾 AI2 小时前
工业场景下时序库与实时计算一体化架构选型实践对比
java·开发语言·后端·python·性能优化·架构·ai agent 实战
ZealSinger2 小时前
Java虚拟线程上线后瓶颈转移到哪看三层
java·开发语言·firefox
2601_961133282 小时前
盘立方软件指标文华期货公式下载
java
蜗牛互联网2 小时前
长任务多Agent共享文件系统的Manifest交接模式
java·人工智能·后端
Sirens.2 小时前
Java并发锁详解:六类锁策略与 synchronized 底层原理
java·前端·算法
和裕3 小时前
全纸结构重型纸箱能否满足 1 吨以上设备出口熏蒸豁免要求?通关合规性全解析
大数据·运维·网络·人工智能·算法
sunshine22 girl3 小时前
Java学习五 面向对象高级5 内部类1
java·学习