数据结构实现之最大优先队列(最大堆)

package xwq.dt;

import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;

import xwq.util.StdIn;
import xwq.util.StdOut;
/**
 ***************************************************************** 
            **************** 最大优先队列API ****************
    1、构造函数
    public MaxPQ();
    public MaxPQ(int capacity);
    public MaxPQ(Comparator cmp);
    public MaxPQ(int capacity,Comparator cmp);
    public MaxPQ(Key[] keys);
    public MaxPQ(Key[] keys,Comparator);

    2、队列操作
    public boolean isEmpty();
    public int size();
    public void push(Key key); 动态扩容*2
    public Key pop();
    public Key peek();
    private void resize(int capacity);

    3、堆辅助操作
    private void adjustDown(int index);
    private void adjustUp(int index);
    private boolean less(Key k1,Key k2);
    private void swap(Key[] keys,int i,int j);

 ******************************************************************
 */
public class MaxPQ<Key extends Comparable<Key>> implements Iterable<Key> {

    private Key[] keys; //关键字集合
    private int N;  //目前关键字容量
    private Comparator comparator; //比较器

    /**
     * 初始化空最大优先队列
     */
    public MaxPQ() {
        this(1);
    }

    /**
     * 初始化容量为capacity的最大优先队列
     * @param capacity 容量
     */
    public MaxPQ(int capacity) {
        this(capacity,null);
    }

    /**
     * 初始化含有Key比较器的空最大优先队列
     * @param cmp 自定义Key比较器
     */
    public MaxPQ(Comparator cmp) {
        this(1,cmp);
    }

    /**
     * 初始化含有Key比较器,容量为capacity的最大优先队列
     * @param capacity 容量
     * @param cmp Key比较器
     */
    public MaxPQ(int capacity,Comparator cmp) {
        keys = (Key[]) new Comparable[capacity+1];
        this.comparator = cmp;
        N = 0;
    }

    /**
     * 初始化数组来自数组的最大优先队列
     * @param keys 数组
     */
    public MaxPQ(Key[] keys) {
        this(keys,null);
    }

    /**
     * 初始化数组来自数组的最大优先队列,含有Key比较器
     * @param keys 数组
     * @param cmp Key比较器
     */
    public MaxPQ(Key[] ks,Comparator cmp) {
        this(ks.length,cmp);
        N = ks.length;
        for(int i = 1;i <= N;i++)
            keys[i] = ks[i-1];
        for(int i=N/2 ;i >= 1;i--)
            adjustDown(i);
    }


    /****************************************************************
                            队列操作
     ****************************************************************/
    /**
     * 判断队列是否为空
     * @return
     */
    public boolean isEmpty() {
        return N == 0;
    }

    /**
     * 获取队列大小
     * @return
     */
    public int size() {
        return N;
    }

    /**
     * 进队,向最大堆插入key
     * @param keys2
     */
    public void push(Key k) {
         //队列容量已满,扩容
        if(N == keys.length-1) 
            resize(N*2);
        keys[++N] = k;
        adjustUp(N);
    }

    /**
     * 出队,删除最大堆的根节点
     * @return
     */
    public Key pop() {
        if(isEmpty()) throw new NoSuchElementException("queue is empty.");
        Key max = keys[1];
        swap(1,N--);
        adjustDown(1);
        keys[N+1]=null;//* 避免指针游走,以帮助尽快垃圾回收
        if(N>0 && N == (keys.length-1)/4 )  resize((keys.length-1)/2);
        return max;
    }

    /**
     * 获取队首元素,最大堆的根节点
     * @return
     */
    public Key peek() {
        if(isEmpty()) throw new NoSuchElementException("queue is empty.");
        return keys[1];
    }

    /**
     * 重定义堆容量大小
     * @param capacity
     */
    private void resize(int capacity) {
        assert capacity>N;
        Key[] news = (Key[]) new Comparable[capacity+1];
        for(int i=1;i<=N;i++)
            news[i] = keys[i];
        keys = news;
    }

    /****************************************************************
                                    堆辅助操作
     ****************************************************************/
    /**
     * 向下调整最大堆
     * @param index 待调整堆起始索引
     */
    private void adjustDown(int index) {
        while(2*index <= N) {
            int l = index*2;
            //选择左右孩子节点中较大的一个
            if(l<N && less(keys[l],keys[l+1]))
                l++;
            //判断index是否已经满足最大堆性质
            if(less(keys[l],keys[index]))
                break;
            //向下调整
            swap(index,l);
            index = l;
        }
    }

    /**
     * 向上调整最大堆
     * @param index 待调整堆起始索引
     */
    private void adjustUp(int index) {
        while(index > 1) {
            int parent = index/2;
            //判断index是否已经满足最大堆性质
            if(less(keys[index],keys[parent])) 
                break;
            //向上调整
            swap(index,parent);
            index = parent;
        }
    }

    /**
     * k1<k2 返回true
     * @param k1
     * @param k2
     * @return
     */
    private boolean less(Key k1,Key k2) {
        if(this.comparator != null)
            return comparator.compare(k1, k2) < 0;
        else
            return ((Comparable)k1).compareTo(k2) < 0;
    }

    /**
     * 交换元素
     * @param i
     * @param j
     */
    private void swap(int i,int j) {
        Key t = keys[i]; keys[i] = keys[j]; keys[j] = t;
    }


    @Override
    public Iterator<Key> iterator() {
        return new HeapIterator();
    }

    /***************************************************************************
        * Iterator.
     ***************************************************************************/

    /**
     * Returns an iterator that iterates over the keys on this priority queue
     * in descending order.
     * The iterator doesn't implement remove() since it's optional.
     *
     * @return an iterator that iterates over the keys in descending order
     */
    private class HeapIterator implements Iterator<Key > {
        //创建一个新的最大优先队列
        private MaxPQ<Key> copy;

        // copy堆中的所有元素
        // 由于原顺序已满足堆性质,所以只需花费线性时间
        public HeapIterator() {
            if(comparator == null) copy = new MaxPQ<Key>(N);
            else    copy = new MaxPQ<Key>(N,comparator);
            for(int i=1;i<=N;i++)
                copy.push(keys[i]);
        }

        @Override
        public boolean hasNext() {
            return copy.size() > 0;
        }

        @Override
        public Key next() {
            if(copy.size() == 0) 
                throw new NoSuchElementException("has not next element.");
            return copy.pop();
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException("not support remove.");
        }

    }

    /**
     * Unit tests the MaxPriorityQueue data type.
     */
    public static void main(String[] args) {
        MaxPQ<String> pq = new MaxPQ<String>();
        while (!StdIn.isEmpty()) {
            String item = StdIn.readString();
            if (!item.equals("-")) pq.push(item);
            else if (!pq.isEmpty()) StdOut.print(pq.pop() + " ");
        }
        //使用迭代器
        for(String s:pq) {
            StdOut.print(s+" ");
        }
        StdOut.println("(" + pq.size() + " left on pq)");
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值