mirror of
https://github.com/AlexMacocian/SystemExtensions.git
synced 2026-07-24 03:56:27 +00:00
Implemented Fibonacci Heap + Tests
This commit is contained in:
@@ -78,10 +78,10 @@ namespace SystemExtensions.Collections
|
||||
items[position] = value;
|
||||
}
|
||||
/// <summary>
|
||||
/// Deletes the item at the root. Throws exception if there are no items in the heap.
|
||||
/// Removes the item at the root. Throws exception if there are no items in the heap.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public T DeleteMin()
|
||||
/// <returns>Value removed.</returns>
|
||||
public T RemoveMin()
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
@@ -93,7 +93,7 @@ namespace SystemExtensions.Collections
|
||||
return min;
|
||||
}
|
||||
/// <summary>
|
||||
/// Function to return the heap structure as an array
|
||||
/// Return the heap structure as an array
|
||||
/// </summary>
|
||||
/// <returns>Array with values sorted as in heap</returns>
|
||||
public T[] ToArray()
|
||||
|
||||
@@ -0,0 +1,549 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemExtensions.Collections
|
||||
{
|
||||
public class FibonacciHeap<T> : IDisposable
|
||||
{
|
||||
#region Fields
|
||||
private FibonacciNode<T> root;
|
||||
private Comparison<T> comparator;
|
||||
private int count;
|
||||
#endregion
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Count of values in the heap.
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return count;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Minimal value contained in the heap.
|
||||
/// </summary>
|
||||
public T Minimum
|
||||
{
|
||||
get
|
||||
{
|
||||
return root.Value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Constructors
|
||||
public FibonacciHeap(Comparison<T> comparator)
|
||||
{
|
||||
this.comparator = comparator;
|
||||
}
|
||||
#endregion
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Inserts value into the heap.
|
||||
/// </summary>
|
||||
/// <param name="value">Value to be inserted.</param>
|
||||
public void Insert(T value)
|
||||
{
|
||||
FibonacciNode<T> node = new FibonacciNode<T>();
|
||||
node.Value = value;
|
||||
node.Previous = node.Next = node;
|
||||
node.Degree = 0;
|
||||
node.Marked = false;
|
||||
node.Child = null;
|
||||
node.Parent = null;
|
||||
root = Merge(root, node);
|
||||
count++;
|
||||
}
|
||||
/// <summary>
|
||||
/// Merge current heap with another heap. The other heap will be disposed at the end of this method.
|
||||
/// </summary>
|
||||
/// <param name="otherHeap">The heap to be merged with the current heap.</param>
|
||||
public void Merge(FibonacciHeap<T> otherHeap)
|
||||
{
|
||||
root = Merge(root, otherHeap.root);
|
||||
otherHeap.root = null;
|
||||
count += otherHeap.count;
|
||||
otherHeap.Dispose();
|
||||
}
|
||||
/// <summary>
|
||||
/// Remove the minimum value from the heap.
|
||||
/// </summary>
|
||||
/// <returns>Minimum value.</returns>
|
||||
public T RemoveMinimum()
|
||||
{
|
||||
FibonacciNode<T> currentRoot = root;
|
||||
if (currentRoot != null)
|
||||
{
|
||||
root = RemoveMinimum(root);
|
||||
count--;
|
||||
return currentRoot.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IndexOutOfRangeException("Heap is empty!");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Decrease the old value to a new provided value.
|
||||
/// </summary>
|
||||
/// <param name="oldValue">Old value used to find the node to have its key decreased.</param>
|
||||
/// <param name="value">New value to be assigned to the node.</param>
|
||||
public void DecreaseKey(T oldValue, T value)
|
||||
{
|
||||
FibonacciNode<T> node = Find(root, oldValue);
|
||||
root = DecreaseKey(root, node, value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Determines whether the heap contains a specified value.
|
||||
/// </summary>
|
||||
/// <param name="value">Valye to locate in the heap.</param>
|
||||
/// <returns></returns>
|
||||
public bool Contains(T value)
|
||||
{
|
||||
return Find(root, value) != null;
|
||||
}
|
||||
/// <summary>
|
||||
/// Clears the heap.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
count = 0;
|
||||
Remove(root);
|
||||
root.Next = root.Previous = root.Parent = root.Child = null;
|
||||
root = null;
|
||||
}
|
||||
/// <summary>
|
||||
/// Return the heap structure as an array. Array is not sorted other than the
|
||||
/// actual structure of the heap.
|
||||
/// </summary>
|
||||
/// <returns>Array with values from the heap.</returns>
|
||||
public T[] ToArray()
|
||||
{
|
||||
if(count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
T[] array = new T[count];
|
||||
if (count == 1)
|
||||
{
|
||||
array[0] = root.Value;
|
||||
return array;
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = 0;
|
||||
RecursiveFillArray(root, ref array, ref index);
|
||||
return array;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Private Methods
|
||||
/// <summary>
|
||||
/// Recursively traverse the heap and copy its contents to an array.
|
||||
/// </summary>
|
||||
/// <param name="currentNode">Current node.</param>
|
||||
/// <param name="array">Array to be filled with contents of heap.</param>
|
||||
/// <param name="index">Index of the next unintialized element in the array.</param>
|
||||
private void RecursiveFillArray(FibonacciNode<T> currentNode, ref T[] array, ref int index)
|
||||
{
|
||||
FibonacciNode<T> oldNode = currentNode;
|
||||
do
|
||||
{
|
||||
array[index] = currentNode.Value;
|
||||
index++;
|
||||
if (currentNode.HasChildren())
|
||||
{
|
||||
RecursiveFillArray(currentNode.Child, ref array, ref index);
|
||||
}
|
||||
currentNode = currentNode.Previous;
|
||||
} while (currentNode != oldNode);
|
||||
}
|
||||
/// <summary>
|
||||
/// Recursively remove the node and its children from the heap.
|
||||
/// </summary>
|
||||
/// <param name="node">Node to be removed.</param>
|
||||
private void Remove(FibonacciNode<T> node)
|
||||
{
|
||||
if(node != null)
|
||||
{
|
||||
FibonacciNode<T> current = node;
|
||||
do
|
||||
{
|
||||
Remove(current.Child);
|
||||
if (current.Parent != null)
|
||||
{
|
||||
current.Parent.Child = null;
|
||||
}
|
||||
current = current.Next;
|
||||
} while (current != node);
|
||||
current.Next = current.Previous = current.Child = current.Parent = null;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Merge two heaps into a larger heap.
|
||||
/// </summary>
|
||||
/// <param name="node1">Root of first heap.</param>
|
||||
/// <param name="node2">Root of second heap.</param>
|
||||
private FibonacciNode<T> Merge(FibonacciNode<T> node1, FibonacciNode<T> node2)
|
||||
{
|
||||
if(node1 == null)
|
||||
{
|
||||
return node2;
|
||||
}
|
||||
if(node2 == null)
|
||||
{
|
||||
return node1;
|
||||
}
|
||||
if(comparator(node1.Value, node2.Value) > 0)
|
||||
{
|
||||
FibonacciNode<T> temp = node1;
|
||||
node1 = node2;
|
||||
node2 = temp;
|
||||
}
|
||||
FibonacciNode<T> node1Next = node1.Next;
|
||||
FibonacciNode<T> node2Prev = node2.Previous;
|
||||
node1.Next = node2;
|
||||
node2.Previous = node1;
|
||||
node1Next.Previous = node2Prev;
|
||||
node2Prev.Next = node1Next;
|
||||
return node1;
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds child to the parent.
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent node to accept child.</param>
|
||||
/// <param name="child">Child node to be added to the parent.</param>
|
||||
private void AddChild(FibonacciNode<T> parent, FibonacciNode<T> child)
|
||||
{
|
||||
child.Previous = child.Next = child;
|
||||
child.Parent = parent;
|
||||
parent.Degree++;
|
||||
parent.Child = Merge(parent.Child, child);
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes the parent of the specified node.
|
||||
/// </summary>
|
||||
/// <param name="node">Node to be removed from its parent.</param>
|
||||
private void RemoveParent(FibonacciNode<T> node)
|
||||
{
|
||||
if(node == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
FibonacciNode<T> current = node;
|
||||
do
|
||||
{
|
||||
current.Marked = false;
|
||||
current.Parent = null;
|
||||
current = current.Next;
|
||||
} while (current != node);
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes the minimum node from the provided tree.
|
||||
/// </summary>
|
||||
/// <param name="node">Root of the provided tree.</param>
|
||||
/// <returns></returns>
|
||||
private FibonacciNode<T> RemoveMinimum(FibonacciNode<T> node)
|
||||
{
|
||||
RemoveParent(node.Child);
|
||||
if(node.Next == node)
|
||||
{
|
||||
node = node.Child;
|
||||
}
|
||||
else
|
||||
{
|
||||
node.Next.Previous = node.Previous;
|
||||
node.Previous.Next = node.Next;
|
||||
node = Merge(node.Next, node.Child);
|
||||
}
|
||||
if(node == null)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
FibonacciNode<T>[] trees = new FibonacciNode<T>[64];
|
||||
while (true)
|
||||
{
|
||||
if(trees[node.Degree] != null)
|
||||
{
|
||||
FibonacciNode<T> t = trees[node.Degree];
|
||||
if(t == node)
|
||||
{
|
||||
break;
|
||||
}
|
||||
trees[node.Degree] = null;
|
||||
if(comparator(node.Value, t.Value) < 0)
|
||||
{
|
||||
t.Previous.Next = t.Next;
|
||||
t.Next.Previous = t.Previous;
|
||||
AddChild(node, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
t.Previous.Next = t.Next;
|
||||
t.Next.Previous = t.Previous;
|
||||
if(node.Next == node)
|
||||
{
|
||||
t.Next = t.Previous = t;
|
||||
AddChild(t, node);
|
||||
node = t;
|
||||
}
|
||||
else
|
||||
{
|
||||
node.Previous.Next = t;
|
||||
node.Next.Previous = t;
|
||||
t.Next = node.Next;
|
||||
t.Previous = node.Previous;
|
||||
AddChild(t, node);
|
||||
node = t;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
trees[node.Degree] = node;
|
||||
}
|
||||
node = node.Next;
|
||||
}
|
||||
FibonacciNode<T> min = node;
|
||||
FibonacciNode<T> start = node;
|
||||
do
|
||||
{
|
||||
if(comparator(node.Value, min.Value) < 0)
|
||||
{
|
||||
min = node;
|
||||
}
|
||||
node = node.Next;
|
||||
} while (node != start);
|
||||
return min;
|
||||
}
|
||||
/// <summary>
|
||||
/// Cut node from heap.
|
||||
/// </summary>
|
||||
/// <param name="root">Root of heap.</param>
|
||||
/// <param name="node">Node to be cut.</param>
|
||||
/// <returns></returns>
|
||||
private FibonacciNode<T> Cut(FibonacciNode<T> root, FibonacciNode<T> node)
|
||||
{
|
||||
if(node.Next == node)
|
||||
{
|
||||
node.Parent.Child = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
node.Next.Previous = node.Previous;
|
||||
node.Previous.Next = node.Next;
|
||||
node.Parent.Child = node.Next;
|
||||
}
|
||||
node.Next = node.Previous = node;
|
||||
node.Marked = false;
|
||||
return Merge(root, node);
|
||||
}
|
||||
/// <summary>
|
||||
/// Decrease value of provided node substituting it with the provided value.
|
||||
/// </summary>
|
||||
/// <param name="root">Root of the heap.</param>
|
||||
/// <param name="node">Node to have value decreased.</param>
|
||||
/// <param name="value">New value of the node. It is only applied if the value is lower than the previous value.</param>
|
||||
/// <returns></returns>
|
||||
private FibonacciNode<T> DecreaseKey(FibonacciNode<T> root, FibonacciNode<T> node, T value)
|
||||
{
|
||||
if(comparator(node.Value, value) < 0)
|
||||
{
|
||||
return root;
|
||||
}
|
||||
node.Value = value;
|
||||
if(node.Parent != null)
|
||||
{
|
||||
if(comparator(node.Value, node.Parent.Value) < 0)
|
||||
{
|
||||
root = Cut(root, node);
|
||||
FibonacciNode<T> parent = node.Parent;
|
||||
node.Parent = null;
|
||||
while(parent != null && parent.Marked)
|
||||
{
|
||||
root = Cut(root, parent);
|
||||
node = parent;
|
||||
parent = node.Parent;
|
||||
node.Parent = null;
|
||||
}
|
||||
if(parent != null && parent.Parent != null)
|
||||
{
|
||||
parent.Marked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(comparator(node.Value, root.Value) < 0)
|
||||
{
|
||||
root = node;
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
/// <summary>
|
||||
/// Find the node that has the specified value in the heap.
|
||||
/// </summary>
|
||||
/// <param name="root">Root of the heap.</param>
|
||||
/// <param name="value">Value to be found.</param>
|
||||
/// <returns></returns>
|
||||
private FibonacciNode<T> Find(FibonacciNode<T> root, T value)
|
||||
{
|
||||
FibonacciNode<T> node = root;
|
||||
if(node == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
do
|
||||
{
|
||||
if(comparator(node.Value, value) == 0)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
FibonacciNode<T> ret = Find(node.Child, value);
|
||||
if(ret != null)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
node = node.Next;
|
||||
} while (node != root);
|
||||
return null;
|
||||
}
|
||||
#endregion
|
||||
#region IDisposable Support
|
||||
private bool disposedValue = false;
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (root != null)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
Remove(root);
|
||||
}
|
||||
root.Previous = root.Next = root.Parent = root.Child = null;
|
||||
root = null;
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
||||
Dispose(true);
|
||||
// TODO: uncomment the following line if the finalizer is overridden above.
|
||||
// GC.SuppressFinalize(this);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
internal class FibonacciNode<T>
|
||||
{
|
||||
#region Fields
|
||||
private FibonacciNode<T> previous;
|
||||
private FibonacciNode<T> next;
|
||||
private FibonacciNode<T> child;
|
||||
private FibonacciNode<T> parent;
|
||||
private T value;
|
||||
private int degree;
|
||||
private bool marked;
|
||||
#endregion
|
||||
#region Properties
|
||||
public FibonacciNode<T> Previous
|
||||
{
|
||||
get
|
||||
{
|
||||
return previous;
|
||||
}
|
||||
set
|
||||
{
|
||||
previous = value;
|
||||
}
|
||||
}
|
||||
public FibonacciNode<T> Next
|
||||
{
|
||||
get
|
||||
{
|
||||
return next;
|
||||
}
|
||||
set
|
||||
{
|
||||
next = value;
|
||||
}
|
||||
}
|
||||
public FibonacciNode<T> Child
|
||||
{
|
||||
get
|
||||
{
|
||||
return child;
|
||||
}
|
||||
set
|
||||
{
|
||||
child = value;
|
||||
}
|
||||
}
|
||||
public FibonacciNode<T> Parent
|
||||
{
|
||||
get
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
set
|
||||
{
|
||||
parent = value;
|
||||
}
|
||||
}
|
||||
public bool Marked
|
||||
{
|
||||
get
|
||||
{
|
||||
return marked;
|
||||
}
|
||||
set
|
||||
{
|
||||
marked = value;
|
||||
}
|
||||
}
|
||||
public T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return value;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
public int Degree
|
||||
{
|
||||
get
|
||||
{
|
||||
return degree;
|
||||
}
|
||||
set
|
||||
{
|
||||
degree = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Public Methods
|
||||
public bool HasChildren()
|
||||
{
|
||||
return child != null;
|
||||
}
|
||||
public bool HasParent()
|
||||
{
|
||||
return parent != null;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ namespace SystemExtensions.Collections
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
return binaryHeap.DeleteMin();
|
||||
return binaryHeap.RemoveMin();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -0,0 +1,467 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemExtensions
|
||||
{
|
||||
public static class Comparators
|
||||
{
|
||||
#region Fields
|
||||
private static Comparison<int> intComparison = new Comparison<int>(IntegerComparison);
|
||||
private static Comparison<float> floatComparison = new Comparison<float>(FloatComparison);
|
||||
private static Comparison<double> doubleComparison = new Comparison<double>(DoubleComparison);
|
||||
private static Comparison<bool> boolComparison = new Comparison<bool>(BoolComparison);
|
||||
private static Comparison<decimal> decimalComparison = new Comparison<decimal>(DecimalComparison);
|
||||
private static Comparison<byte> byteComparison = new Comparison<byte>(ByteComparison);
|
||||
private static Comparison<long> longComparison = new Comparison<long>(LongComparison);
|
||||
private static Comparison<uint> uintComparison = new Comparison<uint>(UintComparison);
|
||||
private static Comparison<Int16> int16Comparison = new Comparison<Int16>(Int16Comparison);
|
||||
private static Comparison<Int32> int32Comparison = new Comparison<Int32>(Int32Comparison);
|
||||
private static Comparison<Int64> int64Comparison = new Comparison<Int64>(int64Comparison);
|
||||
private static Comparison<UInt16> uInt16Comparison = new Comparison<UInt16>(uInt16Comparison);
|
||||
private static Comparison<UInt32> uInt32Comparison = new Comparison<UInt32>(uInt32Comparison);
|
||||
private static Comparison<UInt64> uInt64Comparison = new Comparison<UInt64>(uInt64Comparison);
|
||||
#endregion
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Comparison between two ints.
|
||||
/// </summary>
|
||||
public static Comparison<int> Int
|
||||
{
|
||||
get
|
||||
{
|
||||
return intComparison;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Comparison between two floats.
|
||||
/// </summary>
|
||||
public static Comparison<float> Float
|
||||
{
|
||||
get
|
||||
{
|
||||
return floatComparison;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Comparison between two doubles.
|
||||
/// </summary>
|
||||
public static Comparison<double> Double
|
||||
{
|
||||
get
|
||||
{
|
||||
return doubleComparison;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Comparison between two decimals.
|
||||
/// </summary>
|
||||
public static Comparison<decimal> Decimal
|
||||
{
|
||||
get
|
||||
{
|
||||
return decimalComparison;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Comparison between two bools.
|
||||
/// </summary>
|
||||
public static Comparison<bool> Bool
|
||||
{
|
||||
get
|
||||
{
|
||||
return boolComparison;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Comparison between two bytes.
|
||||
/// </summary>
|
||||
public static Comparison<byte> Byte
|
||||
{
|
||||
get
|
||||
{
|
||||
return byteComparison;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Comparison between two longs.
|
||||
/// </summary>
|
||||
public static Comparison<long> Long
|
||||
{
|
||||
get
|
||||
{
|
||||
return longComparison;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Comparison between two uints.
|
||||
/// </summary>
|
||||
public static Comparison<uint> Uint
|
||||
{
|
||||
get
|
||||
{
|
||||
return uintComparison;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Comparison between two int16.
|
||||
/// </summary>
|
||||
public static Comparison<Int16> Int16
|
||||
{
|
||||
get
|
||||
{
|
||||
return int16Comparison;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Comparison between two int32.
|
||||
/// </summary>
|
||||
public static Comparison<Int32> Int32
|
||||
{
|
||||
get
|
||||
{
|
||||
return int32Comparison;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Comparison between two int64.
|
||||
/// </summary>
|
||||
public static Comparison<Int64> Int64
|
||||
{
|
||||
get
|
||||
{
|
||||
return int64Comparison;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Comparison between two uint16.
|
||||
/// </summary>
|
||||
public static Comparison<UInt16> UInt16
|
||||
{
|
||||
get
|
||||
{
|
||||
return uInt16Comparison;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Comparison between two uint32.
|
||||
/// </summary>
|
||||
public static Comparison<UInt32> UInt32
|
||||
{
|
||||
get
|
||||
{
|
||||
return uInt32Comparison;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Comparison between two uint64.
|
||||
/// </summary>
|
||||
public static Comparison<UInt64> UInt64
|
||||
{
|
||||
get
|
||||
{
|
||||
return uInt64Comparison;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Private Methods
|
||||
/// <summary>
|
||||
/// Compares two UInt64.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x > y. 0 if equal and -1 if y > x.</returns>
|
||||
private static int Uint64Comparison(UInt64 x, UInt64 y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Compares two UInt32.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x > y. 0 if equal and -1 if y > x.</returns>
|
||||
private static int Uint32Comparison(UInt32 x, UInt32 y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Compares two UInt16.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x > y. 0 if equal and -1 if y > x.</returns>
|
||||
private static int Uint16Comparison(UInt16 x, UInt16 y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Compares two Int64.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x > y. 0 if equal and -1 if y > x.</returns>
|
||||
private static int Int64Comparison(Int64 x, Int64 y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Compares two UInt32.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x > y. 0 if equal and -1 if y > x.</returns>
|
||||
private static int Int32Comparison(Int32 x, Int32 y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Compares two UInt16.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x > y. 0 if equal and -1 if y > x.</returns>
|
||||
private static int Int16Comparison(Int16 x, Int16 y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Compares two uint.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x > y. 0 if equal and -1 if y > x.</returns>
|
||||
private static int UintComparison(uint x, uint y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Compares two Long.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x > y. 0 if equal and -1 if y > x.</returns>
|
||||
private static int LongComparison(long x, long y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Compares two Byte.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x > y. 0 if equal and -1 if y > x.</returns>
|
||||
private static int ByteComparison(byte x, byte y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Compares two Decimal.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x > y. 0 if equal and -1 if y > x.</returns>
|
||||
private static int DecimalComparison(decimal x, decimal y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Compares two Bool.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x is true and y is false. 0 if they are the same and -1
|
||||
/// if y is true and x is false.</returns>
|
||||
private static int BoolComparison(bool x, bool y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x == true && y == false)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Compares two Double.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x > y. 0 if equal and -1 if y > x.</returns>
|
||||
private static int DoubleComparison(double x, double y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Compares two Float.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x > y. 0 if equal and -1 if y > x.</returns>
|
||||
private static int FloatComparison(float x, float y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Compares two Integer.
|
||||
/// </summary>
|
||||
/// <param name="x">First value.</param>
|
||||
/// <param name="y">Second value.</param>
|
||||
/// <returns>Returns 1 if x > y. 0 if equal and -1 if y > x.</returns>
|
||||
private static int IntegerComparison(int x, int y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,9 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Collections\BinaryHeap.cs" />
|
||||
<Compile Include="Collections\FibonacciHeap.cs" />
|
||||
<Compile Include="Collections\PriorityQueue.cs" />
|
||||
<Compile Include="Comparators.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Threading\PriorityThreadPool.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SystemExtensions;
|
||||
|
||||
namespace SystemExtensions.Collections.Tests
|
||||
{
|
||||
@@ -77,7 +78,7 @@ namespace SystemExtensions.Collections.Tests
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
System.Diagnostics.Debug.WriteLine(binaryHeap.DeleteMin());
|
||||
System.Diagnostics.Debug.WriteLine(binaryHeap.RemoveMin());
|
||||
tries--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SystemExtensions.Collections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
|
||||
namespace SystemExtensions.Collections.Tests
|
||||
{
|
||||
[TestClass()]
|
||||
public class FibonacciHeapTests
|
||||
{
|
||||
private static int IntegerComparison(int x, int y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
FibonacciHeap<int> fibonacciHeap = new FibonacciHeap<int>(new Comparison<int>(IntegerComparison));
|
||||
[TestMethod()]
|
||||
public void InsertTest()
|
||||
{
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
fibonacciHeap.Insert(i);
|
||||
}
|
||||
if (fibonacciHeap.RemoveMinimum() != 0)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
for (int i = 1; i < 1000; i++)
|
||||
{
|
||||
if (!fibonacciHeap.Contains(i))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void FibonacciHeapTest()
|
||||
{
|
||||
fibonacciHeap.Dispose();
|
||||
fibonacciHeap = new FibonacciHeap<int>(new Comparison<int>(IntegerComparison));
|
||||
if(fibonacciHeap.Count != 0)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void MergeTest()
|
||||
{
|
||||
fibonacciHeap.Dispose();
|
||||
FibonacciHeap<int> fibonacciHeap1 = new FibonacciHeap<int>(new Comparison<int>(IntegerComparison));
|
||||
FibonacciHeap<int> fibonacciHeap2 = new FibonacciHeap<int>(new Comparison<int>(IntegerComparison));
|
||||
|
||||
for(int i = 0; i < 100; i++)
|
||||
{
|
||||
fibonacciHeap1.Insert(i);
|
||||
}
|
||||
|
||||
for(int i = 100; i < 300; i++)
|
||||
{
|
||||
fibonacciHeap2.Insert(i);
|
||||
}
|
||||
|
||||
fibonacciHeap1.Merge(fibonacciHeap2);
|
||||
for(int i = 1; i < 300; i++)
|
||||
{
|
||||
if (!fibonacciHeap1.Contains(i))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void RemoveMinimumTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
fibonacciHeap.RemoveMinimum();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch(IndexOutOfRangeException exception)
|
||||
{
|
||||
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
fibonacciHeap.Insert(i);
|
||||
}
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
if (fibonacciHeap.RemoveMinimum() != i)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void DecreaseKeyTest()
|
||||
{
|
||||
fibonacciHeap.Insert(5);
|
||||
fibonacciHeap.Insert(10);
|
||||
fibonacciHeap.Insert(7);
|
||||
fibonacciHeap.DecreaseKey(5, 3);
|
||||
if(fibonacciHeap.Contains(5) || !fibonacciHeap.Contains(3))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
fibonacciHeap.DecreaseKey(10, 1);
|
||||
if(fibonacciHeap.RemoveMinimum() != 1)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void ContainsTest()
|
||||
{
|
||||
for(int i = 0; i < 10000; i++)
|
||||
{
|
||||
fibonacciHeap.Insert(i);
|
||||
}
|
||||
if (!fibonacciHeap.Contains(5124))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void ClearTest()
|
||||
{
|
||||
for(int i = 0; i < 10000; i++)
|
||||
{
|
||||
fibonacciHeap.Insert(i);
|
||||
}
|
||||
fibonacciHeap.RemoveMinimum();
|
||||
fibonacciHeap.Clear();
|
||||
if(fibonacciHeap.Count > 0)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void DisposeTest()
|
||||
{
|
||||
List<FibonacciHeap<int>> heaps = new List<Collections.FibonacciHeap<int>>();
|
||||
for(int i = 0; i < 10; i++)
|
||||
{
|
||||
heaps.Add(new Collections.FibonacciHeap<int>(new Comparison<int>(IntegerComparison)));
|
||||
for(int j = 0; j < 10000; j++)
|
||||
{
|
||||
heaps[heaps.Count - 1].Insert(j);
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < 10; i++)
|
||||
{
|
||||
heaps[i].Dispose();
|
||||
}
|
||||
GC.Collect();
|
||||
heaps.Clear();
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void ToArrayTest()
|
||||
{
|
||||
for(int i = 999; i >= 0; i--)
|
||||
{
|
||||
fibonacciHeap.Insert(i);
|
||||
}
|
||||
fibonacciHeap.RemoveMinimum();
|
||||
int[] arr = fibonacciHeap.ToArray();
|
||||
|
||||
for(int i = 1; i < 512; i++)
|
||||
{
|
||||
if(arr[i - 1] != i)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SystemExtensions;
|
||||
|
||||
namespace SystemExtensions.Collections.Tests
|
||||
{
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="Collections\BinaryHeapTests.cs" />
|
||||
<Compile Include="Collections\FibonacciHeapTests.cs" />
|
||||
<Compile Include="Collections\PriorityQueueTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Threading\PriorityThreadPoolTests.cs" />
|
||||
|
||||
Reference in New Issue
Block a user