堆
前言
堆有很多种存储形式,我们探讨的二叉堆 二叉堆-就是一颗完全二叉树一、堆的特点
a.二叉堆首先是一颗完全二叉树(结构上)
b.二叉堆节点间关系满足一下关系:
堆中根节点<=子树中的节点值(最大堆/大根堆)
堆中根节点>=子树中的节点值(最小堆/小根堆)
注意:在最大堆中,只能保证当前根节点大于等于子树的所有节点(任意子树都满足),节点大小与所处层数无关
二、堆的基本实现
/**
* 基于整形的最大堆实现
* 此时根节点从0开始编号,若此时节点编号为k
* 左子树编号=2k+1,右子树编号2k+2,父节点编号(k-1)/2
*/
public class MaxHeap {
//使用JDK的动态数组(ArrayList)来存储一个最大堆
List<Integer> data;
public MaxHeap() {
//构造方法的this调用
this(10);
}
//初始化的堆大小
public MaxHeap(int size) {
data = new ArrayList<>(size);
}
public boolean isEmpty() {
return data.size() == 0;
}
//根据索引得到父节点的索引
private int parent(int k){
return (k-1) >>1;
}
//根据索引得到左子树索引
private int leftChild(int k){
return (k<<1)+1;
}
//根据索引得到右子树索引
private int rightChild(int k){
return (k<<1)+2;
}
}
1.添加一个新元素
/**
* 添加一个新元素
* @param val
*/
public void add(int val){
//1.直接向数组末尾添加元素
data.add(val);
//2.进行元素的上浮操作
siftUp(data.size()-1);
}
/**
* 元素上浮操作
* @param k
*/
private void siftUp(int k) {
//此时还没走到根节点,上浮操作的终止条件:已经走到根节点||当前节点值<=父节点的值
//循环的迭代条件:还存在父节点并且当前节点值>父节点
while(k>0 && data.get(k)>data.get(parent(k))){
swap(k,parent(k));
k = parent(k);
}
}
private void swap(int i, int j) {
int temp = data.get(i);
data.set(i,data.get(j));
data.set(j,temp);
}
public String toString(){
return data.toString();
}
2.查看最大元素
public int peekMax(){
if (isEmpty()){
throw new NoSuchElementException("heap is empty");
}
return data.get(0);
}
3.取出最大元素
public int extractMax(){
//取值一定注意判空
if (