学习目标:
掌握堆相关知识
学习内容:
- 堆
- 堆的构造
- 堆的应用
堆:
堆(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:
-
堆中某个节点的值总是不大于或不小于其父节点的值;
-
堆总是一棵完全二叉树。
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。
构建堆:
tips(数组索引从0开始):
- 最后一个非叶子节点:size/2 -1
- 父节点 (child-1)/2
- 子节点 left = parent * 2+1; right = parent * 2+2
public class MaxHeap {
//大顶堆
int[] array;
int size;
public MaxHeap(int capacity) {
this.array = new int[capacity];
}
public MaxHeap(int[] array){
this.array = array;
this.size = array.length;
heapify();
}
public void heapify() {
for (int i = size / 2 - 1; i >= 0; i--) {
down(i);
}
}
public int peek(){
return array[0];
}
public int poll(){ //删除堆顶元素
int top = array[0];
swap(0,size-1);
size--;
down(0);
return top;
}
public int poll(int index){ //删除指定位置元素
int temp = array[index];
swap(index,size-1);
size--;
down(index);
return temp;
}
public void replace(int replaced){ //替换堆顶元素
array[0] = replaced;
down(0);
}
public boolean offer(int offered){
if(size == array.length){
return false;
}
up(offered);
size++;
return true;
}
private void up(int offered) {
int child = size;
while (child>0){
int parent = (child-1)/2;
if(array[child]>array[parent]){
swap(child,parent);
}else {
break;
}
child = parent;
}
array[child] = offered;
}
private void down(int parent) {
int left = parent * 2 + 1;
int right = left + 1;
int max = parent;
if (left < size && array[left] > array[max]) {
max = left;
}
if (right < size && array[right] > array[max]) {
max = right;
}
if(max!=parent){
swap(max,parent);
down(max);
}
}
private void swap(int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
}
堆的练习:
1.堆排序
- 建立大顶堆
- 将堆顶元素和堆㡳元素交换,缩小并下浅调整堆
- 重复第二个步骤直至堆里只剩一个节点
while (maxHeap.size>1){
maxHeap.swap(0,maxHeap.size-1);
maxHeap.size--;
maxHeap.down(0);
}
2.数组中第k大的元素
public static int findKthLargest(int[] numbers, int k) {
MinHeap minHeap = new MinHeap(k);
for (int i = 0; i < k; i++) { //前K个元素入小顶堆,堆顶始终为当前第K小元素
minHeap.offer(numbers[i]);
}
for (int i = k; i < numbers.length; i++) { //剩余元素入堆
if(numbers[i]>minHeap.peek()){
minHeap.replace(numbers[i]);
}
}
return minHeap.peek();
}