1 优先队列是至少允许下列两种操作的数据结构:insert和deleteMin操作,insert相当于入队,deleteMin则相当于在优先队列中的出队。
2 我们使用二叉堆(这里也就叫做堆),来实现这种数据结构。堆有两个重要性质,其一是结构性,是一颗完全二叉树(高为h的二叉树 有2exp(h)到2exp(h+1)-1个节点)
其二是对序性质,如果我们考虑任意一个字树也是一个堆,那么任意节点应该<它的所有孩子
上代码:
package com.itany.binarydui;
public class BinaryHeap<T extends Comparable<? super T>>
{
//堆实际上是通过一个数组容器来实现的 每个元素的下标十分有意义
private static final int DEFAULT_CAPACITY=10;
private int currentSize;//堆中的元素个数
private T[] array;//堆数组
public int getCurrentSize()
{
return currentSize;
}
public BinaryHeap()
{
this(DEFAULT_CAPACITY);
}
public BinaryHeap(int capacity)
{
array=(T[])new Comparable[capacity];
}
//直接初始化时候就放入一个数组 不一个个insert
public BinaryHeap(T[] arrayT)
{
currentSize=arrayT.length;
array=(T[])new Comparable[(currentSize+2)*11/10];
int i=1;
for(T t:arrayT)
array[i++]=t;
buildHeap();//把这些数组传进来的数据 优化成二叉堆
}
public void makeEmpty()
{
currentSize=0;
array=null;
}
public boolean isEmpty()
{
return currentSize==0;
}
public void insert(T t)
{
if(currentSize==array.length-1)
enlargeArray(2*array.length+1);
int hole=++currentSize;//创建一个空穴 再把空穴上浮
//array[hole/2]就是array[hole]的父亲 不管hole是左儿子还是右儿子
for(;hole>1 && t.compareTo(array[hole/2])<0;hole=hole/2)
{
//把大的父亲 拿到下面来 使hole变成父亲的大小 这样就避免了三个式子来进行交换
array[hole]=array[hole/2];
}
array[hole]=t;//把空穴填上值
}
public T findMin()
{
return array[1];
}
public T deleteMin() throws Exception
{
if(isEmpty())
throw new Exception();
T minItem=findMin();
//找出最小之后 还需要对堆的结构根据堆序进行调整
//因为删除了一个 所以多出了一个空位子 我们把最后一个值 放到最上面去 然后再从数组序号1(原来的最后一个值)开始进行相应的比大小调整
array[1]=array[currentSize--];
percolateDown(1);
return minItem;
}
//向下过滤 调整堆结构 使之满足堆序性要求
private void percolateDown(int hole)
{
int child=0;//设置孩子的序号 child序号会不断改变
//把 最上面的元素(不一定是最小的)先存储起来,因为如果它小的话 顶部的值会被下面的值给取代 等到Hole找到合适的位子时候 再把temp放到Hole里面去
T temp=array[1];
//currentSize>=2*hole表示当前hole有孩子时候就会继续进行下沉比较 如果没有孩子了 则比较结束 再给hole赋值
for(;currentSize>=2*hole;hole=child)
{
//每循环一次 child都要至少*2
child=2*hole;
//child!=currentSize表示还有右孩子 且右孩子比较小 那么 此时应该array[hole]和右孩子进行比较 否则就和左孩子比较
if(child!=currentSize && array[child].compareTo(array[child+1])>0)
child++;
if(array[hole].compareTo(array[child])>0)
array[hole]=array[child];
else
break;
}
array[hole]=temp;
}
//建造一个堆
private void buildHeap()
{
for(int i=currentSize/2;i>=1;i--)
{
percolateDown(i);//对每一个父节点进行堆序优化
}
}
//扩大数组
private void enlargeArray(int newSize)
{
T[] newArray=(T[])new Comparable[newSize];
for(int i=0;i<array.length;i++)
{
newArray[i]=array[i];
}
array=newArray;
}
}
package com.itany.binarydui;
public class Test
{
public static void main(String[] args)
{
// BinaryHeap<Integer> bh=new BinaryHeap<Integer>();
// bh.insert(50);
// bh.insert(30);
// bh.insert(40);
Integer[] it={50,30,40};
BinaryHeap<Integer> bh=new BinaryHeap<Integer>(it);
System.out.println(bh.getCurrentSize());
try
{
System.out.print(bh.deleteMin()+" ");
System.out.print(bh.deleteMin()+" ");
System.out.print(bh.deleteMin()+" ");
}
catch (Exception e)
{
e.printStackTrace();
}
}
}