二叉堆是一種特殊的堆案站,二叉堆是完全二元樹(二叉樹)或者是近似完全二元樹(二叉樹)涎嚼。二叉堆有兩種:最大堆和最小堆碴巾。最大堆:父結(jié)點的鍵值總是大于或等于任何一個子節(jié)點的鍵值特愿;最小堆:父結(jié)點的鍵值總是小于或等于任何一個子節(jié)點的鍵值。
Snipaste_2019-03-24_19-23-36.png
堆的結(jié)構(gòu)
package heap;
public class MaxHeap<E extends Comparable<E>> {
private Array<E> data;
public MaxHeap(int capacity){
data = new Array<>(capacity);
}
public MaxHeap(){
data = new Array<>();
}
// 返回堆中的元素個數(shù)
public int size(){
return data.getSize();
}
// 返回一個布爾值, 表示堆中是否為空
public boolean isEmpty(){
return data.isEmpty();
}
// 返回完全二叉樹的數(shù)組表示中(從0開始)光酣,一個索引所表示的元素的父親節(jié)點的索引
private int parent(int index){
if(index == 0)
throw new IllegalArgumentException("index-0 doesn't have parent.");
return (index-1)/2;
}
// 返回完全二叉樹的數(shù)組表示中疏遏,一個索引所表示的元素的左孩子節(jié)點的索引
private int leftChild(int index){
return index * 2 +1;
}
// 返回完全二叉樹的數(shù)組表示中,一個索引所表示的元素的右孩子節(jié)點的索引
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) {
//判斷添加的元素跟父親節(jié)點的大小比較救军,大于父親節(jié)點便和父親節(jié)點交換
while (k > 0 && data.get(parent(k)).compareTo(data.get(k)) < 0) {
data.swap(k, parent(k));
k = parent(k);
}
}
取出堆中的最大元素
// 看堆中的最大元素
public E findMax() {
if (data.getSize() == 0)
throw new IllegalArgumentException("Can not findMax when heap is empty.");
return data.get(0);
}
// 取出堆中最大元素
public E extractMax() {
E ret = findMax();
//第一個和最后一個元素交換位置
data.swap(0, data.getSize() - 1);
//刪除第一個元素
data.removeLast();
return ret;
}
//把交換后的第一個元素下沉(比較左右節(jié)點)
private void siftDown(int k) {
while(leftChild(k) < data.getSize()){
//尋找出左右孩子出的最大值跟k值交換
int j = leftChild(k); // 在此輪循環(huán)中,data[k]和data[j]交換位置
if( j + 1 < data.getSize() &&
data.get(j + 1).compareTo(data.get(j)) > 0 )
j++;
// data[j] 是 leftChild 和 rightChild 中的最大值
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();
data.set(0, e);
siftDown(0);
return ret;
}