优先队列:
优先队列是最少拥有两种操作(插入和删除最小值)实现的数据结构。
实现优先队列并不难,我相信只要是有点计算机基础的人都能想到一些方法,比如:时刻保持一个有序队列,或者每次遍历一个队列直到找出最小值为止,或者更高级点的那就是使用二叉查找树。但是无论是从时间/空间复杂度还是从代码复杂度来讲,以上三种都不是实现优先队列的最好选择。
堆:
就现在来讲,对于优先队列的实现方法中,使用最普遍的还是一种叫做堆的工具!
堆说白了其实就是一颗完全二叉树,但相比于完全二叉树,堆又有着结构性和堆序性两个性质。
完全二叉树的重要规律:
在用数组实现完全二叉树时,对于数组中的任意位置i,其左儿子在2i位置上,右儿子在2i+1位置上,它的父亲则在i/2的位置上,记住这个规律,这对于堆的实现时直观重要的。
代码实现:
bean对象:
public class Node<T> implements Comparable<T>{
private T data;
public Node(T data){
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public int compareTo(T o) {
if (o instanceof Integer && data instanceof Integer){
Integer integer1 = (Integer)data;
Integer integer2 = (Integer)o;
return integer1-integer2;
}else {
throw new RuntimeException("params not Integer");
}
}
}
堆实现:
public class BinaryHeap<T> implements TreeService<T> {
private Node<T>[] array;
private int size = 11;
private int currentSize = 0;
public BinaryHeap(){
array = new Node[size];
}
public BinaryHeap (int size){
this.size = size;
array = new Node[size+1];
}
public BinaryHeap(Collection collection){
array = new Node[collection.size()+1];
for (Object o : collection) {
array[++currentSize] = new Node<>((T) o);
}
for (int hole=currentSize/2;hole>0;hole--){
System.out.println(hole);
fliterDown(hole);
}
System.out.println("---------");
}
/**
* 上虑插入
* @param o
*/
@Override
public void insert(T o) {
if (isEmpty()){
array[1] = new Node<T>(o);
}else if (isFull()) {
throw new RuntimeException("Heap is Full");
}else {
int tail = currentSize+1;
//注意完全二叉树性质
for (array[0]=new Node<>(o); array[tail/2].compareTo(o) > 0 ; tail/=2) {
//如果父节点数据大于待插入数据
array[tail] = array[tail/2];
}
array[tail] = new Node<T>(o);
}
currentSize++;
}
/**
* 删除最小值
* 删除方法:移除根节点中
*/
public T deleteMin(){
if (isEmpty()) {
throw new RuntimeException("Heap is empty");
}
Node min = array[1];
array[1] = array[currentSize--];
fliterDown(1);
return (T) min.getData();
}
private void fliterDown(int hole){
T tail = array[hole].getData();
int child;
for (;2*hole <= currentSize;hole=child){
child = 2 * hole;
//如果child不等于当前size则代表当前节点有两个子节点
if (child!=currentSize&&array[child].compareTo(array[child+1].getData())>0){
child++;
}
if (array[child].compareTo(tail)<0){
array[hole]=array[child];
}else {
break;
}
}
array[hole]=new Node<>(tail);
}
@Override
public boolean isEmpty() {
return currentSize==0;
}
@Override
public boolean isFull() {
return currentSize==size;
}
@Override
public Node<T>[] getArray() {
return array;
}