Mega Code Archive

 
Categories / Java / Collections Data Structure
 

Fibonacci heap data structure

/*   * JGraphT : a free Java graph-theory library  *   *  * Project Info:  http://jgrapht.sourceforge.net/  * Project Creator:  Barak Naveh (barak_naveh@users.sourceforge.net)  *  * (C) Copyright 2003-2007, by Barak Naveh and Contributors.  *  * This library is free software; you can redistribute it and/or modify it  * under the terms of the GNU Lesser General Public License as published by  * the Free Software Foundation; either version 2.1 of the License, or  * (at your option) any later version.  *  * This library is distributed in the hope that it will be useful, but  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public  * License for more details.  *  * You should have received a copy of the GNU Lesser General Public License  * along with this library; if not, write to the Free Software Foundation,  * Inc.,  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.  */ /* --------------------------  * FibonnaciHeap.java  * --------------------------  * (C) Copyright 1999-2003, by Nathan Fiedler and Contributors.  *  * Original Author:  Nathan Fiedler  * Contributor(s):   John V. Sichi  *  * $Id: FibonacciHeap.java 603 2008-06-28 07:51:50Z perfecthash $  *  * Changes  * -------  * 03-Sept-2003 : Adapted from Nathan Fiedler (JVS);  *  *      Name    Date            Description  *      ----    ----            -----------  *      nf      08/31/97        Initial version  *      nf      09/07/97        Removed FibHeapData interface  *      nf      01/20/01        Added synchronization  *      nf      01/21/01        Made Node an inner class  *      nf      01/05/02        Added clear(), renamed empty() to  *                              isEmpty(), and renamed printHeap()  *                              to toString()  *      nf      01/06/02        Removed all synchronization  *  */ import java.util.*; /**  * This class implements a Fibonacci heap data structure. Much of the code in  * this class is based on the algorithms in the "Introduction to Algorithms"by  * Cormen, Leiserson, and Rivest in Chapter 21. The amortized running time of  * most of these methods is O(1), making it a very fast data structure. Several  * have an actual running time of O(1). removeMin() and delete() have O(log n)  * amortized running times because they do the heap consolidation. If you  * attempt to store nodes in this heap with key values of -Infinity  * (Double.NEGATIVE_INFINITY) the <code>delete()</code> operation may fail to  * remove the correct element.  *  * <p><b>Note that this implementation is not synchronized.</b> If multiple  * threads access a set concurrently, and at least one of the threads modifies  * the set, it <i>must</i> be synchronized externally. This is typically  * accomplished by synchronizing on some object that naturally encapsulates the  * set.</p>  *  * <p>This class was originally developed by Nathan Fiedler for the GraphMaker  * project. It was imported to JGraphT with permission, courtesy of Nathan  * Fiedler.</p>  *  * @author Nathan Fiedler  */ public class FibonacciHeap<T> {     //~ Static fields/initializers ---------------------------------------------     private static final double oneOverLogPhi =         1.0 / Math.log((1.0 + Math.sqrt(5.0)) / 2.0);     //~ Instance fields --------------------------------------------------------     /**      * Points to the minimum node in the heap.      */     private FibonacciHeapNode<T> minNode;     /**      * Number of nodes in the heap.      */     private int nNodes;     //~ Constructors -----------------------------------------------------------     /**      * Constructs a FibonacciHeap object that contains no elements.      */     public FibonacciHeap()     {     } // FibonacciHeap     //~ Methods ----------------------------------------------------------------     /**      * Tests if the Fibonacci heap is empty or not. Returns true if the heap is      * empty, false otherwise.      *      * <p>Running time: O(1) actual</p>      *      * @return true if the heap is empty, false otherwise      */     public boolean isEmpty()     {         return minNode == null;     }     // isEmpty     /**      * Removes all elements from this heap.      */     public void clear()     {         minNode = null;         nNodes = 0;     }     // clear     /**      * Decreases the key value for a heap node, given the new value to take on.      * The structure of the heap may be changed and will not be consolidated.      *      * <p>Running time: O(1) amortized</p>      *      * @param x node to decrease the key of      * @param k new key value for node x      *      * @exception IllegalArgumentException Thrown if k is larger than x.key      * value.      */     public void decreaseKey(FibonacciHeapNode<T> x, double k)     {         if (k > x.key) {             throw new IllegalArgumentException(                 "decreaseKey() got larger key value");         }         x.key = k;         FibonacciHeapNode<T> y = x.parent;         if ((y != null) && (x.key < y.key)) {             cut(x, y);             cascadingCut(y);         }         if (x.key < minNode.key) {             minNode = x;         }     }     // decreaseKey     /**      * Deletes a node from the heap given the reference to the node. The trees      * in the heap will be consolidated, if necessary. This operation may fail      * to remove the correct element if there are nodes with key value      * -Infinity.      *      * <p>Running time: O(log n) amortized</p>      *      * @param x node to remove from heap      */     public void delete(FibonacciHeapNode<T> x)     {         // make x as small as possible         decreaseKey(x, Double.NEGATIVE_INFINITY);         // remove the smallest, which decreases n also         removeMin();     }     // delete     /**      * Inserts a new data element into the heap. No heap consolidation is      * performed at this time, the new node is simply inserted into the root      * list of this heap.      *      * <p>Running time: O(1) actual</p>      *      * @param node new node to insert into heap      * @param key key value associated with data object      */     public void insert(FibonacciHeapNode<T> node, double key)     {         node.key = key;         // concatenate node into min list         if (minNode != null) {             node.left = minNode;             node.right = minNode.right;             minNode.right = node;             node.right.left = node;             if (key < minNode.key) {                 minNode = node;             }         } else {             minNode = node;         }         nNodes++;     }     // insert     /**      * Returns the smallest element in the heap. This smallest element is the      * one with the minimum key value.      *      * <p>Running time: O(1) actual</p>      *      * @return heap node with the smallest key      */     public FibonacciHeapNode<T> min()     {         return minNode;     }     // min     /**      * Removes the smallest element from the heap. This will cause the trees in      * the heap to be consolidated, if necessary.      *      * <p>Running time: O(log n) amortized</p>      *      * @return node with the smallest key      */     public FibonacciHeapNode<T> removeMin()     {         FibonacciHeapNode<T> z = minNode;         if (z != null) {             int numKids = z.degree;             FibonacciHeapNode<T> x = z.child;             FibonacciHeapNode<T> tempRight;             // for each child of z do...             while (numKids > 0) {                 tempRight = x.right;                 // remove x from child list                 x.left.right = x.right;                 x.right.left = x.left;                 // add x to root list of heap                 x.left = minNode;                 x.right = minNode.right;                 minNode.right = x;                 x.right.left = x;                 // set parent[x] to null                 x.parent = null;                 x = tempRight;                 numKids--;             }             // remove z from root list of heap             z.left.right = z.right;             z.right.left = z.left;             if (z == z.right) {                 minNode = null;             } else {                 minNode = z.right;                 consolidate();             }             // decrement size of heap             nNodes--;         }         return z;     }     // removeMin     /**      * Returns the size of the heap which is measured in the number of elements      * contained in the heap.      *      * <p>Running time: O(1) actual</p>      *      * @return number of elements in the heap      */     public int size()     {         return nNodes;     }     // size     /**      * Joins two Fibonacci heaps into a new one. No heap consolidation is      * performed at this time. The two root lists are simply joined together.      *      * <p>Running time: O(1) actual</p>      *      * @param h1 first heap      * @param h2 second heap      *      * @return new heap containing h1 and h2      */     public static <T> FibonacciHeap<T> union(         FibonacciHeap<T> h1,         FibonacciHeap<T> h2)     {         FibonacciHeap<T> h = new FibonacciHeap<T>();         if ((h1 != null) && (h2 != null)) {             h.minNode = h1.minNode;             if (h.minNode != null) {                 if (h2.minNode != null) {                     h.minNode.right.left = h2.minNode.left;                     h2.minNode.left.right = h.minNode.right;                     h.minNode.right = h2.minNode;                     h2.minNode.left = h.minNode;                     if (h2.minNode.key < h1.minNode.key) {                         h.minNode = h2.minNode;                     }                 }             } else {                 h.minNode = h2.minNode;             }             h.nNodes = h1.nNodes + h2.nNodes;         }         return h;     }     // union     /**      * Creates a String representation of this Fibonacci heap.      *      * @return String of this.      */     public String toString()     {         if (minNode == null) {             return "FibonacciHeap=[]";         }         // create a new stack and put root on it         Stack<FibonacciHeapNode<T>> stack = new Stack<FibonacciHeapNode<T>>();         stack.push(minNode);         StringBuffer buf = new StringBuffer(512);         buf.append("FibonacciHeap=[");         // do a simple breadth-first traversal on the tree         while (!stack.empty()) {             FibonacciHeapNode<T> curr = stack.pop();             buf.append(curr);             buf.append(", ");             if (curr.child != null) {                 stack.push(curr.child);             }             FibonacciHeapNode<T> start = curr;             curr = curr.right;             while (curr != start) {                 buf.append(curr);                 buf.append(", ");                 if (curr.child != null) {                     stack.push(curr.child);                 }                 curr = curr.right;             }         }         buf.append(']');         return buf.toString();     }     // toString     /**      * Performs a cascading cut operation. This cuts y from its parent and then      * does the same for its parent, and so on up the tree.      *      * <p>Running time: O(log n); O(1) excluding the recursion</p>      *      * @param y node to perform cascading cut on      */     protected void cascadingCut(FibonacciHeapNode<T> y)     {         FibonacciHeapNode<T> z = y.parent;         // if there's a parent...         if (z != null) {             // if y is unmarked, set it marked             if (!y.mark) {                 y.mark = true;             } else {                 // it's marked, cut it from parent                 cut(y, z);                 // cut its parent as well                 cascadingCut(z);             }         }     }     // cascadingCut     protected void consolidate()     {         int arraySize =             ((int) Math.floor(Math.log(nNodes) * oneOverLogPhi)) + 1;         List<FibonacciHeapNode<T>> array =             new ArrayList<FibonacciHeapNode<T>>(arraySize);         // Initialize degree array         for (int i = 0; i < arraySize; i++) {             array.add(null);         }         // Find the number of root nodes.         int numRoots = 0;         FibonacciHeapNode<T> x = minNode;         if (x != null) {             numRoots++;             x = x.right;             while (x != minNode) {                 numRoots++;                 x = x.right;             }         }         // For each node in root list do...         while (numRoots > 0) {             // Access this node's degree..             int d = x.degree;             FibonacciHeapNode<T> next = x.right;             // ..and see if there's another of the same degree.             for (;;) {                 FibonacciHeapNode<T> y = array.get(d);                 if (y == null) {                     // Nope.                     break;                 }                 // There is, make one of the nodes a child of the other.                 // Do this based on the key value.                 if (x.key > y.key) {                     FibonacciHeapNode<T> temp = y;                     y = x;                     x = temp;                 }                 // FibonacciHeapNode<T> y disappears from root list.                 link(y, x);                 // We've handled this degree, go to next one.                 array.set(d, null);                 d++;             }             // Save this node for later when we might encounter another             // of the same degree.             array.set(d, x);             // Move forward through list.             x = next;             numRoots--;         }         // Set min to null (effectively losing the root list) and         // reconstruct the root list from the array entries in array[].         minNode = null;         for (int i = 0; i < arraySize; i++) {             FibonacciHeapNode<T> y = array.get(i);             if (y == null) {                 continue;             }             // We've got a live one, add it to root list.             if (minNode != null) {                 // First remove node from root list.                 y.left.right = y.right;                 y.right.left = y.left;                 // Now add to root list, again.                 y.left = minNode;                 y.right = minNode.right;                 minNode.right = y;                 y.right.left = y;                 // Check if this is a new min.                 if (y.key < minNode.key) {                     minNode = y;                 }             } else {                 minNode = y;             }         }     }     // consolidate     /**      * The reverse of the link operation: removes x from the child list of y.      * This method assumes that min is non-null.      *      * <p>Running time: O(1)</p>      *      * @param x child of y to be removed from y's child list      * @param y parent of x about to lose a child      */     protected void cut(FibonacciHeapNode<T> x, FibonacciHeapNode<T> y)     {         // remove x from childlist of y and decrement degree[y]         x.left.right = x.right;         x.right.left = x.left;         y.degree--;         // reset y.child if necessary         if (y.child == x) {             y.child = x.right;         }         if (y.degree == 0) {             y.child = null;         }         // add x to root list of heap         x.left = minNode;         x.right = minNode.right;         minNode.right = x;         x.right.left = x;         // set parent[x] to nil         x.parent = null;         // set mark[x] to false         x.mark = false;     }     // cut     /**      * Make node y a child of node x.      *      * <p>Running time: O(1) actual</p>      *      * @param y node to become child      * @param x node to become parent      */     protected void link(FibonacciHeapNode<T> y, FibonacciHeapNode<T> x)     {         // remove y from root list of heap         y.left.right = y.right;         y.right.left = y.left;         // make y a child of x         y.parent = x;         if (x.child == null) {             x.child = y;             y.right = y;             y.left = y;         } else {             y.left = x.child;             y.right = x.child.right;             x.child.right = y;             y.right.left = y;         }         // increase degree[x]         x.degree++;         // set mark[y] false         y.mark = false;     }     // link } // FibonacciHeap /*   * JGraphT : a free Java graph-theory library  *   *  * Project Info:  http://jgrapht.sourceforge.net/  * Project Creator:  Barak Naveh (barak_naveh@users.sourceforge.net)  *  * (C) Copyright 2003-2007, by Barak Naveh and Contributors.  *  * This library is free software; you can redistribute it and/or modify it  * under the terms of the GNU Lesser General Public License as published by  * the Free Software Foundation; either version 2.1 of the License, or  * (at your option) any later version.  *  * This library is distributed in the hope that it will be useful, but  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public  * License for more details.  *  * You should have received a copy of the GNU Lesser General Public License  * along with this library; if not, write to the Free Software Foundation,  * Inc.,  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.  */ /* --------------------------  * FibonnaciHeapNode.java  * --------------------------  * (C) Copyright 1999-2007, by Nathan Fiedler and Contributors.  *  * Original Author:  Nathan Fiedler  * Contributor(s):   John V. Sichi  *  * $Id: FibonacciHeapNode.java 568 2007-09-30 00:12:18Z perfecthash $  *  * Changes  * -------  * 03-Sept-2003 : Adapted from Nathan Fiedler (JVS);  *  *      Name    Date            Description  *      ----    ----            -----------  *      nf      08/31/97        Initial version  *      nf      09/07/97        Removed FibHeapData interface  *      nf      01/20/01        Added synchronization  *      nf      01/21/01        Made Node an inner class  *      nf      01/05/02        Added clear(), renamed empty() to  *                              isEmpty(), and renamed printHeap()  *                              to toString()  *      nf      01/06/02        Removed all synchronization  *      JVS     06/24/06        Generics  *  */ /**  * Implements a node of the Fibonacci heap. It holds the information necessary  * for maintaining the structure of the heap. It also holds the reference to the  * key value (which is used to determine the heap structure).  *  * @author Nathan Fiedler  */ class FibonacciHeapNode<T> {     //~ Instance fields --------------------------------------------------------     /**      * Node data.      */     T data;     /**      * first child node      */     FibonacciHeapNode<T> child;     /**      * left sibling node      */     FibonacciHeapNode<T> left;     /**      * parent node      */     FibonacciHeapNode<T> parent;     /**      * right sibling node      */     FibonacciHeapNode<T> right;     /**      * true if this node has had a child removed since this node was added to      * its parent      */     boolean mark;     /**      * key value for this node      */     double key;     /**      * number of children of this node (does not count grandchildren)      */     int degree;     //~ Constructors -----------------------------------------------------------     /**      * Default constructor. Initializes the right and left pointers, making this      * a circular doubly-linked list.      *      * @param data data for this node      * @param key initial key for node      */     public FibonacciHeapNode(T data, double key)     {         right = this;         left = this;         this.data = data;         this.key = key;     }     //~ Methods ----------------------------------------------------------------     /**      * Obtain the key for this node.      *      * @return the key      */     public final double getKey()     {         return key;     }     /**      * Obtain the data for this node.      */     public final T getData()     {         return data;     }     /**      * Return the string representation of this object.      *      * @return string representing this object      */     public String toString()     {         if (true) {             return Double.toString(key);         } else {             StringBuffer buf = new StringBuffer();             buf.append("Node=[parent = ");             if (parent != null) {                 buf.append(Double.toString(parent.key));             } else {                 buf.append("---");             }             buf.append(", key = ");             buf.append(Double.toString(key));             buf.append(", degree = ");             buf.append(Integer.toString(degree));             buf.append(", right = ");             if (right != null) {                 buf.append(Double.toString(right.key));             } else {                 buf.append("---");             }             buf.append(", left = ");             if (left != null) {                 buf.append(Double.toString(left.key));             } else {                 buf.append("---");             }             buf.append(", child = ");             if (child != null) {                 buf.append(Double.toString(child.key));             } else {                 buf.append("---");             }             buf.append(']');             return buf.toString();         }     }     // toString } // End FibonacciHeapNode.java