Java数据结构之堆结构,基于泛型类中泛型数组的创建
首先创建Node类型作为堆的元素类型
class Node{ public int nod; public int value; public Node(int nod, int value) { this.nod = nod; this.value = value; } public String toString() { return ""+value; } }
堆结构的元素必须能够比较,定义Node类的比较器
class NodeComparator implements Comparator<Node>{ @Override public int compare(Node o1, Node o2) { return o1.value - o2.value; } }
首先明确,在Java里面要创建泛型数组需要借助import java.lang.reflect.Array;
创建类HeapExample1,其构造函数之一为:
@SuppressWarnings("unchecked") public HeapExamples1(Class<T> type, boolean minheap, Comparator<T> cmpr) { this.minheap = minheap; this.heap = (T[]) Array.newInstance(type, DEFAULT_CAPACITY); this.cmpr = cmpr; }
其中this.heap是T[]类型,创建泛型数组的方法是(T[]) Array.newInstance(type, DEFAULT_CAPACITY);
其中type应为Node.class,DEFAULT_CAPACIT是数组长度。事实上这句话的意思就是this.heap = new T[DEFAULT_CAPACITY];然而这么做是会报错的,Java不允许通过new关键字创建泛型数组,具体原因可以百度。
不过数组长度不代表数组的元素个数,数组长度是底层数组长度,如果不够需要扩容,而元素个数为private int heapLength;。和栈结构类同,除了确定长度的底层数组之外(如果不够再扩容),还定义了栈指针表示栈的高度,用于判断是否为空,或者是否溢出。
堆结构的基本操作为插入,删除,返回元素个数,判断是否为空。还有自上而下调整和自下而上调整。插入和删除的过程中,通过调整操作来保证堆结构始终有序,事实上堆结构也是优先队列的基础。
堆结构的完整代码为:
public class HeapExamples1<T> { private boolean minheap; private T[] heap; private Comparator<T> cmpr; private int heapLength; private int DEFAULT_CAPACITY = 0x10; // 默认容量16 @SuppressWarnings("unchecked") public HeapExamples1(Class<T> type, boolean minheap, Comparator<T> cmpr) { this.minheap = minheap; this.heap = (T[]) Array.newInstance(type, DEFAULT_CAPACITY); this.cmpr = cmpr; } public HeapExamples1(Class<T> type, boolean minheap) { this(type, minheap, null); } public HeapExamples1(Class<T> type) { this(type, true, null); } public HeapExamples1(Class<T> type, boolean minheap, T[]values, Comparator<T> cmpr) { this(type, minheap, cmpr); for (int i = 0; i < values.length; i++) { this.insert(values[i]); // this.printHeap(); } } public boolean isEmpty() { return this.heapLength == 0; } public int size() { return this.heapLength; } public void printHeap(){ for (int i = 0; i < heapLength; i++) { System.out.print(heap[i].toString()+", "); } System.out.println("\n"); } public void insert(T x) { this.heap[this.heapLength++] = x; for (int i = this.heapLength/2-1;i>0; i = (i-1)/2) shif(i); shif(0); } @SuppressWarnings("unchecked") public void shif(int parent) { //Page289 int end = this.size() - 1; int child = 2 * parent + 1; T value = this.heap[parent]; while (child <= end) { int comp = 0; if (child < end) { T left = this.heap[child], right = this.heap[child+1]; if (this.cmpr == null) comp = ((Comparable<T>)left).compareTo(right); else comp = this.cmpr.compare(left, right); if(this.minheap ? comp>0 : comp<0) child++; } if (this.cmpr==null) comp = ((Comparable<T>)value).compareTo(this.heap[child]); else comp = this.cmpr.compare(value, this.heap[child]); if (this.minheap ? comp>0 : comp<0) { this.heap[parent] = this.heap[child]; parent = child; child = 2*parent+1; }else { break; } } this.heap[parent] = value; } public T removeRoot() { //Page290 if (this.isEmpty()) return null; T x = (T)this.heap[0]; this.heap[0] = this.heap[this.heapLength-1]; this.heap[this.heapLength-1] = null; this.heapLength--; if(this.heapLength>1) shif(0); return x; } public static void main(String[] args) { Node[] nodes = {new Node(0, 3),new Node(1,44),new Node(2,38),new Node(4,47),new Node(5,15), new Node(6,36), new Node(8,27), new Node(7,26),new Node(9,2)}; System.out.println("大顶堆"); HeapExamples1<Node> pq = new HeapExamples1<Node>(Node.class, true, nodes, new NodeComparator()); System.out.println("堆的内容:"); pq.printHeap(); System.out.println("按顺序输出:"); while (!pq.isEmpty()) { Node temp = pq.removeRoot(); System.out.println("(value:"+temp.value+", nod:"+temp.nod+")"); } } }
结果:
大顶堆
堆的内容:
2, 3, 27, 15, 44, 38, 36, 47, 26,
按顺序输出:
(value:2, 9)
(value:3, 0)
(value:15, 5)
(value:26, 7)
(value:27, 8)
(value:36, 6)
(value:38, 2)
(value:44, 1)
(value:47, 4)