import java.util.*; import java.io.*; class Heap implements SeqStructure { protected TreeCell t; protected TreeCell finger;//a cursor into the data structure protected TreeCell previous;//previous is one step behind finger protected int size; protected int nComparisons; public Heap() { t = null; size = 0; nComparisons = 0; } public String toString() { return "Tree has " + size + " elements:" + t; } public int numComparisons() { return nComparisons; } public boolean isEmpty() { return size == 0; } public int size() { return this.size; } public Object get() { //check for empty heap if (isEmpty()) { System.out.println("Attempt to get from empty heap"); return null; } //extract the maximum guy Comparable max = (Comparable)(t.getDatum()); //if empty tree remains after deletion, update is easy if (size == 1) { t = null; size = 0; return max; } //non-empty tree will remain after deletion of root //move down the tree to PARENT of node whose number is size //easy to show that number of this parent node is size/2 heapDecoder d = new heapDecoder(size/2, 2); finger = t; while (d.hasMoreDigits()) if (d.getNextDigit() == 0) finger = finger.getLeft(); else finger = finger.getRight(); //set root value to value in node whose number is size //delete node whose number is size if (size%2 == 0) { //left child t.setDatum(finger.getLeft().getDatum()); finger.setLeft(null); } else { t.setDatum(finger.getRight().getDatum()); finger.setRight(null); } //now walk down the tree from the root restoring the heap property TreeCell dNode = t; //the disturbed node TreeCell cNode; //max child of dNode while (true) { //check the left and right children for heap property TreeCell l = dNode.getLeft(); TreeCell r = dNode.getRight(); //find the max kid if (l == null) break; //d must be a leaf node if (r == null) cNode = l; else {//dNode has two children if (((Comparable)l.getDatum()).compareTo(r.getDatum()) < 0) cNode = r; else cNode = l; nComparisons++; } //swap maxkid with parent maybe? nComparisons++; if (((Comparable)dNode.getDatum()).compareTo(cNode.getDatum()) < 0) { //swap parent and child data fields and update dNode Object o = dNode.getDatum(); dNode.setDatum(cNode.getDatum()); cNode.setDatum(o); dNode = cNode; } else //no need to go further down heap break; } size = size - 1; return max; } public void put(Object o) { Comparable p = (Comparable)o; size = size + 1; if (t == null) { t = new TreeCell(p); return; } //otherwise move down the tree to parent of node whose number is size //along the way, compare values to maintain heap property heapDecoder d = new heapDecoder(size/2,2); finger = t; while (true) { if (p.compareTo(finger.getDatum()) > 0) { //swap Comparable temp = (Comparable) finger.getDatum(); finger.setDatum(p); p = temp; } nComparisons++; if (! d.hasMoreDigits()) { TreeCell n = new TreeCell(p); if (size%2 == 0) //set left finger.setLeft(n); else finger.setRight(n); break; } else { if (d.getNextDigit() == 0) //go left finger = finger.getLeft(); else //go right finger = finger.getRight(); } } } //inner class that implements an iterator for translating heap position numbers //into paths down the tree from root to that position //base will usually be 2 (binary heaps) but it can be set arbitrarily //for more general n-ary heaps. cursor points to bit/digit position to be returned //next. For example, consider a binary heap and the position 6 = 110 in binary. //cursor will be set to 1 by the constructor. The first call to getNextDigit //will return 1 and decrement this cursor to 0, and the next call after that will //return 0. protected class heapDecoder { protected int position; protected int base; protected int cursor; public heapDecoder(int pos, int base){ position = pos; this.base = base; cursor = (int)(Math.log(pos)/Math.log(base)) - 1; } public int getNextDigit() { return (int)(position/Math.pow(base,cursor--)) % base ; } public boolean hasMoreDigits() { return (cursor >= 0); } } //This method tests if a TreeCell t is the root of a heap public static boolean isHeap(TreeCell t) { if (t == null) return true; boolean OK = isHeap(t.getLeft()) && isHeap(t.getRight()); Comparable datum = (Comparable)(t.getDatum()); if (t.getLeft() != null) OK = (datum.compareTo(t.getLeft().getDatum()) >= 0) && OK; if (t.getRight() != null) OK = (datum.compareTo(t.getRight().getDatum()) >= 0) && OK; return OK; } } class testHeapSort { public static void main(String[] args) { TreeCell t = null; System.out.println(Heap.isHeap(t)); t = new TreeCell(new Integer(7)); System.out.println(Heap.isHeap(t)); t.setLeft(new TreeCell(new Integer (8))); System.out.println(Heap.isHeap(t)); t.setLeft(new TreeCell(new Integer (6))); System.out.println(Heap.isHeap(t)); Integer[] ar = new Integer[6]; ar[0] = new Integer(4); ar[1] = new Integer(3); ar[2] = new Integer(8); ar[3] = new Integer(7); ar[4] = new Integer(2); ar[5] = new Integer(9); printArray(ar); int nC = heapSort(ar); printArray(ar); System.out.println("Number of Comparisons:" + nC); //create a random array Random rand = new Random(); ar = new Integer[30]; for (int i = 0; i < ar.length; i++) ar[i] = new Integer((int) (rand.nextFloat() * ar.length) + 1); printArray(ar); nC = heapSort(ar); printArray(ar); System.out.println("Number of Comparisons:" + nC); } public static int heapSort(Object[] ar) { //create a heap Heap uriah = new Heap(); for (int i = 0; i < ar.length; i++) uriah.put(ar[i]); System.out.println("Number of comparisons for put:" + uriah.numComparisons()); for (int i = 0; i< ar.length; i++) { ar[i] = uriah.get(); System.out.println("Number of comparisons:" + uriah.numComparisons()); } return uriah.numComparisons(); } public static void printArray(Object[] foo) { for (int i = 0; i < foo.length; i++) System.out.print (foo[i] + " "); System.out.println(); } }