优先队列

原创 2015年07月07日 21:33:46

完全二叉树

同时满足已下条件的二叉树是完全二叉树:
* 除最后一层外,每层的结点都有左右两个结点
* 最后一层的结点从左向右,紧密排列,中间没有空隙

例如下图就是一颗完全二叉树
一颗完全二叉树

所有父结点都大(小)于子结点的完全二叉树叫做最大(小)堆。上图就是一个最大堆。

堆能做什么

  • 移除最值
  • 吸纳新值

对应接口:
public void add(E item);
public E remove();
public E peek();
public int size();
public boolean isEmpty();

接口代码

public interface IPQ<E> {
    /**
     * 把<code>item<code>加入到队列中
     * 
     * @param item
     *            要添加的元素
     */
    public void add(E item);

    /**
     * 移除最值
     * 
     * @return
     */
    public E remove();

    /**
     * 查询最值
     * 
     * @return 最值
     */
    public E peek();

    /**
     * 返回队列中元素的个数
     * 
     * @return 队列大小
     */
    public int size();

    /**
     * 查询队列是否为空
     * 
     * @return <code>true</code> 如果队列中元素个数为0;否则,返回<code>false</code>。
     */
    public boolean isEmpty();
}

实现代码

package com.gmail.dailyefforts.ds;

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;

import com.gmail.dailyefforts.princeton.stdlib.In;

public class PQ<E extends Comparable<? super E>> implements IPQ<E> {

    private transient E[] a;
    private transient int size;
    private final Order order;

    public enum Order {
        ASC, DESC
    }

    public PQ(int capacity, Order order) {
        this.a = (E[]) new Comparable[capacity + 1];
        this.size = 0;
        this.order = order;
    }

    @Override
    public void add(E item) {
        if (size >= a.length - 1) {
            resize(size << 1);
        }
        a[++size] = item;
        siftUp(size);
    }

    private void siftUp(int i) {
        while (i > 1) {
            final int parentIdx = i >>> 1;
            if (greater(parentIdx, i)) {
                swap(parentIdx, i);
            }
            i = parentIdx;
        }
    }

    private boolean greater(int i, int j) {
        // final Comparable<? super E> key = (Comparable<? super E>) a[i];
        final boolean greater = a[i].compareTo(a[j]) > 0;
        if (Order.DESC.equals(this.order)) {
            return !greater;
        }
        return greater;
    }

    private void swap(int i, int j) {
        final E tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }

    private void resize(int capacity) {
        final E[] tmp = (E[]) new Comparable[capacity];
        for (int i = 1; i <= size; i++) {
            tmp[i] = a[i];
        }
        a = tmp;
    }

    @Override
    public E remove() {
        if (isEmpty()) {
            return null;
        }
        E max = a[1];
        int N = size;
        // move the last item to a[1]
        a[1] = a[N];
        size--;
        siftDown(1);
        a[N] = null;
        return max;
    }

    @Override
    public E peek() {
        return a[0];
    }

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

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

    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder();
        builder.append('[');
        for (int i = 1; i <= size; i++) {
            builder.append(a[i]);
            if (i < size) {
                builder.append(", ");
            }
        }
        builder.append(']');
        return builder.toString();
    }

    private void siftDown(int i) {
        while ((i << 1) <= size) {
            // has child
            final int left = i << 1;
            int k = left;
            if (left < size && greater(left, left + 1)) {
                k++;
            }
            if (greater(k, i)) {
                break;
            }
            swap(i, k);
            i = k;
        }
    }

    public static void main(String[] args) {
        final int N = 100 * 100;
        PQ<Integer> pq = new PQ<>(N, Order.DESC);
        MyComparator comparator = new MyComparator();
        Queue<Integer> q = new PriorityQueue<>(N, comparator);
        Random random = new Random();
        for (int i = 0; i < N; i++) {
            int val = random.nextInt(N);
            pq.add(val);
            q.add(val);
        }
        assert (pq.size() == q.size());
        while (!pq.isEmpty()) {
            final int a = pq.remove();
            final int b = q.remove();
            System.out.println(a);
            assert (a == b);
        }
        System.out.println(pq.size());
    }

}

class MyComparator<E extends Comparable<E>> implements Comparator<E> {
    @Override
    public int compare(E o1, E o2) {
        return o2.compareTo(o1);
    }

}
版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)