/** * extract minimum from the heap. * * <p>minor differences from Cormen et al. pseudocode are present. * * @return */ public HeapNode extractMin() { int sentinel = DoubleLinkedCircularList.sentinelKey; HeapNode z = minimumNode; if (z != null) { // detach each child and add it to heap HeapNode x = z.getChildren().getSentinel().getRight(); // for each child x of z while (x.getKey() != sentinel) { HeapNode next = x.getRight(); rootList.insert(x); x = next; } rootList.remove(z); if (z.getRight().getKey() == z.getKey()) { minimumNode = null; } else { minimumNode = z.getRight(); consolidate(); } n--; } return z; }
/** * a depth first search of all nodes (that is, it descends all children of a node before * proceeding to the next in the current doubly linked circular list). * * @param key * @return */ HeapNode search(long key) { HeapNode node = rootList.getSentinel().getRight(); int sentinel = DoubleLinkedCircularList.sentinelKey; Stack<HeapNode> stack = new Stack<HeapNode>(); while (!stack.isEmpty() || (node.getKey() != sentinel)) { if (node.getKey() != sentinel) { stack.push(node); node = node.getRight(); } else { node = stack.pop(); // System.out.println(node.key); if (node.getKey() == key) { return node; } node = node.getChildren().getSentinel().getRight(); } } return null; }
/** * decrease key for node x * * <p>runtime is O(1) * * @param x * @param decreaseToThisKey */ public void decreaseKey(HeapNode x, long decreaseToThisKey) { if (decreaseToThisKey > x.getKey()) { throw new IllegalArgumentException("key cannot be larger than x.key"); } x.setKey(decreaseToThisKey); HeapNode y = x.getParent(); if ((y != null) && (x.getKey() < y.getKey())) { cut(x, y); cascadingCut(y); } if (x.getKey() < minimumNode.getKey()) { minimumNode = x; } }
protected void printRootList() { StringBuffer sb = new StringBuffer(); HeapNode t = this.rootList.getSentinel().getRight(); while (t.getKey() != DoubleLinkedCircularList.sentinelKey) { if ((minimumNode == null) || (t.getKey() < minimumNode.getKey())) { minimumNode = t; } String str = String.format("%d", t.getKey()); if (sb.length() > 0) { sb.append(" "); } sb.append(str); t = t.getRight(); } sb.insert(0, "Looking for " + minimumNode + " :"); log.info(sb.toString()); }
/** * insert node into heap. runtime is O(1). makes no attempt to consolidate tree. * * @param node */ public void insert(HeapNode node) { if (node.getKey() == DoubleLinkedCircularList.noValue) { throw new IllegalArgumentException("node.key must be set before insert into heap"); } node.setNumberOfChildren(0); node.setParent(null); node.removeChildren(); node.setLeft(node); node.setRight(node); node.setMark(false); // concatenate root list containing node with this.rootList rootList.insert(node); if ((minimumNode == null) || (node.getKey() < minimumNode.getKey())) { minimumNode = node; } n++; }
void consolidate() { // D[n] = max degree of any node = lg_2(n) = lg_2(Integer.MAX) = 31 // int maxDegree = (int) (Math.log(this.n)/Math.log(2)); int maxDegree = 31; HeapNode[] a = new HeapNode[maxDegree]; HeapNode w = rootList.getSentinel().getRight(); // n*m*(constants) while (w.getKey() != DoubleLinkedCircularList.sentinelKey) { HeapNode x = w; // because the x.right gets changed in link(), nab the next // reference before link HeapNode next = w.getRight(); int d = x.getNumberOfChildren(); // is there another node of the same degree, that is, has the // same number of children? while ((d < a.length) && (a[d] != null)) { HeapNode y = a[d]; if (x.getKey() > y.getKey()) { HeapNode tmp = x; x = y; y = tmp; } // link removes y (which has a key larger than x now) from // rootList and adds it as a child of x link(y, x); a[d] = null; d++; } if (d < a.length) { a[d] = x; } else { throw new IllegalStateException("maxDegree=" + maxDegree + " but d is " + d); } w = next; } minimumNode = null; for (int i = 0; i < a.length; i++) { if (a[i] != null) { rootList.remove(a[i]); rootList.insert(a[i]); // not changing the minimumNode because the rootList content // has not changed, so the minimum in that has not changed if ((minimumNode == null) || (a[i].getKey() < minimumNode.getKey())) { minimumNode = a[i]; } } } }