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