最近在复习算法相关知识,今天复习到了二叉堆。
二叉堆是一个完全二叉树,又分为最大堆和最小堆。最大堆的每一个父节点都大于它的两个子节点,最小堆的每个父节点都小于它的两个子节点。本文中,我简单编写代码实现了最小堆,本例也可看作是优先队列的一种简单实现。
package com.zhangyu.study.test20191120;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
* Function: 模拟二叉堆 模拟最小堆
*
* @author zhangyu
* Date: 2019/11/20
* @since JDK 1.8
*/
public class MyBinaryHeap {
/**
* 数据
*/
private int [] data;
/**
* 数据大小
*/
private int size;
/**
* 加载因子
*/
private static final double LOAD_FACTOR = 0.75;
/**
* 默认数据容量
*/
private static final int defaultCapacity = 12;
/**
* 默认构造器
*/
public MyBinaryHeap() {
this(defaultCapacity);
}
/**
* 指定默认容量的构造器
* @param defaultCapacity 默认容量
*/
public MyBinaryHeap(int defaultCapacity) {
data = new int[defaultCapacity];
}
/**
* 将数组转换成二叉堆
* @param originData 原始数据
*/
public MyBinaryHeap(int[] originData) {
data = originData;
size = originData.length;
// 构造堆
for (int i = (size -2) >> 1;i>=0;i-- ) {
down(i) ;
}
}
/**
* 上浮操作 将最后一个元素进行上浮 在增加元素时会遇到上浮
*/
private void up(){
// 最后一个节点的索引
int childIndex = size-1;
// 需要上浮的数据
int tmp = data[childIndex];
// 父节点索引
int parentIndex = (childIndex-1) >> 1;
while (childIndex > 0 && tmp < data[parentIndex]) {
data[childIndex] = data[parentIndex];
childIndex = parentIndex;
parentIndex = (childIndex-1) >> 1;
}
data[childIndex] = tmp;
}
/**
* 下沉操作 在构建堆的时候,只要将所有非子节点依次下沉
* @param parent 需要下沉的节点索引
*/
private void down(int parent){
// 临时数据
int tmp = data[parent];
// 左子节点的索引
int leftChild = (parent << 1) +1;
while (leftChild < size) {
// 如果有右节点,并且右节点小于左节点,则父节点与右节点进行交换
if (leftChild+1 < size && data[leftChild]>data[leftChild+1]) {
// 这时候其实应该叫rightChild了
leftChild ++;
}
if (tmp <= data[leftChild]) {
break;
}
data[parent] = data[leftChild];
parent = leftChild;
leftChild = (parent << 1 )+1;
}
data[parent] = tmp;
}
/**
* 当数组中有效元素的数量达到加载因子控制的数量时,进行扩容操作
*/
private void resize(){
if (size >= data.length * LOAD_FACTOR) {
int[] newData = new int[data.length << 1];
System.arraycopy(data,0, newData, 0, size);
data = newData;
}
}
/**
* 向二叉堆中增加元素
*
* 思想是将新增的元素添加到当前最后一个有效元素的后面,然后将最后一个有效元素进行上浮操作
*
* @param data 添加的数据
*/
public void add(int data) {
resize();
this.data[size++] = data;
up();
}
/**
* 移除元素 即移除第一个元素
*
* 思想是将第一个元素返回,然后将最后一个有效元素放到第一个元素的位置,进行下沉操作
*
* @return 移除元素的值
*/
public int remove(){
int tmp = data[0];
data[0] = data[--size];
down(0);
return tmp;
}
/**
* 打印当前数组
*/
public void print(){
if (size == 0) {
System.out.println("None !");
} else {
System.out.println(Arrays.stream(data).limit(size).mapToObj(Integer::toString).collect(Collectors.joining(" ")));
}
}
public static void main(String[] args) {
MyBinaryHeap heap = new MyBinaryHeap(new int[]{1,3,2,6,5,7,8,9,10,0});
heap.print();
heap.add(2);
heap.print();
heap.remove();
heap.print();
}
}
水平有限,如有错误,请您指出!