二叉堆简单实现与应用

从二叉树谈二叉堆:

二叉树可以简单认为是父节点最多由左、右两个子节点组成的树,常用的二叉树有完全二叉树、二叉搜索树。二叉搜索树在极端境况下存在“跛脚”的问题,由此又有了二叉平衡树。二叉堆相比于二叉搜索树条件要宽松一 些,只要求父节点比它的左右孩子都大(小)。


大顶堆、小顶堆

大顶堆的任何一个父节点的值,都大于或等于它左、右孩子 节点的值;
小顶堆的任何一个父节点的值,都小于或等于它左、右孩子 节点的值。
二叉堆的特点:大顶堆的堆顶是整个堆中的最大元素;小顶堆 的堆顶是整个堆中的最小元素。
二叉堆使用数组来储存节点,下面就拿大顶堆来举例讲解二叉堆的操作:
1、上浮,当我们在二叉堆的最后插入一个节点,为了保证二叉堆还是满足最大堆的特点,需要通过不断的上浮来满足条件;
2、下沉,当我们把最大堆的堆顶节点换成另一个节点,这时候需要通过下沉来重新构造大顶堆。


代码实现(java)

下面用java实现大顶堆的上浮和下沉操作

上浮的代码如下:

public void shangfu(int[] array){
    // 二叉堆数组的最后一个节点进行上浮
    int childIndex = array.length-1;
    // 父节点的位置
    int parentIndex = (childIndex-1)/2;
    int temp = array[childIndex];
    // 循环,当子节点大于父节点,上浮
    while(childIndex>0&&temp>array[parentIndex]){
        array[childIndex] = array[parentIndex];
        childIndex = parentIndex;
        parentIndex = (parentIndex-1)/2;
    }
    // 最后将temp进行赋值
    array[childIndex]=temp;
}

下沉的代码如下:

public void xiachen(int[] array,int parentIndex,int length){
    // 父节点暂时存放
    int temp = array[parentIndex];
    // 左节点
    int childIndex = 2*parentIndex+1;
    while(childIndex<length){
        // 找出左节点和右节点中的较大节点
        if((childIndex<length-1)&&(array[childIndex+1]>array[childIndex])){
            childIndex++;
        }
        // 如果父节点大于子节点
        if(temp>=array[childIndex]){
            break;
        }
        // 将子节点赋值给父节点
        array[parentIndex] = array[childIndex];
        parentIndex = childIndex;
        childIndex = 2*childIndex+1;
    }
    // 最后将temp进行赋值
    array[parentIndex] = temp;
}

应用:堆排序

下面介绍二叉堆常用的使用场景——堆排序:堆排序的过程是先将数组构建为大顶堆,然后交换堆顶与堆尾的节点,在去除最后一个节点的基础上,通过下沉来重新构建大顶堆,多次循环后,数组就完成由小到大循序排列了。

public void sort(int[] array){
    // 构建大顶堆
    for(int i=array.length/2-1;i>=0;i--){
        xiachen(array,i,array.length);
    }
    System.out.println(Arrays.toString(array));
    for(int i=array.length-1;i>0;i--){
        int temp = array[i];
        array[i] = array[0];
        array[0] = temp;
        xiachen(array,0,i);
    }
    System.out.println(Arrays.toString(array));
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值