优先级队列-堆实现

  1 package sorts;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 import java.util.Random;
  6 
  7 public class PriorityQueue<T extends Comparable<T>> { // min-heap
  8     private List<T> heap = new ArrayList<>();
  9     private static final int ROOT_INDEX = 0;
 10     private static final int PRE_ROOT_INDEX = ROOT_INDEX - 1;
 11     public void offer(T obj) {
 12         heap.add(obj);//在最后增加一个元素
 13         int index = heap.size() - 1;//最后一个元素的索引
 14         while (index > ROOT_INDEX) {//在堆中加一个元素后,调整堆使其再成为一个堆
 15             index = stepUpHeap(index);//上浮
 16         }
 17     }
 18     private int stepUpHeap(int index) {
 19         int parentIndex = parent(index);//获取父节点的索引
 20         T element = heap.get(index);
 21         T parent  = heap.get(parentIndex);
 22         if (parent.compareTo(element) > 0) { //父节点大于儿子节点,交换
 23               heap.set(parentIndex, element);
 24               heap.set(index, parent);
 25               return parentIndex;  // 跳到父索引
 26          } else   
 27               return ROOT_INDEX; //不需要交换
 28     }
 29     public T poll() {
 30         if (isEmpty())
 31             throw new RuntimeException();
 32         int index = heap.size() - 1;//最后一个元素的索引
 33         T least;
 34         if(index==0){
 35            least = heap.get(index);
 36            heap.remove(index);
 37         }
 38         else{
 39             T element = heap.get(index);//取最后一个元素
 40             least  = heap.get(ROOT_INDEX);//取堆的根元素
 41             heap.set(ROOT_INDEX, element);//交换这两个元素
 42             heap.set(index, least);
 43             heap.remove(index);//删除最后一个元素
 44             stepDownHeap(ROOT_INDEX);//下沉调整,使之再次成为堆
 45          }
 46          return least;
 47     }
 48     private void stepDownHeap(int index) {
 49         int p = index;//parent
 50         int lchild = lchild(p);//左子节点
 51         T temp = heap.get(p);
 52         while(lchild<heap.size()){
 53         if(lchild+1<heap.size() && heap.get(lchild+1).compareTo(heap.get(lchild))<0)//右节点比左节点小
 54             lchild = lchild + 1;//取两个儿子节点中小的一个
 55             if(temp.compareTo(heap.get(lchild))<=0)//不需要调整了
 56                     break;
 57             else {
 58                  heap.set(p,heap.get(lchild));//较小的儿子节点上浮
 59                  p = lchild;
 60                  lchild = lchild(p);//继续调整
 61             }
 62         }
 63         heap.set(p,temp);//最后要将temp放到p
 64     }
 65     public T peek() {
 66         if (isEmpty())
 67             throw new RuntimeException();
 68         return heap.get(0);
 69     }
 70     public boolean isEmpty() {
 71         return heap.isEmpty();
 72     }
 73     public int size() {
 74         return heap.size();
 75     }
 76     @Override
 77     public String toString() {
 78         return heap.toString();
 79     }
 80     // index starts from 0
 81     private int parent(int index) {
 82         if (index%2==0) {
 83             return ( index / 2 ) - 1;
 84         } else {
 85             return index / 2;
 86         }
 87     }
 88     private int lchild(int index) {
 89         return index * 2 + 1;
 90     }
 91     private int rchild(int index) {
 92         return index * 2 + 2;
 93     }
 94     // test
 95     public static void main(String[] args) {
 96         Random random = new Random();
 97         PriorityQueue<Integer> pq = new PriorityQueue<>();
 98         for (int i = 0; i < 10; i++) {
 99             pq.offer(random.nextInt(100));
100         }
101         for (int i = 0; i < 10; i++) {
102             System.out.print(pq.poll() + " ");
103         }
104     }
105 }

 

posted @ 2014-09-06 12:53  rldts  阅读(283)  评论(0编辑  收藏  举报