- 堆就是通过完全二叉树实现的,可以参考排序部分的堆排序。
当一一棵二叉树的每个结点都大于等于它的两个子结点时,被称为堆有序。
完全二叉树是效率很高的数据结构,堆是一种完全二叉树或者近似完全二叉树,所以效率极高,像十分常用的排序算法、Dijkstra算法、Prim算法等都要用堆才能优化,几乎每次都要考到的二叉排序树的效率也要借助平衡性来提高,而平衡性基于完全二叉树。
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
- 对于第n行,最多有2^(n-1)个元素。
- 通过数组实现二叉堆
public class CompleteBinaryTree<K extends Comparable<K>> {
private Object[] arr; //因为无法实现泛型数组,我们通过Object数组替代。第一个位置不存储元素
private int N; //树中元素的个数。
public CompleteBinaryTree(int N) {
arr = new Object[N];
}
private void swap(int i, int j){ //交换两个元素的位置
Object temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
@SuppressWarnings("unchecked")
private boolean less(Integer i, Integer j){
return ((K)arr[i]).compareTo(((K)arr[j])) < 0;
}
//上浮方法
private void swin(int k){
//当前节点不是第一个元素并且大于它的父结点,则进行位置的交换。
while(k > 1 && less(k/2, k)){
swap(k/2, k);
k /= 2;
}
}
public Integer size(){
return N;
}
@SuppressWarnings("unchecked")
public K get(int i){
return (K)arr[i];
}
private void sink(int i){
while(i * 2 <= N){
int j = i * 2;
if(j + 1 < N && less(j, j+1)) j++; //取两个子结点中更大的一个。
swap(i, j);
i = j; //在当前子树中继续进行下沉
}
}
}
- 增
public void insert(K k){
arr[++N] = k;
swin(N);
}
- 删
public K delMax(){
K max = (K)arr[1];
swap(1, N + 1);
arr[N + 1] = null;
sink(1);
N--;
return max;
}