堆是一棵完全二叉树,所谓的完全二叉树的意思是所有的叶子节点都处于某一层,或者处于两个相邻的层并且最底层的叶子节点处于最左侧。但是堆具有的一个特殊性质是:每个节点上的值都小于(大于)或等于那个节点上的值。
下面的代码是以小于为实现。堆可以做为一个优先队列的实现,可以成为一种排序方式。
public class Heap<E extends Comparable<E>> {
private E[] data=(E[])new Object[10]; //用数组实现
int top=-1; //用来指向元素存到数组哪个位置了
public Heap(){
}
public Heap(Collection<E> coll){
for(E e:coll){
add(e);
}
}
public Heap(E[] coll){
for(E e:coll){
add(e);
}
}
//判断是否为空树
public boolean isEmpty(){
return top==-1;
}
//返回index的左子树位置
private int leftChildIndex(int index){
return 2*index+1;
}
//返回index的右子树位置
private int rightChildIndex(int index){
return 2*index+2;
}
//返回index的父亲位置
private int parentChildIndex(int index){
return (index-1)/2;
}
//实现加入操作
public void add(E target){
//判断是否超出数组大小,如果超出重新创建一个并复制原来的数组到新数组中
if(top==data.length-1){
E[] tempdata=(E[])new Object[data.length+5];
int j=0;
for(int i=0;i<data.length;i++){
tempdata[j++]=data[i];
}
data=tempdata;
}
//以下操作是真正加入到堆中
top=top+1; //指针下移
data[top]=target; //加入到末尾
//加入后可能出现不是堆了,进行堆化操作
int index=top;
int parent=parentChildIndex(index);
while(parent>=0){
//如果父亲比孩子节点大,交换位置
if(data[parent].compareTo(data[index])>0){
swap(parent,index);
index=parent;
parent=parentChildIndex(index);
}else{
return ;
}
}
}
//删除操作
public E remove(){
E temp=data[0]; //删除第一个
data[0]=data[top];//把最尾部的元素来取代这个位置
top--;
//以下是进行堆化操作
int index=0;
int leftchild=leftChildIndex(index);
int rightchild=rightChildIndex(index);
//只要孩子节点没超出执行以下操作
//如果当前节点比孩子节点大(如果都比两个大那么跟其中小)跟其交换
while(leftchild<=top||rightchild<=top){
if((data[index].compareTo(data[leftchild])>0)&&(data[leftchild].compareTo(data[rightchild])<0)){
swap(index,leftchild);
index=leftchild;
leftchild=leftChildIndex(index);
rightchild=rightChildIndex(index);
}else if(data[index].compareTo(data[rightchild])>0){
swap(index,rightchild);
index=rightchild;
leftchild=leftChildIndex(index);
rightchild=rightChildIndex(index);
}else{
break;
}
}
return temp;
}
//交换位置i,j位置元素
private void swap(int i,int j){
E temp=null;
temp=data[i];
data[i]=data[j];
data[j]=temp;
}
}
下面的代码是以小于为实现。堆可以做为一个优先队列的实现,可以成为一种排序方式。
public class Heap<E extends Comparable<E>> {
private E[] data=(E[])new Object[10]; //用数组实现
int top=-1; //用来指向元素存到数组哪个位置了
public Heap(){
}
public Heap(Collection<E> coll){
for(E e:coll){
add(e);
}
}
public Heap(E[] coll){
for(E e:coll){
add(e);
}
}
//判断是否为空树
public boolean isEmpty(){
return top==-1;
}
//返回index的左子树位置
private int leftChildIndex(int index){
return 2*index+1;
}
//返回index的右子树位置
private int rightChildIndex(int index){
return 2*index+2;
}
//返回index的父亲位置
private int parentChildIndex(int index){
return (index-1)/2;
}
//实现加入操作
public void add(E target){
//判断是否超出数组大小,如果超出重新创建一个并复制原来的数组到新数组中
if(top==data.length-1){
E[] tempdata=(E[])new Object[data.length+5];
int j=0;
for(int i=0;i<data.length;i++){
tempdata[j++]=data[i];
}
data=tempdata;
}
//以下操作是真正加入到堆中
top=top+1; //指针下移
data[top]=target; //加入到末尾
//加入后可能出现不是堆了,进行堆化操作
int index=top;
int parent=parentChildIndex(index);
while(parent>=0){
//如果父亲比孩子节点大,交换位置
if(data[parent].compareTo(data[index])>0){
swap(parent,index);
index=parent;
parent=parentChildIndex(index);
}else{
return ;
}
}
}
//删除操作
public E remove(){
E temp=data[0]; //删除第一个
data[0]=data[top];//把最尾部的元素来取代这个位置
top--;
//以下是进行堆化操作
int index=0;
int leftchild=leftChildIndex(index);
int rightchild=rightChildIndex(index);
//只要孩子节点没超出执行以下操作
//如果当前节点比孩子节点大(如果都比两个大那么跟其中小)跟其交换
while(leftchild<=top||rightchild<=top){
if((data[index].compareTo(data[leftchild])>0)&&(data[leftchild].compareTo(data[rightchild])<0)){
swap(index,leftchild);
index=leftchild;
leftchild=leftChildIndex(index);
rightchild=rightChildIndex(index);
}else if(data[index].compareTo(data[rightchild])>0){
swap(index,rightchild);
index=rightchild;
leftchild=leftChildIndex(index);
rightchild=rightChildIndex(index);
}else{
break;
}
}
return temp;
}
//交换位置i,j位置元素
private void swap(int i,int j){
E temp=null;
temp=data[i];
data[i]=data[j];
data[j]=temp;
}
}