最大堆 和 优先队列

最大堆

MaxHeap.java

import java.util.Random;  // 后面测试用

public class MaxHeap<E extends Comparable<E>> {
    private Array<E> data;

    public MaxHeap(int capacity){
        data = new Array<>(capacity);
    }

    public MaxHeap(){
        data = new Array<>();
    }

    /**
     * 将数组转化为堆
     * 一开始就把数组当成未规范的堆,
     * 然后从第一个非叶子节点开始做sift down, 一直到根结点
     * @param arr
     */
    public MaxHeap(E[] arr){
        data = new Array<>(arr);
        for(int i=parent(arr.length-1); i>=0; i--){
            siftDown(i);
        }
    }

    public int size(){
        return data.getSize();
    }

    public boolean isEmpty(){
        return data.isEmpty();
    }

    /**
     *
     * @param index
     * @return 父节点的索引
     */
    private int parent(int index){
        if(index == 0)
            throw new IllegalArgumentException("No parent");
        return (index-1)/2;
    }

    /**
     *
     * @param index
     * @return 左孩子的索引
     */
    private int leftChild(int index){
        return index * 2 + 1;
    }

    /**
     *
     * @param index
     * @return 右孩子的索引
     */
    private int rightChild(int index){
        return index * 2 + 2;
    }

    /**
     * 添加元素e
     * 思路: 把元素添加到最后一个, 然后向上浮动形成最大堆
     * @param e
     */
    public void add(E e){
        data.addLast(e);
        siftUp(data.getSize() - 1);
    }

    /**
     * 向上浮动
     * @param k
     */
    private void siftUp(int k) {
        // 一直循环, 如果k有父节点, 且比父节点大
        while(k > 0 && data.get(parent(k)).compareTo(data.get(k)) < 0){
            data.swap(k, parent(k));
            k = parent(k);
        }
    }

    /**
     * 看最大的元素值
     * @return
     */
    public E findMax(){
        if(data.getSize() == 0)
            throw new IllegalArgumentException();
        return data.get(0);
    }

    /**
     * 取出堆中最大的元素
     * 思路: 先保存最大元素, 然后用最后一个元素覆盖掉最大的元素, 
     * 删除最后一个元素, 然后向下浮动形成最大堆
     * @return
     */
    public E extractMax(){
        E ret = findMax();
        data.swap(0, data.getSize()-1);
        data.removeLast();
        siftDown(0);

        return ret;
    }

    /**
     * 向下浮动
     * @param k
     */
    private void siftDown(int k){
        // 一直循环如果 k 有孩子
        while(leftChild(k) < data.getSize()){
            // 获得最大的孩子的索引
            int maxChildIndex = leftChild(k);
            if(maxChildIndex+1 < data.getSize() &&
                    data.get(maxChildIndex).compareTo(data.get(maxChildIndex+1)) < 0){
                maxChildIndex = rightChild(k);
            }

            // 如果根节点大于等于孩子
            if(data.get(k).compareTo(data.get(maxChildIndex)) >= 0) {
                break;
            }
            // 如果孩子比较大
            data.swap(k, maxChildIndex);
            k = maxChildIndex;
        }
    }

    /**
     * O(log n) 取出堆中最大的元素并替换成e
     * @param e
     * @return
     */
    public E replace(E e){
        E ret = findMax();
        data.set(0, e);
        siftDown(0);

        return ret;
    }

    public static void main(String[] args) {
        int n = 1000000;

        MaxHeap<Integer> maxHeap = new MaxHeap<>();
        Random random = new Random();
        for(int i=0; i<n; i++){
            maxHeap.add(random.nextInt(Integer.MAX_VALUE));
        }

        int[] arr = new int[n];
        for(int i=0; i<n; i++){
            arr[i] = maxHeap.extractMax();
        }

        for(int i=1; i<n; i++){
            if(arr[i-1] < arr[i]){
                throw new IllegalArgumentException();
            }
        }
        System.out.println("Good!");
    }
}

优先队列

Queue.java

public interface Queue<E> {
    int getSize();
    boolean isEmpty();
    void enqueue(E e);
    E dequeue();
    E getFront();
}

PriorityQueue.java

public class PriorityQueue<E extends Comparable<E>> implements Queue<E> {

    private MaxHeap<E> maxHeap;

    public PriorityQueue(){
        maxHeap = new MaxHeap<>();
    }

    @Override
    public int getSize() {
        return maxHeap.size();
    }

    @Override
    public boolean isEmpty() {
        return maxHeap.isEmpty();
    }

    @Override
    public void enqueue(E e) {
        maxHeap.add(e);
    }

    @Override
    public E dequeue() {
        return maxHeap.extractMax();
    }

    @Override
    public E getFront() {
        return maxHeap.findMax();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值