自己实现一个简单的优先队列-二叉堆

需求

自己实现一个简单的优先队列(Priority Queue)-二叉堆(Binary Heap).

二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树)。二叉堆有两种:最大堆和最小堆。最大堆:父结点的键值总是大于或等于任何一个子节点的键值;最小堆:父结点的键值总是小于或等于任何一个子节点的键值。

接口

interface PriorityQueue<E extends Comparable<? super E>> {
    int size();

    boolean isEmpty();

    void add(E e);

    E findMin();

    E deleteMin();
}

实现类

import java.util.Arrays;
import java.util.NoSuchElementException;

class BinaryHeap<E extends Comparable<? super E>> implements PriorityQueue<E> {
    private static final int DEFAULT_CAPACITY = 10;

    private Object[] array;

    private int size;

    public BinaryHeap() {
        this(DEFAULT_CAPACITY);
    }

    public BinaryHeap(int size) {
        size = 0;
        array = new Object[size];
    }

    public BinaryHeap(E[] arr) {
        size = arr.length;
        array = new Object[(size + 2) * 11 / 10];
        int i = 1;
        for (E e : arr) {
            array[i++] = e;
        }
        buildHeap();
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public void add(E e) {
        if (size == array.length - 1) {
            enlargeCapacity(array.length * 2 + 1);
        }
        int h = ++size;
        for (array[0] = e; e.compareTo(array(h / 2)) < 0; h /= 2) {
            array[h] = array[h / 2];
        }
        array[h] = e;
    }

    private void enlargeCapacity(int newCapacity) {
        array = Arrays.copyOf(array, newCapacity);
    }

    @Override
    public E findMin() {
        rangeCheck();
        return array(1);
    }

    @Override
    public E deleteMin() {
        E min = findMin();
        array[1] = array[size--];
        percolateDown(1);
        return min;
    }

    private void percolateDown(int h) {
        E e = array(h);
        int c;
        while (h * 2 <= size) {
            c = h * 2;
            if (c + 1 <= size && array(c + 1).compareTo(array(c)) < 0) {
                c++;
            }
            if (array(c).compareTo(e) < 0) {
                array[h] = array[c];
                h = c;
            }
            else {
                break;
            }
        }
        array[h] = e;
    }

    private void buildHeap() {
        for (int i = size / 2; i > 0; i--) {
            percolateDown(i);
        }
    }

    @SuppressWarnings("unchecked")
    private E array(int index) {
        return (E) array[index];
    }

    private void rangeCheck() {
        if (size == 0) {
            throw new NoSuchElementException();
        }
    }
}

测试

PS

其实这里可以看到,按最小值输出的话,会把数据有序输出,堆排序就是用了这样的方法对数据进行排序的,大根堆与小根堆分别对应顺序排列和逆序排列。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值