优先队列的特点,root元素就是这个队列的最大值。
二叉堆是一颗完全二叉树
package com.yuanxuzhen.heap;
import java.util.ArrayList;
import java.util.Arrays;
/**
* 堆我们可以理解为完全二叉树
* 完全二叉树是的特点是节点一层一层的摆放
* 我们这里使用数组来实现二叉树。有下面这样的算法leftChild=index * 2 + 1, rightChild = index * 2 + 2, parent = (index -1)/2
* @param <T>
*/
public class MaxHeap<T extends Comparable<T>> {
private ArrayList<T> data;
public MaxHeap() {
this.data = new ArrayList<>();
}
public MaxHeap(int capacity) {
this.data = new ArrayList<>(capacity);
}
public int size(){
return data.size();
}
public boolean isEmpty(){
return data.isEmpty();
}
private int parent(int index){
if(index == 0){
throw new IllegalArgumentException("index 0 doesn't have parent");
}
return (index - 1)/2;
}
private int leftChild(int index){
return index * 2 + 1;
}
private int rightChild(int index){
return index * 2 + 2;
}
/**
* 交换i,j元素
* @param i
* @param j
*/
public void swap(int i, int j){
if(i < 0 || i >= size() || j < 0 || j >= size()){
throw new IllegalArgumentException("index is illegal");
}
T entry = data.get(i);
data.set(i, data.get(j));
data.set(j, entry);
}
/**
* 优先队列的特点,root元素为最大值,我们添加的元素在末尾,然后通过和自己的父元素进行对比,达到最后最大元素移动到root
* @param entry
*/
public void add(T entry){
data.add(entry);
shifup(data.size() - 1);
}
private void shifup(int index){
while(index > 0 && data.get(index).compareTo(data.get(parent(index))) > 0 ){
swap(index, parent(index));
index = parent(index);
}
}
public T findMax(){
if(isEmpty()){
throw new IllegalArgumentException("arraylist is empty");
}
return data.get(0);
}
/**
* 优先队列的特点,root元素为最大值,我们去出最大值后,用最后一个元素先替代root,然后root和自己的子节点中的大值进行对比,如果子节点大,那么就进行交换。达到root的元素进行下沉
* @param
*/
public T extractMax(){
T ret = findMax();
swap(0, data.size() - 1);
data.remove(data.size() - 1);
shifDown(0);
return ret;
}
private void shifDown(int index){
while(leftChild(index) < data.size()){
int leftChildIndex = leftChild(index);
int rightChildIndex = rightChild(index);
int swapIndex = 0;
//右孩子节点大于左孩子节点
if(rightChildIndex < data.size() && data.get(rightChildIndex).compareTo(data.get(leftChildIndex)) > 0 ){
swapIndex = rightChildIndex;
}else{
swapIndex = leftChildIndex;
}
if(data.get(index).compareTo(data.get(swapIndex)) < 0){
swap(index, swapIndex);
index = swapIndex;
}else{
break;
}
}
}
}