二叉堆
性质:
是完全二叉树(缺失的节点在整棵树的右下侧,换言之,即把元素顺序排列成树的形状)
堆中某个节点的值总是不大于其父节点的值(最大堆)
注意:节点大小和节点所处层次间没有必然联系
public class MaxHeap<E extends Comparable<E>> {
//最大堆:满足1、完全二叉树 2、父节点大于其孩子节点
private Array<E> data;
public MaxHeap(){
data = new Array<>();
}
public MaxHeap(int capacity){
data = new Array<>(capacity);
}
public MaxHeap(E[] arr){
data = new Array<>(arr);
for (int i = parent(arr.length - 1); i >= 0 ; i--) {
siftDown(i);
}
}
public boolean isEmpty(){
return data.isEmpty();
}
public int size(){
return data.getSize();
}
private int parent(int index){
if(index == 0){
throw new IllegalArgumentException("index does not have parent");
}
return (index-1)/2;
}
private int leftChild(int index){
return index * 2 + 1;
}
private int rightChild(int index){
return index * 2 + 2;
}
public void add(E e){
data.addLast(e);
siftUp(data.getSize()-1);
}
private void siftUp(int k){
while (k>0 && data.get(parent(k)).compareTo(data.get(k))<0){
data.swap(k,parent(k));
k = parent(k);
}
}
//找出堆中最大元素
public E findMax(E e){
if(data.getSize() == 0){
throw new IllegalArgumentException("Can not find Max");
}
return data.get(0);
}
//取出堆中最大元素
public E extractMax(E e){
E ret = findMax(e);
data.swap(0,data.getSize()-1);
data.removeLast();
siftDown(0);
return ret;
}
private void siftDown(int k){
while (leftChild(k) < data.getSize()){
int j = leftChild(k);
if(j+1 < data.getSize() && data.get(j + 1).compareTo(data.get(j)) > 0){
j = rightChild(k);
}
if(data.get(k).compareTo(data.get(j)) >= 0){
break;
}
data.swap(k, j);
k = j;
}
}
//取出堆中最大元素,替换成e
public E replace(E e){
E ret = findMax(e);
data.set(0 ,e);
siftDown(0);
return ret;
}
}