1.堆
堆实际上就是用数组将一个完全二叉树存起来,堆的主要用途就是用来找集合中的最大值和最小值,也可以解决top-K问题,就是类似找出第一最大值,第二最大值。。。。
1》堆可以分为:大堆和小堆
大堆:树中的任意节点,节点值必须大于左右孩子的值
小堆:树中的任意节点,节点值必须小于左右孩子的值
2》堆的调整操作:
向上调整(除根结点外,其他结点都符合堆的要求)对象:大堆小堆
private void shiftUp(int[] array,int size,int index) {
int child = index;
int parent = (child-1)/2;
while (child > 0) {
if (array[parent]<array[child]) {
int tmp = array[parent];
array[parent] = array[child];
array[child] = tmp;
}else {
break;
}
child = parent;
parent = (child-1)/2;
}
}
时间复杂度:O(logN)
向下调整(除孩子结点,其他结点都符合堆的要求)对象:大堆小堆
public static void shiftDown(int[] array,int size,int index) {
int parent = index;
int child = 2*parent+1;
while (child<size) {
if (child+1<size&&array[child+1]>array[child]) {
child = child+1;
}
if (array[child]>array[parent]) {
int tmp = array[child];
array[child] = array[parent];
array[parent] = tmp;
}else {
break;
}
parent = child;
child = 2*parent+1;
}
}
时间复杂度:O(logN)
3》建堆(时间复杂度:O(N))
基于向下调整建堆必须从后往前遍历数组
基于向上调整建堆必须从前往后遍历数组
public static void createHeap(int[] array,int size) {
for (int i = (size-1-1)/2;i>=0;i--) {
shiftDown(array,size,i);
}
}
2.用堆创建的优先队列
1》入队列
public void offer(int x) {
array[size] = x;
size++;
shiftUp(array,size,size-1);
}
直接插到数组最后,然后向上调整成大堆
2》出队列
public Integer poll() {
if (size <= 0) {
return null;
}
int ret = array[0];
array[0] = array[size-1];
size--;
shiftDown(array,size,0);
return ret;
}
即将数组第一个元素取出并删除还要保持剩下的结点是一个堆,用新的变量保存根节点,然后将最后一个元素赋值给第一个,然后size–将最后一个元素删除,在从0号元素进行向下调整就可以保证剩下元素是堆,然后返回新的变量,最大值就取到了。
3》取队首元素
public Integer peek() {
if (size == 0) {
return null;
}
return array[0];
}
3.标准库中的优先队列
import java.util.Comparator;
import java.util.PriorityQueue;
// 标准库中的优先队列默认为小堆
public class TestPriorityQueue {
//自定义优先级
static class MyComp implements Comparator<Integer> {
public int compare(Integer o1,Integer o2) {
return o2-o1;
}
}
public static void main(String[] args) {
PriorityQueue<Integer> queue = new PriorityQueue<>(new MyComp());
queue.offer(9);
queue.offer(5);
queue.offer(2);
queue.offer(7);
queue.offer(3);
queue.offer(6);
queue.offer(8);
while (!queue.isEmpty()) {
Integer cur = queue.poll();
System.out.println(cur);
}
}
}
标准库中的优先队列默认是小堆,即最小的优先权最高,我们可以通过定义这个比较器来修改输出顺序。