BinaryHeap

来自维基的解释:堆通常是一个可以被看做一棵树的数组对象。在队列中,调度程序反复提取队列中第一个作业并运行,因为实际情况中某些时间较短的任务将等待很长时间才能结束,或者某些不短小,但具有重要性的作业,同样应当具有优先权。堆即为解决此类问题设计的一种数据结构。[1]

性质:

堆的实现通过构造二叉堆(binary heap),实为二叉树的一种;由于其应用的普遍性,当不加限定时,均指该数据结构的这种实现。这种数据结构具有以下性质。

  • 任意节点小于它的所有后裔,最小元在堆的根上(堆序性)。
  • 堆总是一棵完全树
各种操作时间复杂度
操作 描述 时间复杂度
build建立一个空堆O(n)
insert向堆中插入一个新元素O(\log n)
update将新元素提升使其符合堆的性质 
get获取当前堆顶元素的值O(1)
delete删除堆顶元素O(\log n)
heapify使删除堆顶元素的堆再次成为堆

package org.jerry.datastructure;

public class BinaryHeap<T extends Comparable<? super T>> {

    /** store data and abort array[0] */
    private T[] array;

    /** the current number of data in heap */
    private int currentSize;

    /** default capacity */
    private static final int DEFAULT_CAPACITY = 10;

    public BinaryHeap() {
        this(DEFAULT_CAPACITY);
    }

    public BinaryHeap(int size) {
        currentSize = 0;
        array = (T[]) new Comparable[size + 1];
    }

    /**
     *  Insert an element
     * @param x
     */
    public void insert(T x) {
        if (currentSize == array.length - 1)
            enlargeArray(array.length * 2 + 1);
//		int hole = ++currentSize;  // 大小加1

        siftup(++currentSize, x);
    }

    /**
     * 为将元素X插入堆中,找到空闲位置,建立一个空穴,若满足堆序性(英文:heap order),则插入完成;
     * 否则将父节点元素装入空穴,删除该父节点元素,完成空穴上移。直至满足堆序性。这种策略叫做上滤(percolate up)。[1]
     * @param hole
     * @param x
     */
    private void siftup(int hole, T x) {
        for (; hole > 1 && x.compareTo(array[hole / 2]) < 0; hole /= 2)
            array[hole] = array[hole / 2];
        array[hole] = x;
    }

    /**
     * 堆大小扩大一倍
     * @param size
     */
    private void enlargeArray(int size) {
        T[] old = array;
        array = (T[]) new Comparable[size];
        for (int i = 1; i < old.length; ++i)
            array[i] = old[i];
    }

    public T findMin() {
        if (currentSize < 1)
            return null;
        return array[1];
    }

    public boolean isEmpty() {
        return currentSize == 0;
    }

    public void makeEmpty() {
        currentSize = 0;
    }

    public T deleteMin() {
        if (isEmpty())
            return null;
        T minItem = findMin();
        array[1] = array[currentSize--];

        siftdown(1);
        return minItem;
    }

    /**
     * DeleteMin,删除最小元,即二叉树的根或父节点。
     * 删除该节点元素后,队列最后一个元素必须移动到堆得某个位置,使得堆仍然满足堆序性质。这种向下替换元素的过程叫作下滤。
     * @param hole
     */
    private void siftdown(int hole) {
        T tmp = array[hole];
        int child = 0;
        for (; hole * 2 <= currentSize; hole = child) {
            child = hole * 2;
            if (child + 1 <= currentSize && array[child + 1].compareTo(array[child]) < 0)
                child++;
            if (array[child].compareTo(tmp) < 0)
                array[hole] = array[child];
            else
                break;
        }
        array[hole] = tmp;
    }

    public int size() {
        return currentSize;
    }

    public void buildHeap() {
        for (int i = currentSize / 2; i > 0; --i)
            siftdown(i);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值