2011-03-04 CLRS Chapter6 Heapsort(下)优先队列
优先队列的概念好理解,想想进程调度中的进程队列就是了。在CLRS中,优先队列的定义如下:
A priority queue is a data structure for maintaining a set S of elements, each with an associated value called a key. A max-priority queue supports the following operations.
· INSERT(S, x) inserts the element x into the set S. This operation could be written as S ← S ∪ {x}.
· MAXIMUM(S) returns the element of S with the largest key.
· EXTRACT-MAX(S) removes and returns the element of S with the largest key.
· INCREASE-KEY(S, x, k) increases the value of element x's key to the new value k, which is assumed to be at least as large as x's current key value.
下面的代码由Java实现,很是别扭,如果把Heap当作数据层,PriorityQueue当作逻辑层,那最大的问题就是对于很多代码,或者说功能,究竟应该放到数据层呢,还是应该放到逻辑层?
HeapPriorityQueue.java:
package com.zy.heappriorityqueue; public class HeapPriorityQueue { private Heap heap; public HeapPriorityQueue(int queueSize) { heap = new Heap(queueSize); } //得到最大值 public int heapMaximum() { return heap.getValue(0); } //取出最大值,相当于pop,原最大值结点被删除 public int heapExtractMax() { return heap.popMax(); } //将第i个结点的值增加x public boolean heapIncreaseKey(int i, int x) { if(i>heap.getHeapSize()-1) { System.out.println("overflow"); return false; } else if(heap.getValue(i)>x){ System.out.println("new key is smaller than current key"); return true; } else { heap.setValue(i, x); //保持最大堆的性质 while(i>0&&heap.getValue(heap.parent(i))<heap.getValue(i)) { int temp = heap.getValue(i); heap.setValue(i, heap.getValue(heap.parent(i))); heap.setValue(heap.parent(i), temp); i = heap.parent(i); } return true; } } //向队列中增加一个元素 public void maxHeapInsert(int value) { heap.addElement(value); } }
底层的Heap数据结构 Heap.java
package com.zy.heappriorityqueue; public class Heap { private int[] data; private int heapSize; //堆的大小,表示当前堆中有多少个元素 //新建一个堆,容量为size public Heap(int size) { data = new int[size]; heapSize = 0; } //取得结点i的父结点 public int parent(int i) { return (i-1)/2; } //取得结点i的左孩子 public int left(int i) { return 2*i+1; } //取得结点i的右孩子 public int right(int i) { return 2*i + 2; } //让i结点及其子结点保持最大堆的性质 public void maxHeapity(int i) { int l = left(i); int r = right(i); int largest = i; //取得{结点i,i的左孩子,i的右孩子}三者当中的最大值的下标,赋给largest if(l<heapSize&&data[l]>data[i]) { largest = l; } if(r<heapSize&&data[r]>data[largest]) { largest = r; } //如果largest不等于i,则将i与largest两者的值交换,以保持最大堆的性质 if(largest!=i) { int temp = data[i]; data[i] = data[largest]; data[largest] = temp; maxHeapity(largest); //同时递归处理largest结点. } } //返回堆的大小,即当前堆中有多少个元素 public int getHeapSize() { return heapSize; } //返回第i个结点的值 public int getValue(int i) { return data[i]; } //设置第i个结点的值 public void setValue(int i, int x) { data[i] = x; } //增加一个结点 public void addElement(int value) { // TODO Auto-generated method stub if(heapSize>data.length) { System.out.println("overflow"); System.exit(-1); } else { data[heapSize-1] = value; int i = heapSize -1; //保持最大堆的性质 while(i>0&&getValue(parent(i))<getValue(i)) { int temp = getValue(i); setValue(i, getValue(parent(i))); setValue(parent(i), temp); i = parent(i); } } } //取出最大值,相当于pop,原最大值结点被删除 public int popMax() { // TODO Auto-generated method stub if(heapSize<1) { System.out.println("heap underflow"); return Integer.MIN_VALUE; } else { int max = data[0]; data[0] = data[heapSize-1]; maxHeapity(0); heapSize--; return max; } } }