堆(Heap)与优先队列
堆的基础知识
堆是一个完全二叉树,可以采用数组形式存储
下标从0开始,i位置的节点:
左孩子坐标为:2 * i + 1;
右孩子坐标为:2 * i + 2;
父亲节点坐标为:(i - 1) / 2;
Java中的PriorityQueue类(优先队列)是堆的实现类
大顶堆:
性质:
在二叉树任意的三元子中,根节点都大于两个子节点的堆
最大值在堆顶,第二大的值在根节点的左节点或右节点中。
兄弟之间无大小关系
堆适合维护:集合最值
小顶堆:
性质:
在二叉树任意的三元子中,根节点都小于两个子节点的堆
最小值在堆顶,第二小的值在根节点的左节点或右节点中。
兄弟之间无大小关系
堆—尾部插入调整(插入元素)
将新节点不断地与其父节点比较,新节点大于父节点则与父节点交换位置。
堆—头部弹出调整(删除元素)
大顶堆:弹出的是堆中的最大值
小顶堆:弹出的是堆中的最小值
在弹出堆顶元素之后,数组长度应该减一。原0下标的元素因为被弹出,所以为空,那么我们就把原数组中末尾的元素**(为了方便将其记为a)插入到下标0的位置上去。随后我们要进行堆性质的维护,每一次都从三元组中选择一个最大的节点与a交换,直到元素a**是三元组中最大的节点。
堆排序
—待完善
堆–优先队列的一种实现方式
普通队列 | (最大/最小)堆 |
---|---|
尾部入队 | 尾部可以插入 |
头部出队 | 头部可以弹出 |
先进先出 | 每次出队权值(最大/最小的元素) |
数组实现 | 数组实现,逻辑上看成一个堆 |
堆的代码实现
大顶堆:
import java.util.Arrays;
class BigHeap{
int size;
int[] bigHeap;
public BigHeap() {
this.size = 0;
this.bigHeap = new int[10];//默认是10大小
}
public BigHeap(int n) {
this.size = 0;
this.bigHeap = new int[n];
}
//返回堆大小的方法
public int size(){
return size;
}
//返回堆顶元素的方法
public int top(){
return bigHeap[0];
}
//向堆中插入元素的方法
public void push(int num){
if(size == bigHeap.length) return;//数组满了无法插入
bigHeap[size] = num;
int index = size++;//堆中元素数量加一,index为最后一个元素的下标
while(index > 0 && bigHeap[(index - 1) / 2] < num){
//保证下标不越界并且可以比较大小
swap(bigHeap,index,(index - 1) / 2);
index = (index - 1) / 2;
}
}
//删除堆顶元素的方法
public int pop(){
if(size == 0)
return 0;
int num = bigHeap[0];
bigHeap[0] = bigHeap[size - 1];
bigHeap[size - 1] = 0;//这里不写也是可以的,写了主要是为了toString观看方便,因为插入新值的时候会把老值覆盖掉
size -= 1;
int n = size - 1;//n为数组中最后一个元素的下标
int index = 0;//这是要向下进行置换的元素
while((index * 2 + 1) <= n){
//判断是否越界
int temp = index;
if(bigHeap[temp] < bigHeap[index * 2 + 1