数据结构-优先队列(堆)的实现
数据结构--优先队列(堆)的实现
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(); } } }