org.graphstream.algorithm.util.FibonacciHeap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gs-algo Show documentation
Show all versions of gs-algo Show documentation
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.
/*
* 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