Fibonacci heaps are an effective data structure that may be used to create priority queues. They provide better reduced time complexity than conventional binary heaps for important operations like insertion, deletion, and minimal element finding. This article explores the topic of Java Fibonacci heaps, describing their implementation, structure, and uses.
A Fibonacci heap is formed up of several trees, each of which is a min-heap. The structure maintains references to the roots of all trees using a root list, and the trees are unordered. Fibonacci Heaps’ key features are as follows:
- Minimum Pointer: A pointer to the tree root with the smallest key.
- Root List: A circular doubly linked list containing all tree roots.
- Degree: The number of children a node has.
- Marked Nodes: Nodes that have lost a child since the last time they were made the child of another node.
Visual representation of a Fibonacci heap: Java Program to Implement Fibonacci HeapBelow is the implementation of Fibonacci Heap:
Java
// Java Program to Fibonacci Heap
import java.util.*;
// Class to represent a node in the Fibonacci Heap
class FibonacciHeapNode {
int key;
int degree;
FibonacciHeapNode parent;
FibonacciHeapNode child;
FibonacciHeapNode left;
FibonacciHeapNode right;
boolean mark;
// Constructor to initialize a new node
public FibonacciHeapNode(int key) {
this.key = key;
this.degree = 0;
this.mark = false;
this.parent = null;
this.child = null;
this.left = this;
this.right = this;
}
}
// Class to represent a Fibonacci Heap
class FibonacciHeap {
// Pointer to the minimum node in the heap
private FibonacciHeapNode minNode;
// Total number of nodes in the heap
private int nodeCount;
// Constructor to initialize an empty Fibonacci Heap
public FibonacciHeap() {
minNode = null;
nodeCount = 0;
}
// Insert a new node into the Fibonacci Heap
public void insert(int key) {
FibonacciHeapNode node = new FibonacciHeapNode(key);
if (minNode != null) {
// Add the new node to the root list
addToRootList(node);
if (key < minNode.key) {
// Update the minNode pointer if necessary
minNode = node;
}
} else {
// Set the new node as the minNode if the heap was empty
minNode = node;
}
nodeCount++;
}
// Add a node to the root list of the Fibonacci Heap
private void addToRootList(FibonacciHeapNode node) {
node.left = minNode;
node.right = minNode.right;
minNode.right.left = node;
minNode.right = node;
}
// Find the minimum node in the Fibonacci Heap
public FibonacciHeapNode findMin() {
return minNode;
}
// Extract the minimum node from the Fibonacci Heap
public FibonacciHeapNode extractMin() {
FibonacciHeapNode min = minNode;
if (min != null) {
if (min.child != null) {
// Add the children of the minNode to the root list
addChildrenToRootList(min);
}
// Remove the minNode from the root list
removeNodeFromRootList(min);
if (min == min.right) {
// Set minNode to null if it was the only node in the root list
minNode = null;
}
else {
minNode = min.right;
// Consolidate the trees in the root list
consolidate();
}
nodeCount--;
}
return min;
}
// Add the children of a node to the root list
private void addChildrenToRootList(FibonacciHeapNode min) {
FibonacciHeapNode child = min.child;
do {
FibonacciHeapNode nextChild = child.right;
child.left = minNode;
child.right = minNode.right;
minNode.right.left = child;
minNode.right = child;
child.parent = null;
child = nextChild;
} while (child != min.child);
}
// Remove a node from the root list
private void removeNodeFromRootList(FibonacciHeapNode node) {
node.left.right = node.right;
node.right.left = node.left;
}
// Consolidate the trees in the root list
private void consolidate() {
int arraySize = ((int) Math.floor(Math.log(nodeCount) / Math.log(2.0))) + 1;
List<FibonacciHeapNode> array = new ArrayList<>(Collections.nCopies(arraySize, null));
List<FibonacciHeapNode> rootList = getRootList();
for (FibonacciHeapNode node : rootList) {
int degree = node.degree;
while (array.get(degree) != null) {
FibonacciHeapNode other = array.get(degree);
if (node.key > other.key) {
FibonacciHeapNode temp = node;
node = other;
other = temp;
}
// Link two trees of the same degree
link(other, node);
array.set(degree, null);
degree++;
}
array.set(degree, node);
}
minNode = null;
for (FibonacciHeapNode node : array) {
if (node != null) {
if (minNode == null) {
minNode = node;
} else {
// Add the node back to the root list
addToRootList(node);
if (node.key < minNode.key) {
minNode = node;
}
}
}
}
}
// Get a list of all root nodes
private List<FibonacciHeapNode> getRootList() {
List<FibonacciHeapNode> rootList = new ArrayList<>();
if (minNode != null) {
FibonacciHeapNode current = minNode;
do {
rootList.add(current);
current = current.right;
} while (current != minNode);
}
return rootList;
}
// Link two trees of the same degree
private void link(FibonacciHeapNode y, FibonacciHeapNode x) {
// Remove y from the root list
removeNodeFromRootList(y);
y.left = y.right = y;
y.parent = x;
if (x.child == null) {
// Make y a child of x
x.child = y;
} else {
y.right = x.child;
y.left = x.child.left;
x.child.left.right = y;
x.child.left = y;
}
x.degree++;
y.mark = false;
}
}
// Main class to test the Fibonacci Heap
public class Main {
public static void main(String[] args) {
FibonacciHeap heap = new FibonacciHeap();
heap.insert(10);
heap.insert(3);
heap.insert(24);
heap.insert(17);
heap.insert(39);
System.out.println("Minimum: " + heap.findMin().key);
heap.extractMin();
System.out.println("Minimum after extraction: " + heap.findMin().key);
}
}
OutputMinimum: 3
Minimum after extraction: 10
Applications- Dijkstra’s Algorithm: For finding the shortest paths in graphs.
- Prim’s Algorithm: For finding the minimum spanning tree.
- Network Optimization: In various optimization problems involving networks.
|