堆(Heap)是一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。
在二叉堆中,从任意结点向上,我们都能得到一列非递减的元素;从任意结点向下,我们都能得到一列非递增的元素。
在堆中有两个特殊的操作:
- 上浮(swim):
如果堆的有序状态因为某个结点变得比它父结点更大而打破,那么我们就需要进行上浮操作。
- 下沉(sink):
如果堆的有序状态因为某个结点变得比它的两个子节点或者其中之一更小而打破,那么我们就需要进行下沉操作。
插入元素:
将新元素添加到元素末尾,增加堆的大小并让这个新的元素上浮到合适的位置。
删除最大元素:
将数组最后一个元素和堆顶元素交换,减小数组大小并让这个元素下沉到合适的位置
具体实现代码如下:
/**
* 大顶堆
* @param <Item> 键
*/
public class MaxPQ <Item extends Comparable<Item>> {
private int N;
private Item[] pq; //利用数组表示堆
public MaxPQ() {
N = 0;
pq = (Item[]) new Comparable[2];
}
/**
* 调整数组大小
* @param size 调整后的数组大小
*/
private void resize(int size) {
Comparable[] a = new Comparable[size];
for (int i = 1; i <= N; i++) {
a[i] = pq[i];
}
pq = (Item[]) a;
}
/**
*
* @param i 索引i
* @param j 索引j
* @return 索引为i的元素是否小于索引为j的元素
*/
private boolean less(int i, int j) {
return pq[i].compareTo(pq[j]) < 0;
}
/**
* 交换元素
* @param i 索引i
* @param j 索引j
*/
private void exch(int i, int j) {
Item t = pq[i];
pq[i] = pq[j];
pq[j] = t;
}
/**
* 上浮:如果某个结点比它的父结点要大,采取该操作
* @param k 结点的位置
*/
private void swim(int k) {
while (k > 1) {
if (less(k/2, k)) {
exch(k/2, k);
k = k/2;
}
}
}
/**
* 下沉
* @param k 结点的位置
*/
private void sink(int k) {
while (2*k <= N) {
int j = 2*k;
if (j < N && less(j, j+1)) {
j++;
}
if (less(j, k)) {
break;
}
exch(k, j);
k = j;
}
}
/**
*
* @return 堆是否为空
*/
public boolean isEmpty() {
return N == 0;
}
/**
*
* @return 堆中元素个数
*/
public int size() {
return N;
}
/**
* 插入元素
* @param Item 要插入的元素
*/
public void insert(Item item) {
if (N == pq.length-1) {
resize(2*pq.length);
}
pq[++N] = item;
swim(N);
}
/**
* 删除并返回最大元素
* @return 最大元素
*/
public Item delMax() {
if (N == pq.length/4) {
resize(pq.length/2);
}
Item max = pq[1];
exch(1, N--);
pq[N+1] = null;
sink(1);
return max;
}
/**
*
* @return 堆中最大值
*/
public Item max() {
return pq[1];
}
/**
*
* @return 堆中最小值
*/
public Item min() {
int min = N;
for (int i = N; i >= 1; i--) {
if (less(i, min)) {
min = i;
}
}
return pq[min];
}
/**
*
* @param item 所要查找的元素
* @return 该元素是否存在
*/
public boolean contains(Item item) {
for (int i = 1; i <= N; i++) {
if (pq[i] == item) {
return true;
}
}
return false;
}
@Override
public String toString() {
StringBuilder s = new StringBuilder();
for (int i = 1; i <= N; i++) {
s.append(pq[i] + " ");
}
return s.toString();
}
public static void main(String[] args) {
MaxPQ<Integer> maxPQ = new MaxPQ<>();
for (int i = 1; i <= 24; i++) {
maxPQ.insert(i);
}
System.out.println(maxPQ.toString());
System.out.println(maxPQ.size());
System.out.println(maxPQ.max());
System.out.println(maxPQ.min());
System.out.println(maxPQ.contains(0));
maxPQ.delMax();
System.out.println(maxPQ.toString());
}
}