Java——堆

一、什么是堆

九月在老家是收割水稻的月份,每次打完水稻,农民伯伯就会拿稻杆累成一堆。我觉得这个稻杆堆和数据结构 外形有点相似哈。
在这里插入图片描述堆是一棵完全二叉树, 但是这个完全二叉树要满足条件:其中任意一个结点要 >= 其左孩子结点和有孩子结点,这叫大根堆;其中任意一个结点要 <= 其左孩子结点和有孩子结点,这叫小根堆。
堆的逻辑结构是一棵完全二叉树,但是其所有的元素是按完全二叉树的层序存储在一个一维数组当中的(物理结构是一维数组)。
在这里插入图片描述

二、堆的存储方式

堆是一棵完全二叉树,因此可以层序的规则采用顺序的方式来高效存储。对于非完全二叉树,则不适合使用顺序方式进行存储。
在这里插入图片描述
那么对于存储到数组中的堆,也要会还原成二叉树。
对于数组中的下标i

  • 如果i=0,则i表示为根节点,否则i结点的双亲为(i-1)/ 2
  • 对于i,如果 i * 2 + 1 小于数组的长度,则i的左孩子为 i * 2 + 1,否则无左孩子。
  • 对于i,如果 i * 2 + 2 小于数组的长度,则i的右孩子为 i * 2 + 2,否则无右孩子。

三、堆的创建

堆的创建有两种方式:向下调整和向上调整。

向下调整

对于一个不是堆的任意一个数组,采用向下调整为大根堆 我们可以这样做:
先调整最下面的每一层子二叉树变大根堆,再一层一层往上面调整,那么整棵树到最后也就变为大根堆了。

  • 1.先找到最后一个根结点 (叫child结点),再找child的父节点(叫parent 结点)。
  • 2.比较父结点与 左右孩子结点中最大的孩子结点的大小,如果大于最大孩子结点则不交换,小于则交换两结点 parent=child,child=child*2+1 同时child 要在数组有效数据的范围内。
  • parent - -,重复2,parent要在数组范围内。
    在这里插入图片描述
public class TestHeap {
   
	//堆存在一维数组elem中
    public int[] elem;
    //堆中的元素个数
    public int usedSize;

    public TestHeap() {
   
        this.elem = new int[10];
    }
    
    //先初始化数组
    public void  initElem(int[] array) {
   
        for (int i = 0; i < array.length; i++) {
   
            this.elem[i] = array[i];
            usedSize++;
        }
    }

	//创建堆
    public void createHeap() {
   
    //先调整最下面的每一层子二叉树变大根堆,再一层一层往上面调整。
        for (int parent = (elem.length-1-1)/2; parent >= 0 ;parent--) {
   
        
            siftDown(parent,this.usedSize);
        }

    }
//向下调整
    private void siftDown(int parent, int usedSize) {
   
    
        int child = parent*2+1;
        
        // child要在堆内
        while(child<usedSize) {
   
        
        //求出左右孩子中最大的孩子
            if(child+1<usedSize && elem[child]<elem[child+1]) {
   
                child++;
            }
            
            if(elem[child]>elem[parent]) {
   
                //大于就交换
                int tmp = elem[par
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是无敌小恐龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值