001
002
003//@license@
004package cnslab.cnsmath;
005
006/**
007 * Copyright 2005 The Apache Software Foundation
008 *
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *     http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 */
021
022import java.util.HashMap;
023
024/**
025 * A Fibonacci Heap, as described in <i>Introduction to Algorithms</i> by
026 * Charles E. Leiserson, Thomas H. Cormen, Ronald L. Rivest.
027 * <p/>
028 * <p/>
029 * <p/>
030 * A Fibonacci heap is a very efficient data structure for priority
031 * queuing.
032 */
033public class FibonacciHeap<T2 extends Comparable<T2>> {
034
035  private FibonacciHeapNode<T2> m_MinNode;
036 // private HashMap<T2, FibonacciHeapNode<T2>> m_ItemsToNodes;
037  private int size;
038
039
040  /**
041   * Creates a new <code>FibonacciHeap</code>.
042   */
043  public FibonacciHeap() {
044    this.m_MinNode = null;
045    this.size=0;
046//    this.m_ItemsToNodes = new HashMap<T2, FibonacciHeapNode<T2> >();
047  }//constructor
048
049  /**
050   * Adds the Object <code>item</code>, with the supplied
051   * <code>priority</code>.
052   *
053   * @param item     the item to be added.
054   * @param priority the priority of the item.
055   */
056  public void add(T2 priority) {
057          size++;
058    FibonacciHeapNode<T2> newNode = new FibonacciHeapNode<T2>(priority);
059
060    if (m_MinNode == null) {
061      m_MinNode = newNode;
062    } else {
063      concatenateSiblings(newNode, m_MinNode);
064      if (newNode.compareTo(m_MinNode) < 0) {
065        m_MinNode = newNode;
066      }
067    }
068  }
069
070  /**
071   * Returns the same Object that {@link #popMin()} would, without
072   * removing it.
073   *
074   * @return the min item without removing it.
075   */
076  public T2 peekMin() {
077    if (m_MinNode == null)
078      return null;
079    return m_MinNode.m_Priority;
080  }//peekMin
081
082  /**
083   * Returns the object which has the <em>lowest</em> priority in the
084   * heap.  If the heap is empty, <code>null</code> is returned.
085   *
086   * @return returns the min item removing it from the heap.
087   */
088  public T2 popMin() {
089    if (m_MinNode == null)
090      return null;
091    if (m_MinNode.m_Child != null) {
092      FibonacciHeapNode<T2> tmp = m_MinNode.m_Child;
093      // rempve m_Parent pointers to m_MinNode
094      while (tmp.m_Parent != null) {
095        tmp.m_Parent = null;
096        tmp = tmp.m_NextSibling;
097      }
098      // add children of m_MinNode to root list
099      concatenateSiblings(tmp, m_MinNode);
100    }
101    // remove m_MinNode from root list
102    FibonacciHeapNode<T2> oldMin = m_MinNode;
103    if (m_MinNode.m_NextSibling == m_MinNode) {
104      m_MinNode = null;
105    } else {
106      m_MinNode = m_MinNode.m_NextSibling;
107      removeFromSiblings(oldMin);
108      consolidate();
109    }
110    size--;
111    return oldMin.m_Priority;
112  }//popMin
113
114  /**
115   * Decreases the <code>priority</code> value associated with
116   * <code>item</code>.
117   * <p/>
118   * <p/>
119   * <p/>
120   * <code>item<code> must exist in the heap, and it's current
121   * priority must be greater than <code>priority</code>.
122   *
123   * @param item     the item.
124   * @param priority the new priority
125   * @throws IllegalStateException if <code>item</code> does not exist
126   *                               in the heap, or if <code>item</code> already has an equal or
127   *                               lower priority than the supplied<code>priority</code>.
128   */
129
130  // makes x's nextSibling and m_PrevSibling point to itself
131  private void removeFromSiblings(FibonacciHeapNode x) {
132    if (x.m_NextSibling == x)
133      return;
134    x.m_NextSibling.m_PrevSibling = x.m_PrevSibling;
135    x.m_PrevSibling.m_NextSibling = x.m_NextSibling;
136    x.m_NextSibling = x;
137    x.m_PrevSibling = x;
138  }//removeFromSiblings
139
140  // joins siblings lists of a and b
141  private void concatenateSiblings(FibonacciHeapNode<T2> a, FibonacciHeapNode<T2> b) {
142    a.m_NextSibling.m_PrevSibling = b;
143    b.m_NextSibling.m_PrevSibling = a;
144    FibonacciHeapNode<T2> origAnext = a.m_NextSibling;
145    a.m_NextSibling = b.m_NextSibling;
146    b.m_NextSibling = origAnext;
147  }//concatenateSiblings
148
149
150  // consolidates heaps of same degree
151  private void consolidate() {
152    FibonacciHeapNode<T2>[] newRoots = new FibonacciHeapNode[size];
153
154    FibonacciHeapNode<T2> node = m_MinNode;
155    FibonacciHeapNode<T2> start = m_MinNode;
156    do {
157      FibonacciHeapNode<T2> x = node;
158      int currDegree = node.degree;
159      while (newRoots[currDegree] != null) {
160        FibonacciHeapNode<T2> y = newRoots[currDegree];
161        if (x.compareTo(y) > 0) {
162          //swap
163          FibonacciHeapNode<T2> tmp = x;
164          x = y;
165          y = tmp;
166        }
167        if (y == start) {
168          start = start.m_NextSibling;
169        }
170        if (y == node) {
171          node = node.m_PrevSibling;
172        }
173        link(y, x);
174        newRoots[currDegree++] = null;
175      }
176      newRoots[currDegree] = x;
177      node = node.m_NextSibling;
178    } while (node != start);
179
180    m_MinNode = null;
181    for (int i = 0; i < newRoots.length; i++)
182      if (newRoots[i] != null) {
183        if ((m_MinNode == null)
184            || newRoots[i].compareTo(m_MinNode) < 0) {
185          m_MinNode = newRoots[i];
186        }
187      }
188  }//consolidate
189
190  // links y under x
191  private void link(FibonacciHeapNode<T2> y, FibonacciHeapNode<T2> x) {
192    removeFromSiblings(y);
193    y.m_Parent = x;
194    if (x.m_Child == null)
195      x.m_Child = y;
196    else
197      concatenateSiblings(x.m_Child, y);
198    x.degree++;
199    y.mark = false;
200  }//link
201
202
203  // cut node x from below y
204  private void cut(FibonacciHeapNode<T2> x, FibonacciHeapNode<T2> y) {
205    // remove x from y's children
206    if (y.m_Child == x)
207      y.m_Child = x.m_NextSibling;
208    if (y.m_Child == x)
209      y.m_Child = null;
210
211    y.degree--;
212    removeFromSiblings(x);
213    concatenateSiblings(x, m_MinNode);
214    x.m_Parent = null;
215    x.mark = false;
216
217  }//cut
218
219  private void cascadingCut(FibonacciHeapNode<T2> y) {
220    FibonacciHeapNode<T2> z = y.m_Parent;
221    if (z != null) {
222      if (!y.mark) {
223        y.mark = true;
224      } else {
225        cut(y, z);
226        cascadingCut(z);
227      }
228    }
229  }//cascadingCut
230
231
232  // private node class
233  private static class FibonacciHeapNode<T2 extends Comparable<T2>>
234      implements Comparable<FibonacciHeapNode<T2> > {
235
236    private T2 m_Priority;
237
238    private FibonacciHeapNode<T2> m_Parent;
239    private FibonacciHeapNode<T2> m_PrevSibling;
240    private FibonacciHeapNode<T2> m_NextSibling;
241    private FibonacciHeapNode<T2> m_Child;
242    private int degree;
243    private boolean mark;
244
245    FibonacciHeapNode(T2 priority) {
246      this.m_Priority = priority;
247
248      this.m_Parent = null;
249      this.m_PrevSibling = this;
250      this.m_NextSibling = this;
251      this.m_Child = null;
252      this.degree = 0;
253      this.mark = false;
254    }//constructor
255
256    public String toString() {
257      return "[" + m_Priority + ", " + degree + "]";
258    }
259
260    public int compareTo(FibonacciHeapNode<T2> other) {
261      return this.m_Priority.compareTo(other.m_Priority);
262    }//compareTo
263
264    public int compareTo(T2 other) {
265      return this.m_Priority.compareTo(other);
266    }//compareTo
267
268  }//inner class FibonacciHeapNode
269
270}//class FibonacciHeap
271