diff --git a/src/FibonacciHeap.cs b/src/FibonacciHeap.cs
index 646de58..8f1e76e 100644
--- a/src/FibonacciHeap.cs
+++ b/src/FibonacciHeap.cs
@@ -58,13 +58,22 @@ public void DecreaseKey(Node node, T newKey) {
}
}
+ ///
+ /// Cut the link between a node and its parent, moving the node to the root list.
+ ///
+
private void Cut(Node node, Node parent) {
- RemoveNodeFromList(node);
parent.Degree--;
+ parent.Child = (node.Next == node ? null : node.Next);
+ RemoveNodeFromList(node);
MergeLists(_minNode, node);
node.IsMarked = false;
}
+ ///
+ /// Perform a cascading cut on a node; mark the node if it is not marked, otherwise cut the
+ /// node and perform a cascading cut on its parent.
+ ///
private void CascadingCut(Node node) {
Node parent = node.Parent;
if (parent != null) {
@@ -81,7 +90,6 @@ public void Delete(Node node) {
// This is a special implementation of decreaseKey that sets the
// argument to the minimum value. This is necessary to make generic keys
// work, since there is no MIN_VALUE constant for generic types.
- node.IsMinimum = true;
Node parent = node.Parent;
if (parent != null) {
Cut(node, parent);
@@ -104,7 +112,7 @@ public Node ExtractMinimum() {
} while (child != extractedMin.Child);
}
- Node nextInRootList = _minNode.Next == _minNode ? null : _minNode.Next;
+ Node nextInRootList = extractedMin.Next == extractedMin ? null : extractedMin.Next;
// Remove min from root list
RemoveNodeFromList(extractedMin);
@@ -186,6 +194,9 @@ private void RemoveNodeFromList(Node node) {
node.Prev = node;
}
+ ///
+ /// Links two heaps of the same order together.
+ ///
private void LinkHeaps(Node max, Node min) {
RemoveNodeFromList(max);
min.Child = MergeLists(max, min.Child);
@@ -236,7 +247,6 @@ public class Node : IComparable {
public Node Prev { get; set; }
public Node Next { get; set; }
public bool IsMarked { get; set; }
- public bool IsMinimum { get; set; }
public Node() {
Key = default(T);
diff --git a/test/FibonacciHeap/FibonacciHeapDecreaseKeyTest.cs b/test/FibonacciHeap/FibonacciHeapDecreaseKeyTest.cs
new file mode 100644
index 0000000..bdb8bbd
--- /dev/null
+++ b/test/FibonacciHeap/FibonacciHeapDecreaseKeyTest.cs
@@ -0,0 +1,129 @@
+using GrowingWithTheWeb.DataStructures;
+using Xunit;
+
+public class FibonacciHeapDecreaseKeyTest {
+ [Fact]
+ public void LeavesValidTreeOnFlatHeapTest() {
+ var heap = new FibonacciHeap();
+ heap.Insert(13);
+ heap.Insert(26);
+ heap.Insert(3);
+ heap.Insert(-6);
+ heap.Insert(27);
+ var node6 = heap.Insert(88);
+ heap.Insert(59);
+ heap.Insert(-10);
+ heap.Insert(16);
+ heap.DecreaseKey(node6, -8);
+ Assert.Equal(heap.ExtractMinimum().Key, -10);
+ Assert.Equal(heap.ExtractMinimum().Key, -8);
+ Assert.Equal(heap.ExtractMinimum().Key, -6);
+ Assert.Equal(heap.ExtractMinimum().Key, 3);
+ Assert.Equal(heap.ExtractMinimum().Key, 13);
+ Assert.Equal(heap.ExtractMinimum().Key, 16);
+ Assert.Equal(heap.ExtractMinimum().Key, 26);
+ Assert.Equal(heap.ExtractMinimum().Key, 27);
+ Assert.Equal(heap.ExtractMinimum().Key, 59);
+ }
+
+ [Fact]
+ public void LeavesValidTreeOnConsolidatedHeapTest() {
+ var heap = new FibonacciHeap();
+ var node0 = heap.Insert(0);
+ var node1 = heap.Insert(1);
+ var node2 = heap.Insert(2);
+ var node3 = heap.Insert(3);
+ var node4 = heap.Insert(4);
+ var node5 = heap.Insert(5);
+ var node6 = heap.Insert(6);
+ var node7 = heap.Insert(7);
+ var node8 = heap.Insert(8);
+
+ // Extracting minimum should trigger consolidate.
+ //
+ // __1
+ // / /|
+ // 5 3 2
+ // 0--1--2--3--4--5--6--7--8 -> /| |
+ // 7 6 4
+ // |
+ // 8
+ //
+ Assert.Equal(heap.ExtractMinimum(), node0);
+
+ // Decrease node 8 to 0
+ //
+ // __1
+ // / /| __1--0
+ // 5 3 2 / /|
+ // /| | -> 5 3 2
+ // 7 6 4 /| |
+ // | 7 6 4
+ // 8
+ //
+ heap.DecreaseKey(node8, 0);
+ Assert.True(node1.Next == node8);
+
+ Assert.Equal(heap.Size, 8);
+ Assert.True(heap.ExtractMinimum() == node8);
+ Assert.True(heap.ExtractMinimum() == node1);
+ Assert.True(heap.ExtractMinimum() == node2);
+ Assert.True(heap.ExtractMinimum() == node3);
+ Assert.True(heap.ExtractMinimum() == node4);
+ Assert.True(heap.ExtractMinimum() == node5);
+ Assert.True(heap.ExtractMinimum() == node6);
+ Assert.True(heap.ExtractMinimum() == node7);
+ Assert.True(heap.IsEmpty());
+ }
+}
+/*
+
+test('should leave a valid tree on a consolidated Fibonacci heap', function (t) {
+ var heap = new Heap();
+ var node0 = heap.insert(0, null);
+ var node1 = heap.insert(1, null);
+ var node2 = heap.insert(2, null);
+ var node3 = heap.insert(3, null);
+ var node4 = heap.insert(4, null);
+ var node5 = heap.insert(5, null);
+ var node6 = heap.insert(6, null);
+ var node7 = heap.insert(7, null);
+ var node8 = heap.insert(8, null);
+
+ // Extracting minimum should trigger consolidate.
+ //
+ // __1
+ // / /|
+ // 5 3 2
+ // 0--1--2--3--4--5--6--7--8 -> /| |
+ // 7 6 4
+ // |
+ // 8
+ //
+ t.is(heap.extractMinimum(), node0);
+
+ // Decrease node 8 to 0
+ //
+ // __1
+ // / /| __1--0
+ // 5 3 2 / /|
+ // /| | -> 5 3 2
+ // 7 6 4 /| |
+ // | 7 6 4
+ // 8
+ //
+ heap.decreaseKey(node8, 0);
+ t.true(node1.next === node8);
+
+ t.is(heap.size(), 8);
+ t.true(heap.extractMinimum() === node8);
+ t.true(heap.extractMinimum() === node1);
+ t.true(heap.extractMinimum() === node2);
+ t.true(heap.extractMinimum() === node3);
+ t.true(heap.extractMinimum() === node4);
+ t.true(heap.extractMinimum() === node5);
+ t.true(heap.extractMinimum() === node6);
+ t.true(heap.extractMinimum() === node7);
+ t.true(heap.isEmpty());
+});
+*/
\ No newline at end of file