1 /**
2  * Copyright (c) 2007-2017, Gaudenz Alder
3  * Copyright (c) 2007-2017, JGraph Ltd
4  */
5 package com.mxgraph.analysis;
6 
7 import java.util.Hashtable;
8 import java.util.Map;
9 
10 /**
11  * This class implements a priority queue.
12  */
13 public class mxFibonacciHeap
14 {
15 
16 	/**
17 	 * Maps from elements to nodes
18 	 */
19 	protected Map<Object, Node> nodes = new Hashtable<Object, Node>();
20 
21 	/**
22 	 *
23 	 */
24 	protected Node min;
25 
26 	/**
27 	 *
28 	 */
29 	protected int size;
30 
31 	/**
32 	 * Returns the node that represents element.
33 	 * @param element the element whose node to find
34 	 * @param create whether to create
35 	 * @return the node representing the specified element
36 	 */
getNode(Object element, boolean create)37 	public Node getNode(Object element, boolean create)
38 	{
39 		Node node = nodes.get(element);
40 
41 		if (node == null && create)
42 		{
43 			node = new Node(element, Double.MAX_VALUE);
44 			nodes.put(element, node);
45 			insert(node, node.getKey());
46 		}
47 		return node;
48 	}
49 
50 	/**
51 	 * Returns true if the queue is empty.
52 	 * @return whether the queue is empty
53 	 */
isEmpty()54 	public boolean isEmpty()
55 	{
56 		return min == null;
57 	}
58 
59 	/**
60 	 * Decreases the key value for a heap node, given the new value to take on.
61 	 * The structure of the heap may be changed and will not be consolidated.
62 	 *
63 	 * <p>
64 	 * Running time: O(1) amortized
65 	 * </p>
66 	 *
67 	 * @param x Node whose value should be decreased.
68 	 * @param k New key value for node x.
69 	 *
70 	 * @exception IllegalArgumentException
71 	 *                Thrown if k is larger than x.key value.
72 	 */
decreaseKey(Node x, double k)73 	public void decreaseKey(Node x, double k)
74 	{
75 		if (k > x.key)
76 		{
77 			throw new IllegalArgumentException(
78 					"decreaseKey() got larger key value");
79 		}
80 
81 		x.key = k;
82 		Node y = x.parent;
83 
84 		if ((y != null) && (x.key < y.key))
85 		{
86 			cut(x, y);
87 			cascadingCut(y);
88 		}
89 
90 		if (min == null || x.key < min.key)
91 		{
92 			min = x;
93 		}
94 	}
95 
96 	/**
97 	 * Deletes a node from the heap given the reference to the node. The trees
98 	 * in the heap will be consolidated, if necessary. This operation may fail
99 	 * to remove the correct element if there are nodes with key value
100 	 * -Infinity.
101 	 *
102 	 * <p>
103 	 * Running time: O(log n) amortized
104 	 * </p>
105 	 *
106 	 * @param x The node to remove from the heap.
107 	 */
delete(Node x)108 	public void delete(Node x)
109 	{
110 		// make x as small as possible
111 		decreaseKey(x, Double.NEGATIVE_INFINITY);
112 
113 		// remove the smallest, which decreases n also
114 		removeMin();
115 	}
116 
117 	/**
118 	 * Inserts a new data element into the heap. No heap consolidation is
119 	 * performed at this time, the new node is simply inserted into the root
120 	 * list of this heap.
121 	 *
122 	 * <p>
123 	 * Running time: O(1) actual
124 	 * </p>
125 	 *
126 	 * @param node
127 	 *            new node to insert into heap
128 	 * @param key
129 	 *            key value associated with data object
130 	 */
insert(Node node, double key)131 	public void insert(Node node, double key)
132 	{
133 		node.key = key;
134 
135 		// concatenate node into min list
136 		if (min != null)
137 		{
138 			node.left = min;
139 			node.right = min.right;
140 			min.right = node;
141 			node.right.left = node;
142 
143 			if (key < min.key)
144 			{
145 				min = node;
146 			}
147 		}
148 		else
149 		{
150 			min = node;
151 		}
152 
153 		size++;
154 	}
155 
156 	/**
157 	 * Returns the smallest element in the heap. This smallest element is the
158 	 * one with the minimum key value.
159 	 *
160 	 * <p>
161 	 * Running time: O(1) actual
162 	 * </p>
163 	 *
164 	 * @return Returns the heap node with the smallest key.
165 	 */
min()166 	public Node min()
167 	{
168 		return min;
169 	}
170 
171 	/**
172 	 * Removes the smallest element from the heap. This will cause the trees in
173 	 * the heap to be consolidated, if necessary.
174 	 * Does not remove the data node so that the current key remains stored.
175 	 *
176 	 * <p>
177 	 * Running time: O(log n) amortized
178 	 * </p>
179 	 *
180 	 * @return Returns the node with the smallest key.
181 	 */
removeMin()182 	public Node removeMin()
183 	{
184 		Node z = min;
185 
186 		if (z != null)
187 		{
188 			int numKids = z.degree;
189 			Node x = z.child;
190 			Node tempRight;
191 
192 			// for each child of z do...
193 			while (numKids > 0)
194 			{
195 				tempRight = x.right;
196 
197 				// remove x from child list
198 				x.left.right = x.right;
199 				x.right.left = x.left;
200 
201 				// add x to root list of heap
202 				x.left = min;
203 				x.right = min.right;
204 				min.right = x;
205 				x.right.left = x;
206 
207 				// set parent[x] to null
208 				x.parent = null;
209 				x = tempRight;
210 				numKids--;
211 			}
212 
213 			// remove z from root list of heap
214 			z.left.right = z.right;
215 			z.right.left = z.left;
216 
217 			if (z == z.right)
218 			{
219 				min = null;
220 			}
221 			else
222 			{
223 				min = z.right;
224 				consolidate();
225 			}
226 
227 			// decrement size of heap
228 			size--;
229 		}
230 
231 		return z;
232 	}
233 
234 	/**
235 	 * Returns the size of the heap which is measured in the number of elements
236 	 * contained in the heap.
237 	 *
238 	 * <p>
239 	 * Running time: O(1) actual
240 	 * </p>
241 	 *
242 	 * @return Returns the number of elements in the heap.
243 	 */
size()244 	public int size()
245 	{
246 		return size;
247 	}
248 
249 	/**
250 	 * Joins two Fibonacci heaps into a new one. No heap consolidation is
251 	 * performed at this time. The two root lists are simply joined together.
252 	 *
253 	 * <p>
254 	 * Running time: O(1) actual
255 	 * </p>
256 	 *
257 	 * @param h1 The first heap.
258 	 * @param h2 The second heap.
259 	 * @return Returns a new heap containing h1 and h2.
260 	 */
union(mxFibonacciHeap h1, mxFibonacciHeap h2)261 	public static mxFibonacciHeap union(mxFibonacciHeap h1, mxFibonacciHeap h2)
262 	{
263 		mxFibonacciHeap h = new mxFibonacciHeap();
264 
265 		if ((h1 != null) && (h2 != null))
266 		{
267 			h.min = h1.min;
268 
269 			if (h.min != null)
270 			{
271 				if (h2.min != null)
272 				{
273 					h.min.right.left = h2.min.left;
274 					h2.min.left.right = h.min.right;
275 					h.min.right = h2.min;
276 					h2.min.left = h.min;
277 
278 					if (h2.min.key < h1.min.key)
279 					{
280 						h.min = h2.min;
281 					}
282 				}
283 			}
284 			else
285 			{
286 				h.min = h2.min;
287 			}
288 
289 			h.size = h1.size + h2.size;
290 		}
291 
292 		return h;
293 	}
294 
295 	/**
296 	 * Performs a cascading cut operation. This cuts y from its parent and then
297 	 * does the same for its parent, and so on up the tree.
298 	 *
299 	 * <p>
300 	 * Running time: O(log n); O(1) excluding the recursion
301 	 * </p>
302 	 *
303 	 * @param y The node to perform cascading cut on.
304 	 */
cascadingCut(Node y)305 	protected void cascadingCut(Node y)
306 	{
307 		Node z = y.parent;
308 
309 		// if there's a parent...
310 		if (z != null)
311 		{
312 			// if y is unmarked, set it marked
313 			if (!y.mark)
314 			{
315 				y.mark = true;
316 			}
317 			else
318 			{
319 				// it's marked, cut it from parent
320 				cut(y, z);
321 
322 				// cut its parent as well
323 				cascadingCut(z);
324 			}
325 		}
326 	}
327 
328 	/**
329 	 * Consolidates the trees in the heap by joining trees of equal degree until
330 	 * there are no more trees of equal degree in the root list.
331 	 *
332 	 * <p>
333 	 * Running time: O(log n) amortized
334 	 * </p>
335 	 */
consolidate()336 	protected void consolidate()
337 	{
338 		int arraySize = size + 1;
339 		Node[] array = new Node[arraySize];
340 
341 		// Initialize degree array
342 		for (int i = 0; i < arraySize; i++)
343 		{
344 			array[i] = null;
345 		}
346 
347 		// Find the number of root nodes.
348 		int numRoots = 0;
349 		Node x = min;
350 
351 		if (x != null)
352 		{
353 			numRoots++;
354 			x = x.right;
355 
356 			while (x != min)
357 			{
358 				numRoots++;
359 				x = x.right;
360 			}
361 		}
362 
363 		// For each node in root list do...
364 		while (numRoots > 0)
365 		{
366 			// Access this node's degree..
367 			int d = x.degree;
368 			Node next = x.right;
369 
370 			// ..and see if there's another of the same degree.
371 			while (array[d] != null)
372 			{
373 				// There is, make one of the nodes a child of the other.
374 				Node y = array[d];
375 
376 				// Do this based on the key value.
377 				if (x.key > y.key)
378 				{
379 					Node temp = y;
380 					y = x;
381 					x = temp;
382 				}
383 
384 				// Node y disappears from root list.
385 				link(y, x);
386 
387 				// We've handled this degree, go to next one.
388 				array[d] = null;
389 				d++;
390 			}
391 
392 			// Save this node for later when we might encounter another
393 			// of the same degree.
394 			array[d] = x;
395 
396 			// Move forward through list.
397 			x = next;
398 			numRoots--;
399 		}
400 
401 		// Set min to null (effectively losing the root list) and
402 		// reconstruct the root list from the array entries in array[].
403 		min = null;
404 
405 		for (int i = 0; i < arraySize; i++)
406 		{
407 			if (array[i] != null)
408 			{
409 				// We've got a live one, add it to root list.
410 				if (min != null)
411 				{
412 					// First remove node from root list.
413 					array[i].left.right = array[i].right;
414 					array[i].right.left = array[i].left;
415 
416 					// Now add to root list, again.
417 					array[i].left = min;
418 					array[i].right = min.right;
419 					min.right = array[i];
420 					array[i].right.left = array[i];
421 
422 					// Check if this is a new min.
423 					if (array[i].key < min.key)
424 					{
425 						min = array[i];
426 					}
427 				}
428 				else
429 				{
430 					min = array[i];
431 				}
432 			}
433 		}
434 	}
435 
436 	/**
437 	 * The reverse of the link operation: removes x from the child list of y.
438 	 * This method assumes that min is non-null.
439 	 *
440 	 * <p>
441 	 * Running time: O(1)
442 	 * </p>
443 	 *
444 	 * @param x The child of y to be removed from y's child list.
445 	 * @param y The parent of x about to lose a child.
446 	 */
cut(Node x, Node y)447 	protected void cut(Node x, Node y)
448 	{
449 		// remove x from childlist of y and decrement degree[y]
450 		x.left.right = x.right;
451 		x.right.left = x.left;
452 		y.degree--;
453 
454 		// reset y.child if necessary
455 		if (y.child == x)
456 		{
457 			y.child = x.right;
458 		}
459 
460 		if (y.degree == 0)
461 		{
462 			y.child = null;
463 		}
464 
465 		// add x to root list of heap
466 		x.left = min;
467 		x.right = min.right;
468 		min.right = x;
469 		x.right.left = x;
470 
471 		// set parent[x] to nil
472 		x.parent = null;
473 
474 		// set mark[x] to false
475 		x.mark = false;
476 	}
477 
478 	/**
479 	 * Make node y a child of node x.
480 	 *
481 	 * <p>
482 	 * Running time: O(1) actual
483 	 * </p>
484 	 *
485 	 * @param y The node to become child.
486 	 * @param x The node to become parent.
487 	 */
link(Node y, Node x)488 	protected void link(Node y, Node x)
489 	{
490 		// remove y from root list of heap
491 		y.left.right = y.right;
492 		y.right.left = y.left;
493 
494 		// make y a child of x
495 		y.parent = x;
496 
497 		if (x.child == null)
498 		{
499 			x.child = y;
500 			y.right = y;
501 			y.left = y;
502 		}
503 		else
504 		{
505 			y.left = x.child;
506 			y.right = x.child.right;
507 			x.child.right = y;
508 			y.right.left = y;
509 		}
510 
511 		// increase degree[x]
512 		x.degree++;
513 
514 		// set mark[y] false
515 		y.mark = false;
516 	}
517 
518 	/**
519 	 * Implements a node of the Fibonacci heap. It holds the information
520 	 * necessary for maintaining the structure of the heap. It also holds the
521 	 * reference to the key value (which is used to determine the heap
522 	 * structure). Additional Node data should be stored in a subclass.
523 	 */
524 	public static class Node
525 	{
526 
527 		Object userObject;
528 
529 		/**
530 		 * first child node
531 		 */
532 		Node child;
533 
534 		/**
535 		 * left sibling node
536 		 */
537 		Node left;
538 
539 		/**
540 		 * parent node
541 		 */
542 		Node parent;
543 
544 		/**
545 		 * right sibling node
546 		 */
547 		Node right;
548 
549 		/**
550 		 * true if this node has had a child removed since this node was added
551 		 * to its parent
552 		 */
553 		boolean mark;
554 
555 		/**
556 		 * key value for this node
557 		 */
558 		double key;
559 
560 		/**
561 		 * number of children of this node (does not count grandchildren)
562 		 */
563 		int degree;
564 
565 		/**
566 		 * Default constructor. Initializes the right and left pointers, making
567 		 * this a circular doubly-linked list.
568 		 *
569 		 * @param key The initial key for node.
570 		 */
Node(Object userObject, double key)571 		public Node(Object userObject, double key)
572 		{
573 			this.userObject = userObject;
574 			right = this;
575 			left = this;
576 			this.key = key;
577 		}
578 
579 		/**
580 		 * Obtain the key for this node.
581 		 *
582 		 * @return the key
583 		 */
getKey()584 		public final double getKey()
585 		{
586 			return key;
587 		}
588 
589 		/**
590 		 * @return Returns the userObject.
591 		 */
getUserObject()592 		public Object getUserObject()
593 		{
594 			return userObject;
595 		}
596 
597 		/**
598 		 * @param userObject The userObject to set.
599 		 */
setUserObject(Object userObject)600 		public void setUserObject(Object userObject)
601 		{
602 			this.userObject = userObject;
603 		}
604 
605 	}
606 
607 }
608