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

来源:互联网 发布:淘宝没有延长收货时间 编辑:程序博客网 时间:2024/04/29 14:20

需求

自己实现一个简单的优先队列(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

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