Java实现二叉堆 - 优先队列的简单实现

    最近在复习算法相关知识,今天复习到了二叉堆。

    二叉堆是一个完全二叉树,又分为最大堆和最小堆。最大堆的每一个父节点都大于它的两个子节点,最小堆的每个父节点都小于它的两个子节点。本文中,我简单编写代码实现了最小堆,本例也可看作是优先队列的一种简单实现。 

package com.zhangyu.study.test20191120;

import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * Function: 模拟二叉堆  模拟最小堆
 *
 * @author zhangyu
 * Date: 2019/11/20
 * @since JDK 1.8
 */
public class MyBinaryHeap {

    /**
     * 数据
     */
    private int [] data;

    /**
     * 数据大小
     */
    private int size;

    /**
     * 加载因子
     */
    private static final double LOAD_FACTOR = 0.75;

    /**
     * 默认数据容量
     */
    private static final int defaultCapacity = 12;

    /**
     * 默认构造器
     */
    public MyBinaryHeap() {
        this(defaultCapacity);
    }

    /**
     * 指定默认容量的构造器
     * @param defaultCapacity   默认容量
     */
    public MyBinaryHeap(int defaultCapacity) {
        data = new int[defaultCapacity];
    }

    /**
     * 将数组转换成二叉堆
     * @param originData    原始数据
     */
    public MyBinaryHeap(int[] originData) {
        data = originData;
        size = originData.length;
        // 构造堆
        for (int i = (size -2) >> 1;i>=0;i--  ) {
            down(i) ;
        }

    }

    /**
     * 上浮操作 将最后一个元素进行上浮 在增加元素时会遇到上浮
     */
    private void up(){
        // 最后一个节点的索引
        int childIndex = size-1;
        // 需要上浮的数据
        int tmp = data[childIndex];
        // 父节点索引
        int parentIndex = (childIndex-1) >> 1;
        while (childIndex > 0 && tmp < data[parentIndex]) {
            data[childIndex] = data[parentIndex];
            childIndex = parentIndex;
            parentIndex = (childIndex-1) >> 1;
        }
        data[childIndex] = tmp;
    }

    /**
     * 下沉操作 在构建堆的时候,只要将所有非子节点依次下沉
     * @param parent    需要下沉的节点索引
     */
    private void down(int parent){
        // 临时数据
        int tmp = data[parent];
        // 左子节点的索引
        int leftChild = (parent << 1) +1;
        while (leftChild < size) {
            // 如果有右节点,并且右节点小于左节点,则父节点与右节点进行交换
            if (leftChild+1 < size && data[leftChild]>data[leftChild+1]) {
                // 这时候其实应该叫rightChild了
                leftChild ++;
            }
            if (tmp <= data[leftChild]) {
                break;
            }
            data[parent] = data[leftChild];
            parent = leftChild;
            leftChild = (parent << 1 )+1;
        }
        data[parent] = tmp;
    }

    /**
     * 当数组中有效元素的数量达到加载因子控制的数量时,进行扩容操作
     */
    private void resize(){
        if (size >= data.length * LOAD_FACTOR) {
            int[] newData = new int[data.length << 1];
            System.arraycopy(data,0, newData, 0, size);
            data = newData;
        }
    }

    /**
     * 向二叉堆中增加元素
     *
     * 思想是将新增的元素添加到当前最后一个有效元素的后面,然后将最后一个有效元素进行上浮操作
     *
     * @param data  添加的数据
     */
    public void add(int data) {
        resize();
        this.data[size++] = data;
        up();
    }

    /**
     * 移除元素  即移除第一个元素
     *
     * 思想是将第一个元素返回,然后将最后一个有效元素放到第一个元素的位置,进行下沉操作
     *
     * @return      移除元素的值
     */
    public int remove(){
        int tmp = data[0];
        data[0] = data[--size];
        down(0);
        return tmp;
    }

    /**
     * 打印当前数组
     */
    public void print(){
        if (size == 0) {
            System.out.println("None !");
        } else {
            System.out.println(Arrays.stream(data).limit(size).mapToObj(Integer::toString).collect(Collectors.joining(" ")));
        }
    }


    public static void main(String[] args) {
        MyBinaryHeap heap = new MyBinaryHeap(new int[]{1,3,2,6,5,7,8,9,10,0});
        heap.print();
        heap.add(2);
        heap.print();
        heap.remove();
        heap.print();
    }

}

 

    水平有限,如有错误,请您指出!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值