1、自定义实现:
(1)自定义的堆接口:
/**
* 元素为int类型的堆的接口
*/
public interface Heap {
/**
* 当堆为空时返回true
* @return
*/
boolean isEmpty();
/**
* 堆的元素个数
* @return
*/
int size();
/**
* 返回堆的根节点并将其从堆中删除
* @return
*/
int poll();
/**
* 返回堆的根节点元素但不删除
* @return
*/
int peek();
/**
* 向堆中添加一个元素,当堆已满时会返回false,此时无法再插入元素
* @param element
* @return
*/
boolean add(int element);
}
(2)自定义的小根堆实现:
/**
* 小根堆,即其根节点元素的值小于其子节点元素的值
*/
public class MinHeap implements Heap{
private int capacity;//堆的容量(能存储的最大元素个数)
private int heapSize;//堆中的元素个数
private int[] heap;//存储元素的小根堆
/**
* 构造函数,初始化堆的容量,默认容量设置为16
*/
public MinHeap() {
this.capacity = 16;
heap=new int[capacity+1];
}
/**
* 构造函数,初始化堆的容量
* @param capacity
*/
public MinHeap(int capacity) {
this.capacity = capacity;
heap=new int[capacity+1];
}
@Override
public boolean isEmpty() {
return (heapSize==0);
}
@Override
public int size() {
return heapSize;
}
@Override
public int poll() {
if(heapSize==0)
throw new RuntimeException("堆为空");
int result=heap[1];//保存根节点的值
//获取到最后一个叶子结点
int latElement=heap[heapSize--];
//将最后一个叶子节点放在根节点上
heap[1]=latElement;
int currentNode=1;//从根节点开始向下遍历,将根节点放在合适的位置上。
int child=2;//当前节点的子节点
while (child<=heapSize){
//heap[child]应该是较小的孩子
if(child<heapSize&&heap[child]>heap[child+1])
child++;
//已经找到了合适的插入位置
if(latElement<heap[child])
break;
//继续向下移动寻找位置
heap[currentNode]=heap[child];
currentNode=child;
child*=2;
}
heap[currentNode]=latElement;
return result;
}
@Override
public int peek() {
if(heapSize==0)
throw new RuntimeException("堆为空");
return heap[1];
}
@Override
public boolean add(int element) {
//堆已满
if (heapSize ==capacity)
return false;
int currentNode=++heapSize;//当前节点的索引
//从新叶子开始向上查找合适的位置将新节点插入
while (currentNode!=1&&heap[currentNode/2]>element){
heap[currentNode]=heap[currentNode/2];
currentNode/=2;
}
heap[currentNode]=element;
return true;
}
}
(3)自定义的大根堆实现:
/**
* 大根堆,即其根节点元素的值大于其子节点元素的值
*/
public class MaxHeap implements Heap{
private int capacity;//堆的容量(能存储的最大元素个数)
private int heapSize;//堆中的元素个数
private int[] heap;//存储元素的大根堆
/**
* 构造函数,初始化堆的容量,默认容量设置为16
*/
public MaxHeap() {
this.capacity = 16;
heap=new int[capacity+1];
}
/**
* 构造函数,初始化堆的容量
* @param capacity
*/
public MaxHeap(int capacity) {
this.capacity = capacity;
heap=new int[capacity+1];
}
@Override
public boolean isEmpty() {
return (heapSize==0);
}
@Override
public int size() {
return heapSize;
}
@Override
public int poll() {
if(heapSize==0)
throw new RuntimeException("堆为空");
int result=heap[1];//保存根节点的值
//获取到最后一个叶子结点
int latElement=heap[heapSize--];
//将最后一个叶子节点放在根节点上
heap[1]=latElement;
int currentNode=1;//从根节点开始向下遍历,将根节点放在合适的位置上。
int child=2;//当前节点的子节点
while (child<=heapSize){
//heap[child]应该是较大的孩子
if(child<heapSize&&heap[child]<heap[child+1])
child++;
//已经找到了合适的插入位置
if(latElement>=heap[child])
break;
//继续向下移动寻找位置
heap[currentNode]=heap[child];
currentNode=child;
child*=2;
}
heap[currentNode]=latElement;
return result;
}
@Override
public int peek() {
if(heapSize==0)
throw new RuntimeException("堆为空");
return heap[1];
}
@Override
public boolean add(int element) {
//堆已满
if (heapSize==capacity)
return false;
int currentNode=++heapSize;//当前节点的索引
//从新叶子开始向上查找合适的位置将新节点插入
while (currentNode!=1&&heap[currentNode/2]<element){
heap[currentNode]=heap[currentNode/2];
currentNode/=2;
}
heap[currentNode]=element;
return true;
}
}
2、java jdk中的堆:
通过使用jdk自带的PriorityQueue类,当调用不带参数的构造函数时,堆的默认容量为11(可通过调用带参数的构造函数创建堆来指定堆的容量)。
(1)小根堆:
PriorityQueue<Integer> minHeap=new PriorityQueue<>();
//
(2)大根堆:(在小根堆的基础上重写Comparator中的compare函数)
PriorityQueue<Integer> maxHeap=new PriorityQueue<Integer>(new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});