All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graphstream.algorithm.util.FibonacciHeap Maven / Gradle / Ivy

Go to download

The GraphStream library. With GraphStream you deal with graphs. Static and Dynamic. You create them from scratch, from a file or any source. You display and render them. This package contains algorithms and generators.

There is a newer version: 2.0
Show newest version
/*
 * Copyright 2006 - 2015
 *     Stefan Balev     
 *     Julien Baudry    
 *     Antoine Dutot    
 *     Yoann Pigné      
 *     Guilhelm Savin   
 * 
 * This file is part of GraphStream .
 * 
 * GraphStream is a library whose purpose is to handle static or dynamic
 * graph, create them from scratch, file or any source and display them.
 * 
 * This program is free software distributed under the terms of two licenses, the
 * CeCILL-C license that fits European law, and the GNU Lesser General Public
 * License. You can  use, modify and/ or redistribute the software under the terms
 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
 * URL  or under the terms of the GNU LGPL as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 * 
 * This program 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 program.  If not, see .
 * 
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
 */
package org.graphstream.algorithm.util;

import java.util.ArrayList;

/**
 * 

* Fibonacci heap is a data structure used mainly to implement priority queues. * It stores pairs (key, value) in nodes. The structure is designed so that the * following operations can be implemented efficiently: *

    *
  • Finding the node with minimal key
  • *
  • Extracting the node with minimal key
  • *
  • Decreasing the key of a given node
  • *
  • Adding a new node
  • *
  • Merging two heaps
  • *
  • Deleting a node
  • *
* *

* This implementation does not support directly the last operation, but there * is a workaround. To delete a node, first decrease its key to something less * than the current minimum, then just extract the minimum. * *

* In order to compare keys, this implementation uses their natural order: they * must implement {@link java.lang.Comparable} interface. The values can be of * any type. * *

Example

* *
 * FibonacciHeap<Integer, String> heap = new FibonacciHeap<Integer, String>();
 * // add some nodes and keep their references in order to be able to decrease
 * // their keys later
 * FibonacciHeap<Integer, String>.Node nodeA = heap.add(20, "A");
 * FibonacciHeap<Integer, String>.Node nodeB = heap.add(10, "B");
 * FibonacciHeap<Integer, String>.Node nodeC = heap.add(30, "C");
 * FibonacciHeap<Integer, String>.Node nodeD = heap.add(50, "D");
 * FibonacciHeap<Integer, String>.Node nodeE = heap.add(40, "E");
 * 
 * String s1 = heap.extractMin(); // "B"
 * String s2 = heap.getMinValue(); // "A"
 * heap.decreaseKey(nodeD, 5);
 * String s3 = heap.extractMin(); // "D"
 * //delete nodeC
 * int kMin = heap.getMinKey(); // 20
 * heap.decreaseKey(nodeC, kMin - 1);
 * String s4 = heap.extractMin(); // C
 * 
* * @author Stefan Balev * * @param * the type of the keys * @param * the type of the values */ public class FibonacciHeap, V> { /** * This class encapsulates pairs (key, value) in nodes stored in Fibonacci * heaps. Objects of this class cannot be instantiated directly. The only * way to obtain a node reference is the return value of * {@link FibonacciHeap#add(Comparable, Object)}. Typically these references * are stored and then used in calls to * {@link FibonacciHeap#decreaseKey(Node, Comparable)}. * * @author Stefan Balev * */ public class Node { protected K key; protected V value; protected Node parent; protected Node child; protected Node left; protected Node right; protected int degree; protected boolean lostChild; protected Node(K key, V value) { this.key = key; this.value = value; parent = child = null; left = right = this; degree = 0; lostChild = false; } protected void clear() { parent = null; if (child != null) { child.clear(); child = null; } left.right = null; left = null; if (right != null) right.clear(); } protected void concatLists(Node y) { Node r = right; Node l = y.left; right = y; y.left = this; l.right = r; r.left = l; } protected void addChild(Node y) { y.parent = this; y.left = y.right = y; y.lostChild = false; degree++; if (child == null) child = y; else child.concatLists(y); } /** * Returns the key stored in this node. * @return the key stored in this node */ public K getKey() { return key; } /** * Returns the value stored in this node. * @return the value stored in this node */ public V getValue() { return value; } } protected Node min; protected int size; protected ArrayList degList; /** * Creates a new empty Fibonacci heap. */ public FibonacciHeap() { min = null; size = 0; degList = new ArrayList(); } /** * Checks if the heap is empty. * @return {@code true} if the heap is empty * @complexity O(1) */ public boolean isEmpty() { return size == 0; } /** * Returns the number of nodes in the heap. * @return the number of nodes in the heap * @complexity O(1) */ public int size() { return size; } /** * Removes all the nodes in the heap * @complexity This operation can be done in O(1) but this implementation takes O(n) * in order to facilitate the garbage collection. */ public void clear() { if (!isEmpty()) { min.clear(); min = null; size = 0; } } /** * Adds a new node containing the given key and value to the heap. * @param key the key of the new node * @param value the value of the new node * @return a reference to the new node. Typically this reference is stored and used in subsequent calls to * {@link #decreaseKey(Node, Comparable)} * @complexity O(1) */ public Node add(K key, V value) { Node node = new Node(key, value); if (isEmpty()) min = node; else { min.concatLists(node); if (node.key.compareTo(min.key) < 0) min = node; } size++; return node; } /** * Merges two heaps. Warning: this operation is destructive. This method empties the parameter {@code heap}. * @param heap the heap to be merged with this heap * @complexity O(1) */ public void addAll(FibonacciHeap heap) { if (isEmpty()) min = heap.min; else if (!heap.isEmpty()) { min.concatLists(heap.min); if (heap.min.key.compareTo(min.key) < 0) min = heap.min; } size += heap.size; heap.min = null; heap.size = 0; } /** * Returns the minimal key in the heap. * @return the minimal key in the heap * @complexity O(1) */ public K getMinKey() { return min.key; } /** * Returns the value stored in the node containing the minimal key. * @return the value stored in the node containing the minimal key * @complexity O(1) * */ public V getMinValue() { return min.value; } /** * Removes the node containing the minimal key from the heap. * @return the value stored in the removed node * @complexity O(logn) amortized running time */ public V extractMin() { Node z = min; Node x = z.child; if (x != null) { do { x.parent = null; x = x.right; } while (x != z.child); z.concatLists(x); z.child = null; } if (z == z.right) min = null; else { z.left.right = z.right; z.right.left = z.left; min = z.right; consolidate(); } z.left = z.right = null; size--; return z.value; } protected void consolidate() { Node w, x, y, t; int d; w = min; degList.clear(); do { x = w; w = w.right; d = x.degree; while (d >= degList.size()) degList.add(null); y = degList.get(d); while (y != null) { if (x.key.compareTo(y.key) > 0) { t = x; x = y; y = t; } x.addChild(y); degList.set(d, null); d++; if (d >= degList.size()) degList.add(null); y = degList.get(d); } degList.set(d, x); } while (w != min); min = null; for (Node s : degList) if (s != null) { s.left = s.right = s; if (min == null) min = s; else { min.concatLists(s); if (s.key.compareTo(min.key) < 0) min = s; } } } /** Decreases the key of a given node * @param x the node whose key is to be decreased. Must be a reference returned by {@link #add(Comparable, Object)}. * @param key the new key * @throws IllegalArgumentException if the new key is greater than the current. * @complexity O(1) amortized running time */ public void decreaseKey(Node x, K key) { if (key.compareTo(x.key) > 0) throw new IllegalArgumentException( "The new key must be less than the old"); x.key = key; Node y = x.parent; if (y != null && x.key.compareTo(y.key) < 0) { detach(x); multiDetach(y); } if (key.compareTo(min.key) < 0) min = x; } protected void detach(Node x) { Node y = x.parent; y.degree--; if (x == x.right) y.child = null; else { x.left.right = x.right; x.right.left = x.left; if (y.child == x) y.child = x.right; x.left = x.right = x; } min.concatLists(x); x.parent = null; x.lostChild = false; } protected void multiDetach(Node x) { if (x.parent == null) return; if (x.lostChild) { Node z = x.parent; detach(x); multiDetach(z); } else x.lostChild = true; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy