定义
二叉堆(简称堆,当然还有别的堆),是一种具有特定规则的树形结构,二叉堆规定:父节点的值必定大于(小于)其孩子节点,因此可以称其为最大堆(最小堆),堆是维护极值的非常快速的一种数据结构。
实现思路
堆一般都是数组实现的(不明白用数组怎么写树的,请自己脑补,很容易想的)。
拿最小堆来说,堆的根节点一定是最小的,堆只可以从根节点取值,所以堆的调整是最重要的工作。
比如对数列: 10 1 11 9 6 建最小堆
开始,堆是空的,把10放进去(下标是1),再把1放进去(下标是2),1就是10的左孩子,但是由于1比10小,需要调正,把1和10对调。这样根节点变成了1,10是1的左孩子。接着把11放进去(下标是3),那11就是1的右孩子,11比1大,因此无需调整,接着把9放进去(下标是4),那9是10的左孩子,9比10小,调整,9比1大,无需调整,则树就变成了这样:
、、、、、好吧,图片有点大了。图片大人也大=。=
接着把6放进去(下标是5),那6是9的右孩子,6比9小,调整,1比6小,无需调整,树又变了个样:
以此类推,每次插入都是在数组最后,插入一次就要调整一次,递归去和父节点比,符合规则就调整。
取数同样需要调整,上面的例子,取出根节点1,把末尾的数(9)放到根节点,然后向下作出相应的调整。
代码(JAVA实现)
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
/**
* Created by Lee Y on 2016/4/2.
* 最小堆JAVA实现
*/
public class CompleteTree {
/*
我这里用的是vector 已经过时了,建议使用arraylist
*/
private Vector<Integer> list = new Vector<>();
private static final int start = 1;
private int end = start;
public CompleteTree(){
addLength();
}
/*
插入
*/
public void insert(Integer item){
if(end == list.size()){
addLength();
}
list.set(end, item);
insert_adapt();
end++;
}
/*
增加vector的长度,并初始化,vector虽然是动态的,但set方法不是动态的(add方法可以动态增加长度)
对于某些情况叶子节点可能会取空,所以应该手动增加长度。
*/
private void addLength(){
for (int i=0;i<100;i++){
list.add(0xfffffff);
}
}
/*
插入调整
*/
private void insert_adapt(){
int pos = end;
Integer a,b;
while(pos != 1){
a = list.get(pos);
b = list.get(pos>>1);
if(a.intValue() < b.intValue()){
list.set(pos>>1, a);
list.set(pos, b);
}
pos >>= 1;
}
}
/*
取数调整
*/
private void adapt(int c, int deep, int maxDeep){
if(deep == maxDeep) return;
else{
int front = c<<1;
int back = (c<<1)+1;
Integer a = list.get(front);
Integer b = list.get(back);
Integer t = list.get(c);
int i=a.intValue(),j=b.intValue(),k=t.intValue();
if (k > i || k > j){
if(i > j){
list.set(c, b);
list.set(back, t);
adapt(back,deep+1,maxDeep);
}else{
list.set(c, a);
list.set(front, t);
adapt(front,deep+1,maxDeep);
}
}
return;
}
}
/*
计算当前堆的深度
*/
private int getDeep(){
int i=0,c;
while(true){
c = 1<<i;
i++;
if(end <= c+c-1){
break;
}
}
return i;
}
/*
取出堆顶
*/
public Integer top(){
Integer t = list.get(start);
list.set(start, list.get(--end));
list.set(end,0xfffffff);
int c = getDeep();
adapt(start,1,c);
return t;
}
/*
打印整个树,从上至下
*/
public void print(){
int hh = 1,weight = 0;
for(int i=1;i<end;i++){
System.out.print(list.get(i) + " ");
if(i == hh){
System.out.println();
hh += (2<<weight);
weight++;
}
}
System.out.println();
}
public static void main(String[] args) {
CompleteTree heap = new CompleteTree();
int[] q = {1,10,11,9,6,7,15,2,3,16};
int[] qq = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
int[] qqq = {10,2,5,12,6,7,1,9,9,10,1,15,19,25,3,5,8};
for(int i : qqq){
heap.insert(i);
}
heap.print();
System.out.println("#############################");
System.out.println(heap.top());
System.out.println("#############################");
heap.print();
System.out.println(heap.top());
System.out.println("#############################");
heap.print();
}
}