堆实际也是一种二叉数。特点是父节点的数值总是大于等于子节点的数值。堆可以用来实现堆排序,也可以用来实现优先队列。
//堆实现为泛型类,实现类型必须实现Comparable接口
public class Heap <T extends Comparable>{
private List<T> data; //数据放在list里面
public Heap(){
data=new ArrayList<T>();
}
public boolean isEmpty(){
return data.isEmpty();
}
public int Size(){
return data.size();
}
//添加新元素,策略:先添加到list末尾,然后和父节点比,如果比父节点大,则换位,如此递归下去。
public void add(T t){
data.add(t);
int currentIndex=data.size()-1;
while(currentIndex>0){
int p_index=(currentIndex+1)/2-1;
int res=data.get(p_index).compareTo(data.get(currentIndex));
if(res<0){
T temp=data.get(currentIndex);
data.set(currentIndex, data.get(p_index));
data.set(p_index, temp);
currentIndex=p_index;
}else{
break;
}
}
}
/*
删除元素,策略:每次都拿list最后的一个数值覆盖第一个数值,list长度减1,然后比较第一个元素和两个孩子(可能没有或者有一个或者两个孩子),如果
孩子的值更大,则互换值,如此递归
*/
public T remove(){
if(data.size()==0) throw new NullPointerException();
T result=data.get(0);
data.set(0, data.get(data.size()-1));
data.remove(data.size()-1);
if(data.size()==0)
return result;
int curIndex=0;
while(curIndex<data.size()-1){
// System.out.println("currentIndex="+curIndex);
int left_index=curIndex*2+1;
int right_index=curIndex*2+2;
if(data.size()-1<left_index) //如何已经没有孩子
break;
if(left_index==data.size()-1){ //只有左子树
int res=data.get(left_index).compareTo(data.get(curIndex));
if(res>0){
T temp=data.get(left_index);
data.set(left_index, data.get(curIndex));
data.set(curIndex, temp);
break;
}else{
break;
}
}else{
T cur_data=data.get(curIndex);
T left_data=data.get(left_index);
T right_data=data.get(right_index);
if(cur_data.compareTo(left_data)>=0&&cur_data.compareTo(right_data)>=0)
break;
int res=left_data.compareTo(right_data);
if(res>0){
data.set(left_index, cur_data);
data.set(curIndex, left_data);
curIndex=left_index;
continue;
}else{
data.set(right_index, cur_data);
data.set(curIndex, right_data);
curIndex=right_index;
continue;
}
}
}
return result;
}
}