package com.e2u.util; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * A heap is usually used as Priority-Queue. Etheir max-heap or min-heap * @param <E> */ public class Heap<E extends Comparable<E>> { private ArrayList<E> heapData = null; private boolean isMinHeap; public Heap(List<? extends E> initData, boolean minHeap) { heapData = new ArrayList<E>(initData.size()); isMinHeap = minHeap; heapData.addAll(initData); initHeap(); } public Heap(List<? extends E> initData) { this(initData, true); } private void initHeap() { for(int i = size() / 2 - 1; i >= 0; i--) { shiftDown(i); } } public int size() { return heapData.size(); } public boolean isLeaf(int pos) { return pos > (size() / 2 - 1); } public int leftChild(int pos) { return pos * 2 + 1; } public int rightChild(int pos) { return pos * 2 + 2; } public void shiftUp(int pos) { if(pos <= 0) { return; } int parent = (pos + 1) / 2 - 1; //has parent while(parent >= 0) { //parent is bigger than child, do nothing if(compare(heapData.get(parent), heapData.get(pos)) >= 0) { break; } Collections.swap(heapData, parent, pos); pos = parent; parent = (pos + 1) / 2 - 1; } } public void shiftDown(int pos) { int c = pos * 2 + 1; while(c < size()) { if(c < size() - 1 && compare(heapData.get(c), heapData.get(c + 1)) < 0) { c++; } if(compare(heapData.get(pos), heapData.get(c)) >= 0) { break; } Collections.swap(heapData, pos, c); pos = c; c = pos * 2 + 1; } } private int compare(E e1, E e2) { int result = e1.compareTo(e2); if(isMinHeap) { result = -result; } return result; } /** * Peek the heap-top element. * @return */ public E peek() { if(size() <= 0) { return null; } return heapData.get(0); } /** * Get the heap-top element and remove it. * @return */ public E remove() { if(size() <= 0) { return null; } if(size() == 1) { return heapData.remove(0); } E result = heapData.get(0); Collections.swap(heapData, 0, size() - 1); heapData.remove(size() - 1); shiftDown(0); return result; } /** * Insert an new element to the heap * @param e */ public void insert(E e) { heapData.add(e); shiftUp(size() - 1); } /** * Unit Test * @param args */ public static void main(String[] args) { List<Integer> list = new java.util.ArrayList<Integer>(); int data[] = {49, 38, 65, 97, 76, 13, 27, 49}; for(int i = 0; i < data.length; i++) { list.add(data[i]); } Heap<Integer> hp = new Heap<Integer>(list, true); int x, y, z; while(hp.size() > 1) { x = hp.remove(); y = hp.remove(); System.out.println("Remove: " + x + ", " + y); z = x + y; hp.insert(z); System.out.println("Insert: " + z); } if(hp.size() == 1) { System.out.println("Last: " + hp.remove()); } //Re-init with max-heap hp = new Heap<Integer>(list, false); while(hp.size() > 0) { x = hp.remove(); System.out.println("Remove: " + x); } } }