基本介绍
堆的实现通过构造二叉堆(binary heap),实为二叉树的一种;这种数据结构具有以下性质。
任意节点小于(或大于)它的所有后裔,最小元(或最大元)在堆的根上(堆序性)。
堆总是一棵完全树。即除了最底层,其他层的节点都被元素填满,且最底层尽可能地从左到右填入。
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
n个元素序列{k1, k2… ki…kn},当且仅当满足下列关系时称之为堆:
(ki <= k2i, ki <= k2i+1)或者(ki >= k2i, ki >= k2i+1), (i = 1, 2, 3, 4… n/2)
Shift Up
当向堆中插入元素时,先将元素放于堆的末尾(data 中的 count + 1 的位置上)。
count++
while(k > 1 && data[k] > data[k/2]){
swap(data[k], data[k/2]);
k /= 2;
}
Shift Down
代码实现
package com.dataStructure.heap;
import java.lang.*;
public class MaxHeap {
protected Integer[] data;
protected int count;
protected int capacity;
// 构造函数,构造一个空的堆,可以容纳 capacity 个元素
public MaxHeap(int capacity) {
data = new Integer[capacity + 1];
count = 0;
this.capacity = capacity;
}
// 返回堆中元素的个数
public int size() {
return count;
}
// 返回一个布尔值,表示堆是否为空
public boolean isEmpty() {
return count == 0;
}
// 向最大堆中插入一个新的元素 item
public void insert(Integer item) {
if (count + 1 > capacity) {
System.out.println("元素数量已经达到堆容量的最大值!");
return;
}
// 先将 item 放在堆的末尾
data[count + 1] = item;
count++;
// 上浮 item
shiftUp(count);
}
// 将堆中 k 位置的元素 上浮 到合适的位置
private void shiftUp(int k) {
// 如果 当前节点(k指向的位置) 不是根节点,且 父节点 < 当前节点
// 进行循环
while (k > 1 && data[k / 2].compareTo(data[k]) < 0) {
swap(k, k / 2);
k /= 2;
}
}
// 将堆中 i 和 j 位置的元素进行交换
private void swap(int i, int j) {
Integer temp = data[i];
data[i] = data[j];
data[j] = temp;
}
// 从堆中取出堆顶元素,即堆中所存储的最大元素
public Integer extractMax() {
if (count <= 0 ){
System.out.println("堆已空!");
return null;
}
Integer ret = data[1];
swap(1, count);
count--;
shiftDown(1);
return ret;
}
// 将堆顶元素 下沉 到合适的位置
private void shiftDown(int k){
while (2*k <= count){
int j = 2*k;
// 如果 有 右子节点 且 右子节点 > 左子节点
if (j+1 <= count && data[j+1].compareTo(data[j]) > 0){
// j 移动到 右子节点 处
j++;
}
// 如果 根节点 > 子节点中较大者
if (data[k].compareTo(data[j]) >= 0){
// 跳出循环
break;
}
// 交换 根节点 和 子节点中较大者
swap(k, j);
// 移动 k
k = j;
}
}
public static void main(String[] args) {
MaxHeap maxHeap = new MaxHeap(100);
int N = 50; // 堆中元素个数
int M = 100; // 堆中元素取值范围[0, M)
for (int i = 0; i < N; i++)
maxHeap.insert(new Integer((int) (Math.random() * M)));
System.out.println(maxHeap.size());
// for (Integer item : maxHeap.data) {
// System.out.print(item + " ");
// }
while (maxHeap.count != 0){
System.out.print(maxHeap.extractMax() + " ");
}
}
}