您的位置:首页 > 其它

2015-11-30 15:13 106 查看
大家好,利用数组实现最小堆和最大堆,请大家多多指教

/**
* 实现堆:利用完全二叉树实现,利用数组
*   特点:
*       最小堆
*       最大堆
*  插入:
*  删除:
*  查找:
* @author admin
*
*/
public class Head {

private static final int DEFAULT_CAPACITY = 50;

private int size ;

private int MaxSize;

private int [] head;

public Head(){
MaxSize = DEFAULT_CAPACITY;
head = new int [DEFAULT_CAPACITY+1];
//表示为哨兵
head[0] = Integer.MAX_VALUE;
}

public Head(int MaxSize){
if(MaxSize <= 0){
throw new IllegalArgumentException("maxsize is illgeal");
}
this.MaxSize = MaxSize;
head = new int [MaxSize+1];
head[0] = Integer.MAX_VALUE;
}

/**
* 判断队列是否满
* @return
*/
public boolean isFull(){
return size == MaxSize;
}

/**
* 判断堆是否为空
* @return
*/
public boolean isEmpty(){
return size == 0;
}

/**
* 插入元素
* @param element
*/
public void insert(int element){
//判断堆是否已经满
if(isFull()){
System.out.println("堆已经满了");
return ;
}
int index = ++this.size;  //插入的位置
//插入,依次判断节点和父节点元素大小关系,调整顺序
//index / 2 表示父节点的位置
for(;head[index/2] > element;index /=2){
head[index] = head[index / 2];
}
head[index] = element;  //最后插入位置
}

public void dispHead(){
StringBuilder builder = new StringBuilder("[");
for(int i = 1; i <= size;i++){
builder.append(head[i]);
if(i != size){
builder.append(",");
}
}
builder.append("]");
System.out.println(builder.toString());
}
/**
* 删除最大值
* @return
*/
public int deleteMax(){
if(isEmpty()){
System.out.println("堆已经为空,不能删除");
throw new IllegalArgumentException("堆已经为空,不能删除");
}
int tmp = head[size--];  //最后一个元素
int maxTmp = head[1];    //第一个元素
int parent = 1;
int child = 1;
for(;parent *2 <= size;parent = child){
child = parent *2;
if(child <= size && head[child] < head[child+1]){
child++;  //找到左右孩子最大值的节点位置
}
if(head[child] <= tmp){
break;
}else{
head[parent] = head[child];
}
}
head[parent] = tmp;
return maxTmp;
}

/**
* 删除最小值
* @return
*/
public int deleteMin(){
if(isEmpty()){
System.out.println("堆已经为空,不能删除");
throw new IllegalArgumentException("堆已经为空,不能删除");
}
int tmp = head[size--];  //最后一个元素
int minTmp = head[1];    //第一个元素
int parent = 1;
int child = 1;
for(;parent *2 <= size;parent = child){
child = parent *2;
if(child <= size && head[child] > head[child+1]){
child++;  //找到左右孩子最小值的节点位置
}
if(head[child] >= tmp){
break;
}else{
head[parent] = head[child];
}
}
head[parent] = tmp;
return minTmp;
}

/**
利用数组来创建堆,效率比直接插入要高
*/
public void createByArray(int [] arr){
//1.判断数组的容量
if(arr.length > MaxSize){
head = new int [arr.length+1];
}
//2.进行复制
System.arraycopy(arr, 0, head, 1, arr.length);
size = arr.length;  //指向末尾元素
//3.进行排序,分堆处理
int parent = size /2;
int child = size;
for(;parent >= 1;parent -= 1){
child = 2*parent;
if(child <= size && child +1 <= size && head[child] > head[child+1]){
child++;  //找到最大的孩子节点
}
if(head[parent] < head[child]){
continue;
}
else{
int tmp = head[parent];
head[parent] = head[child];
//再次进行排列
int parent2 = child;
int child2 = 0;
for(;parent2*2 <= size;parent2= child2){
child2 = parent2*2;
if(child2 <= size && child2 +1 <= size && head[child2] > head[child2+1]){
child2++;
}
if(head[child2] > tmp){
break;
}else{
head[parent2] = head[child2];
}
}
head[parent2] = tmp;
}

}

}
/**
* 返回节点的数目
* @return
*/
public int getSize(){
return this.size;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: