package com.algs;
import java.util.Iterator;
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
/*
* 优先队列基于二叉堆实现,数据存储在数组pq[1 ... N]中,其中pq[0]不使用
*/
public class MaxPQ> implements Iterable
{
private static final int DEFAULT_LENGTH = 1 << 4;
private Key[] pq;
private int N = 0;
public MaxPQ()
{
this(DEFAULT_LENGTH);
}
@SuppressWarnings("unchecked")
public MaxPQ(int capacity)
{
pq = (Key[]) new Comparable[capacity + 1];
N = 0;
}
@SuppressWarnings("unchecked")
public MaxPQ(Key[] keys)
{
int N = keys.length;
pq = (Key[]) new Comparable[N + 1];
for(int i = 0; i < N; i++) pq[i + 1] = keys[i];
for(int k = N/2; k > 1; k--) swin(k); // 堆有序
assert isMaxPQ();
}
public boolean isEmpty()
{
return N == 0;
}
public int size()
{
return N;
}
public void insert(Key v)
{
if(N == pq.length - 1) resize(N + N / 2);
pq[++N] = v;
swin(N);
assert isMaxPQ();
}
public Key delMax()
{
Key max = pq[1];
exch(1, N--);
pq[N + 1] = null; // 防止对象游离
if(N > 0 && N == pq.length / 4) resize(pq.length / 2);
sink(1);
assert isMaxPQ();
return max;
}
private void swin(int k)
{
while (k > 1 && less(k / 2, k))
{
exch(k / 2, k);
k = k / 2;
}
}
private void sink(int k)
{
while (2 * k <= N)
{
int j = 2 * k;
if (j < N && less(j, j + 1)) j++; // 找到两个子节点中较大的
if (!less(k, j)) break; // 若父节点大于较大的子节点,则两者交换
exch(k, j);
k = j;
}
}
private void resize(int capacity)
{
assert capacity > N;
@SuppressWarnings("unchecked")
Key[] temp = (Key[]) new Comparable[capacity + 1];
System.arraycopy(pq, 0, temp, 0, N);
pq = temp;
}
private boolean isMaxPQ()
{
return isMaxPQ(1);
}
private boolean isMaxPQ(int k)
{
if(k > N) return true;
int left = 2 * k, right = 2 * k + 1;
if(left < N && less(k, left)) return false;
if(left < N && less(k, right)) return false;
return isMaxPQ(left) && isMaxPQ(right);
}
private boolean less(int i, int j)
{
return pq[i].compareTo(pq[j]) < 0;
}
private void exch(int i, int j)
{
Key t = pq[i];
pq[i] = pq[j];
pq[j] = t;
}
@Override
public Iterator iterator()
{
return new HeapIterator();
}
public class HeapIterator implements Iterator
{
private MaxPQ clone;
public HeapIterator()
{
clone = new MaxPQ<>(size());
for(int i = 1; i < size(); i++) clone.insert(pq[i]);
}
@Override
public boolean hasNext()
{
return !clone.isEmpty();
}
@Override
public Key next()
{
if(!hasNext()) throw new UnsupportedOperationException(); ;
return clone.delMax();
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
public static void main(String[] args)
{
MaxPQ pq = new MaxPQ();
while (!StdIn.isEmpty()) {
String item = StdIn.readString();
if (!item.equals("-")) pq.insert(item);
else if (!pq.isEmpty()) StdOut.print(pq.delMax() + " ");
}
StdOut.println("(" + pq.size() + " left on pq)");
}
}