前段时间要用堆,java里面的优先级队列PriorityQueue没有这么一个功能:堆里元素更改后没法确定最值的真假,因为没有再次更新堆。于是自己动手写了个堆,加了refresh()方法把元素再进行一下上浮下沉操作,要最值的时候refresh一下就再也不担心堆里元素被更改了:
/**
* Version_new
* @author Tcorpion
* @time 2017-03-28
*/
public class BinaryHeap<AnyType extends Comparable<? super AnyType>> {
private AnyType[] array;
private int currentSize;
private final static int DEFAULT_SIZE=11;
private final static boolean MaxHeap=false;//MinHeap is false true
public BinaryHeap(){
this(DEFAULT_SIZE);
}
public BinaryHeap(int capacity){
currentSize=0;
array=(AnyType[])new Comparable[capacity];
}
public BinaryHeap(AnyType[] items){
currentSize=items.length;
array=(AnyType[])new Comparable[currentSize+1];
int i=0;
for(AnyType item:items)
array[++i]=item;
for(int j=currentSize/2;j>0;j--)
filterUpDownForMinHeap(j);
}
public void refresh(){
if(currentSize>0){
for(int j=currentSize/2;j>0;j--){
filterUpDownForMinHeap(j);
}
}
}
/**
*@param startIndex ,endIndex: [startIndex, endIndex)
*/
public BinaryHeap(AnyType[] items,int startIndex,int endIndex){
currentSize=items.length;
array=(AnyType[])new Comparable[endIndex-startIndex];
for(int i=startIndex;i<endIndex;i++)
{ array[i]=items[i]; }
for(int j=currentSize/2;j>0;j--)
{ filterUpDownForMinHeap(j); }
}
public void makeEmpty(){
currentSize=0;
array=(AnyType[])new Object[DEFAULT_SIZE];
}
public int size(){
return this.currentSize;
}
public void add(AnyType x){
if(currentSize==(array.length-1)){
enlarge(array.length*2+1);
}
int loc=++currentSize;
int child=loc/2;
array[0]=x;
if(MaxHeap){
while(x.compareTo(array[child])>0){//used as maxHeap
array[loc]=array[child];
loc=child;
child/=2;
}
}else{
while(x.compareTo(array[child])<0){//used as minHeap
array[loc]=array[child];
loc=child;
child/=2;
}
}
array[loc]=x;
}
/**
*make array[1]=array[currentSize--], do the filter up-down to get the new top.
*@param return the original top value.
*/
public AnyType deleteTop(){
if(isEmpty())
return null;
AnyType top=array[1];
array[1]=array[currentSize--];
filterUpDownForMinHeap(1);
return top;
}
public AnyType top(){
return isEmpty()?null:array[1];
}
public boolean isEmpty(){
return 0>=currentSize;
}
private void enlarge(int size){
AnyType[] oldArray=array;
array=(AnyType[])new Comparable[array.length*2+1];
int i=0;
for(AnyType item:oldArray){
array[i++]=item;//!warning: although the first location-array[0] is unused, it still need to be copied to ensuring right location.
}
}
/**
*do the filter up-down between top-down layers in a subtree whose root is at location.
*/
private void filterUpDownForMinHeap(int location){
if(location<1)
return;
AnyType temp=array[location];
for(int child=2*location;child<=currentSize;child=2*child){
if( (child!=currentSize) && //if two children exist,select a min-child
(array[child].compareTo(array[child+1])>0) ){
child++;
}
if(temp.compareTo(array[child])>0){
array[location]=array[child];//min-child move up
location=child;
}else{
break;
}
}
array[location]=temp;
}
private void filterUpDownForMaxHeap(int location){
if(location<1)
return;
AnyType temp=array[location];
for(int child=2*location;child<=currentSize;child=2*child){
if( (child!=currentSize) &&//if two children exist,select a max-child
(array[child].compareTo(array[child+1])<0) ){
child++;
}
if(temp.compareTo(array[child])<0){
array[location]=array[child];//max-child move up
location=child;
}else{
break;
}
}
array[location]=temp;
}
/**
*left param is bigger than right param.
*/
private boolean leftIsBigger(AnyType up, AnyType down){
return up.compareTo(down)>0;
}
}