一、堆(Heap)
概念
- 堆逻辑上是一棵完全二叉树;
- 堆物理上是保存在数组中;
- 满足任意结点的值都大于其子树中结点的值,叫做大堆,或者大根堆,或者最大堆;
- 反之,则是小堆,或者小根堆,或者最小堆
- 堆的基本作用是用来查找最值的,堆顶元素。
操作-向下调整
前提:左右子树必须已经是一个堆了,才能调整
调整过程(以小堆为例):
- index:代表要调整位置的下标
- array:代表存储堆的数组
- size:代表数组中被视为堆元素的个数
- left:代表index左孩子的下标
- right:代表index右孩子的下标
- minIndex:保存index最小孩子的下标
思路:
(以小堆调整为例)
1.index如果是叶子结点,则调整结束
(1)判断 index 位置有没有孩子
(2)因为堆是完全二叉树,没有左孩子就一定没有右孩子,所以判断是否有左孩子
(3)因为堆的存储结构是数组,所以判断是否有左孩子即判断左孩子下标是否越界,即 left >= size 越界
2. 确定 left 或 right,谁是 index 的最小孩子 minIndex
(1)如果右孩子不存在,则 minIndex = left
(2) 否则,比较 array[left] 和 array[right] 值得大小,选择小的为 minIndex
3.比较 array[index] 的值 和 array[minIndex] 的值,如果 array[index] <=array[minIndex],则满足堆的性质,调整结束
4.否则,交换 array[index] 和 array[min] 的值
5.然后因为 minIndex 位置的堆的性质可能被破坏,所以把 minIndex 视作 index,继续循环执行以上操作
向上调整思路:
1.判断index是否为根节点(index==0),如果是则结束;
2.找到index的父亲节点,比较它的值和父亲节点的值,如果array[Index]<=array[parentIndex],则结束;否则,交换两者的值;
3.让index为父亲结点的值,继续循环。
思路整体简单一点,只需要和父亲节点比较即可。
建堆
建堆也是一个循环调整的过程,首先保证它在逻辑上是一棵二叉树,根据堆的定义和性质进行判断让它符合堆的性质。
堆的应用:
优先级队列(堆):
public class MyPriorityQueue {
private Integer[] array;
private int size;
public MyPriorityQueue(){
array=new Integer[100];
size=0;
}
//得到element下标的元素
public Integer element(){
if(size==0){
throw new RuntimeException("空了");
}
return array[0];
}
//删除元素
public Integer remove(){
if(size==0){
throw new RuntimeException("空的");
}
int e=array[0];
array[0]=array[size-1];
size--;
adjustDown(0);
return e;
}
public void adjustDown(int index){
while(true){
int leftIndex=2*index+1;
if(array[leftIndex]>=size){
break;
}
int minIndex=leftIndex;
int rightIndex=leftIndex+1;
if(rightIndex<size&&array[rightIndex]<array[leftIndex]){
minIndex=rightIndex;
}
int t=array[index];
array[index]=array[rightIndex];
array[rightIndex]=t;
index=minIndex;
}
}
public void add(Integer e){
array[size]=e;
size++;
adjustUp(size-1);
}
private void adjustUp(int index){
while (true){
if(index==0){
break;
}
int parentIndex=(index-1)/2;
if(array[parentIndex]<=array[index]){
break;
}
int t=array[index];
array[index]=array[parentIndex];
array[parentIndex]=t;
index=parentIndex;
}
}
public static void main(String[] args) {
MyPriorityQueue myPriorityQueue=new MyPriorityQueue();
myPriorityQueue.add(1);
myPriorityQueue.add(4);
myPriorityQueue.add(3);
myPriorityQueue.add(5);
myPriorityQueue.add(6);
}
}