From df2c4df71c5b6ac05bd9e828c8679e5bb12550b2 Mon Sep 17 00:00:00 2001 From: Mohamed Fazrin Date: Wed, 12 Oct 2022 09:20:08 +0300 Subject: [PATCH 1/5] All Projects updated to .NET 6, redundant code removed and old syntax changed to new style --- Algorithms/Algorithms.csproj | 3 +- Algorithms/Search/BinarySearcher.cs | 12 +- Algorithms/Sorting/BinarySearchTreeSorter.cs | 4 +- Algorithms/Strings/EditDistance.cs | 4 +- Algorithms/Trees/BinaryTreeRecursiveWalker.cs | 50 ++--- DataStructures/Common/Helpers.cs | 2 +- DataStructures/Common/PrimesList.cs | 10 +- DataStructures/DataStructures.csproj | 3 +- .../Dictionaries/ChainedHashTable.cs | 52 ++--- .../Dictionaries/CuckooHashTable.cs | 8 +- .../Dictionaries/OpenAddressingHashTable.cs | 38 ++-- .../Dictionaries/OpenScatterHashTable.cs | 38 +--- DataStructures/Graphs/CliqueGraph.cs | 77 ++----- DataStructures/Graphs/DirectedDenseGraph.cs | 31 +-- DataStructures/Graphs/DirectedSparseGraph.cs | 33 +-- .../Graphs/DirectedWeightedDenseGraph.cs | 5 +- .../Graphs/DirectedWeightedSparseGraph.cs | 33 +-- DataStructures/Graphs/UndirectedDenseGraph.cs | 33 +-- .../Graphs/UndirectedSparseGraph.cs | 31 +-- .../Graphs/UndirectedWeightedDenseGraph.cs | 5 +- .../Graphs/UndirectedWeightedSparseGraph.cs | 33 +-- DataStructures/Graphs/UnweightedEdge.cs | 10 +- DataStructures/Graphs/WeightedEdge.cs | 5 +- DataStructures/Hashing/PrimeHashingFamily.cs | 5 +- .../Hashing/UniversalHashingFamily.cs | 5 +- DataStructures/Heaps/BinaryMaxHeap.cs | 18 +- DataStructures/Heaps/BinaryMinHeap.cs | 18 +- DataStructures/Heaps/BinomialMinHeap.cs | 38 ++-- DataStructures/Heaps/KeyedPriorityQueue.cs | 24 +-- DataStructures/Heaps/MinPriorityQueue.cs | 20 +- DataStructures/Lists/ArrayList.cs | 51 ++--- DataStructures/Lists/CircularBuffer.cs | 54 ++--- DataStructures/Lists/DLinkedList.cs | 72 ++----- DataStructures/Lists/DLinkedList_KeyValue.cs | 67 ++---- DataStructures/Lists/Queue.cs | 14 +- DataStructures/Lists/SLinkedList.cs | 78 +++---- DataStructures/Lists/SkipList.cs | 50 ++--- DataStructures/Lists/SkipListNode.cs | 18 +- DataStructures/Lists/Stack.cs | 12 +- .../SortedCollections/SortedDictionary.cs | 21 +- .../SortedCollections/SortedList.cs | 47 ++--- DataStructures/Trees/AVLTree.cs | 16 +- DataStructures/Trees/AVLTreeNode.cs | 22 +- .../Trees/AugmentedBinarySearchTree.cs | 54 +++-- DataStructures/Trees/BTree.cs | 199 ++++++++---------- DataStructures/Trees/BinarySearchTree.cs | 59 ++---- DataStructures/Trees/BinarySearchTreeMap.cs | 63 ++---- .../Trees/BinarySearchTreeMapNode.cs | 74 ++----- DataStructures/Trees/BinarySearchTreeNode.cs | 71 ++----- DataStructures/Trees/RedBlackTree.cs | 30 +-- DataStructures/Trees/RedBlackTreeMap.cs | 30 +-- DataStructures/Trees/RedBlackTreeMapNode.cs | 43 ++-- DataStructures/Trees/RedBlackTreeNode.cs | 43 ++-- DataStructures/Trees/TernaryTreeNode.cs | 14 +- DataStructures/Trees/Trie.cs | 10 +- DataStructures/Trees/TrieMap.cs | 36 ++-- DataStructures/Trees/TrieMapNode.cs | 2 +- DataStructures/Trees/TrieNode.cs | 2 +- .../DataStructuresTests/CircularBufferTest.cs | 2 +- .../DataStructuresTests/CliqueGraphTest.cs | 10 +- UnitTest/UnitTest.csproj | 12 +- global.json | 7 + 62 files changed, 634 insertions(+), 1297 deletions(-) create mode 100644 global.json diff --git a/Algorithms/Algorithms.csproj b/Algorithms/Algorithms.csproj index 28974149..d453a958 100644 --- a/Algorithms/Algorithms.csproj +++ b/Algorithms/Algorithms.csproj @@ -1,6 +1,7 @@  - netcoreapp2.0 + net6.0 + 10 diff --git a/Algorithms/Search/BinarySearcher.cs b/Algorithms/Search/BinarySearcher.cs index 52430e68..918efc6a 100644 --- a/Algorithms/Search/BinarySearcher.cs +++ b/Algorithms/Search/BinarySearcher.cs @@ -17,13 +17,7 @@ public class BinarySearcher : IEnumerator /// /// The value of the current item /// - public T Current - { - get - { - return _collection[_currentItemIndex]; - } - } + public T Current => _collection[_currentItemIndex]; object IEnumerator.Current => Current; @@ -77,7 +71,7 @@ public int BinarySearch(T item) /// true if iteration can proceed to the next item, false otherwise public bool MoveNext() { - _currentItemIndex = this._leftIndex + (this._rightIndex - this._leftIndex) / 2; + _currentItemIndex = _leftIndex + (_rightIndex - _leftIndex) / 2; if (_comparer.Compare(_item, Current) < 0) { @@ -96,7 +90,7 @@ public bool MoveNext() public void Reset() { - this._currentItemIndex = -1; + _currentItemIndex = -1; _leftIndex = 0; _rightIndex = _collection.Count - 1; } diff --git a/Algorithms/Sorting/BinarySearchTreeSorter.cs b/Algorithms/Sorting/BinarySearchTreeSorter.cs index 795c6b40..2c1ac437 100644 --- a/Algorithms/Sorting/BinarySearchTreeSorter.cs +++ b/Algorithms/Sorting/BinarySearchTreeSorter.cs @@ -93,7 +93,7 @@ private class Node : IComparable> where T : IComparable public Node() { - Value = default(T); + Value = default; Parent = null; Left = null; Right = null; @@ -102,7 +102,7 @@ public Node() public int CompareTo(Node other) { if (other == null) return -1; - return this.Value.CompareTo(other.Value); + return Value.CompareTo(other.Value); } } } diff --git a/Algorithms/Strings/EditDistance.cs b/Algorithms/Strings/EditDistance.cs index af1a81f5..9238c8fe 100644 --- a/Algorithms/Strings/EditDistance.cs +++ b/Algorithms/Strings/EditDistance.cs @@ -66,7 +66,7 @@ public static Int32 GetMinDistance(string source, string destination, EditDistan deletionCost: Convert.ToInt64(distances.DeletionCost), substitutionCost: Convert.ToInt64(distances.InsertionCost)); - return Convert.ToInt32(EditDistance.GetMinDistance(source, destination, longDistance)); + return Convert.ToInt32(GetMinDistance(source, destination, longDistance)); } /// @@ -82,7 +82,7 @@ public static Int16 GetMinDistance(string source, string destination, EditDistan deletionCost: Convert.ToInt64(distances.DeletionCost), substitutionCost: Convert.ToInt64(distances.InsertionCost)); - return Convert.ToInt16(EditDistance.GetMinDistance(source, destination, longDistance)); + return Convert.ToInt16(GetMinDistance(source, destination, longDistance)); } } diff --git a/Algorithms/Trees/BinaryTreeRecursiveWalker.cs b/Algorithms/Trees/BinaryTreeRecursiveWalker.cs index 97fd45e0..e1f95c7d 100644 --- a/Algorithms/Trees/BinaryTreeRecursiveWalker.cs +++ b/Algorithms/Trees/BinaryTreeRecursiveWalker.cs @@ -35,8 +35,8 @@ private static void PreOrderVisitor(BSTNode BinaryTreeRoot, Action Acti return; Action(BinaryTreeRoot.Value); - BinaryTreeRecursiveWalker.PreOrderVisitor(BinaryTreeRoot.LeftChild, Action); - BinaryTreeRecursiveWalker.PreOrderVisitor(BinaryTreeRoot.RightChild, Action); + PreOrderVisitor(BinaryTreeRoot.LeftChild, Action); + PreOrderVisitor(BinaryTreeRoot.RightChild, Action); } /// @@ -47,9 +47,9 @@ private static void InOrderVisitor(BSTNode BinaryTreeRoot, Action Actio if (BinaryTreeRoot == null) return; - BinaryTreeRecursiveWalker.InOrderVisitor(BinaryTreeRoot.LeftChild, Action); + InOrderVisitor(BinaryTreeRoot.LeftChild, Action); Action(BinaryTreeRoot.Value); - BinaryTreeRecursiveWalker.InOrderVisitor(BinaryTreeRoot.RightChild, Action); + InOrderVisitor(BinaryTreeRoot.RightChild, Action); } /// @@ -60,8 +60,8 @@ private static void PostOrderVisitor(BSTNode BinaryTreeRoot, Action Act if (BinaryTreeRoot == null) return; - BinaryTreeRecursiveWalker.PostOrderVisitor(BinaryTreeRoot.LeftChild, Action); - BinaryTreeRecursiveWalker.PostOrderVisitor(BinaryTreeRoot.RightChild, Action); + PostOrderVisitor(BinaryTreeRoot.LeftChild, Action); + PostOrderVisitor(BinaryTreeRoot.RightChild, Action); Action(BinaryTreeRoot.Value); } @@ -109,13 +109,13 @@ private static bool InOrderSearcher(BSTNode BinaryTreeRoot, T Value, bool if (IsBinarySearchTree == true) { if (hasLeft && current.IsGreaterThan(Value)) - return BinaryTreeRecursiveWalker.InOrderSearcher(BinaryTreeRoot.LeftChild, Value); + return InOrderSearcher(BinaryTreeRoot.LeftChild, Value); if (current.IsEqualTo(Value)) return true; if (hasRight && current.IsLessThan(Value)) - return BinaryTreeRecursiveWalker.InOrderSearcher(BinaryTreeRoot.RightChild, Value); + return InOrderSearcher(BinaryTreeRoot.RightChild, Value); } else { @@ -144,10 +144,10 @@ private static bool PostOrderSearcher(BSTNode BinaryTreeRoot, T Value, boo if (IsBinarySearchTree == true) { if (hasLeft && current.IsGreaterThan(Value)) - return BinaryTreeRecursiveWalker.PostOrderSearcher(BinaryTreeRoot.LeftChild, Value); + return PostOrderSearcher(BinaryTreeRoot.LeftChild, Value); if (hasRight && current.IsLessThan(Value)) - return BinaryTreeRecursiveWalker.PostOrderSearcher(BinaryTreeRoot.RightChild, Value); + return PostOrderSearcher(BinaryTreeRoot.RightChild, Value); if (current.IsEqualTo(Value)) return true; @@ -183,10 +183,10 @@ public static void PrintAll(BSTNode BinaryTreeRoot, TraversalMode Mode=Tra throw new ArgumentNullException("Tree root cannot be null."); var printAction = new Action((T nodeValue) => - System.Console.Write(String.Format("{0} ", nodeValue))); + Console.Write(String.Format("{0} ", nodeValue))); - BinaryTreeRecursiveWalker.ForEach(BinaryTreeRoot, printAction, Mode); - System.Console.WriteLine(); + ForEach(BinaryTreeRoot, printAction, Mode); + Console.WriteLine(); } /// @@ -205,16 +205,16 @@ public static void ForEach(BSTNode BinaryTreeRoot, Action Action, Trave switch (Mode) { case TraversalMode.PreOrder: - BinaryTreeRecursiveWalker.PreOrderVisitor(BinaryTreeRoot, Action); + PreOrderVisitor(BinaryTreeRoot, Action); return; case TraversalMode.InOrder: - BinaryTreeRecursiveWalker.InOrderVisitor(BinaryTreeRoot, Action); + InOrderVisitor(BinaryTreeRoot, Action); return; case TraversalMode.PostOrder: - BinaryTreeRecursiveWalker.PostOrderVisitor(BinaryTreeRoot, Action); + PostOrderVisitor(BinaryTreeRoot, Action); return; default: - BinaryTreeRecursiveWalker.InOrderVisitor(BinaryTreeRoot, Action); + InOrderVisitor(BinaryTreeRoot, Action); return; } } @@ -233,13 +233,13 @@ public static bool Contains(BSTNode BinaryTreeRoot, T Value, TraversalMode switch (Mode) { case TraversalMode.PreOrder: - return BinaryTreeRecursiveWalker.PreOrderSearcher(BinaryTreeRoot, Value); + return PreOrderSearcher(BinaryTreeRoot, Value); case TraversalMode.InOrder: - return BinaryTreeRecursiveWalker.InOrderSearcher(BinaryTreeRoot, Value); + return InOrderSearcher(BinaryTreeRoot, Value); case TraversalMode.PostOrder: - return BinaryTreeRecursiveWalker.PostOrderSearcher(BinaryTreeRoot, Value); + return PostOrderSearcher(BinaryTreeRoot, Value); default: - return BinaryTreeRecursiveWalker.InOrderSearcher(BinaryTreeRoot, Value); + return InOrderSearcher(BinaryTreeRoot, Value); } } @@ -257,13 +257,13 @@ public static bool BinarySearch(BSTNode BinaryTreeRoot, T Value, Traversal switch (Mode) { case TraversalMode.PreOrder: - return BinaryTreeRecursiveWalker.PreOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree: true); + return PreOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree: true); case TraversalMode.InOrder: - return BinaryTreeRecursiveWalker.InOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree: true); + return InOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree: true); case TraversalMode.PostOrder: - return BinaryTreeRecursiveWalker.PostOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree:true); + return PostOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree:true); default: - return BinaryTreeRecursiveWalker.InOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree: true); + return InOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree: true); } } diff --git a/DataStructures/Common/Helpers.cs b/DataStructures/Common/Helpers.cs index e1a3ab66..8b34684b 100644 --- a/DataStructures/Common/Helpers.cs +++ b/DataStructures/Common/Helpers.cs @@ -53,7 +53,7 @@ public static string PadCenter(this string text, int newWidth, char fillerCharac /// /// Populates the specified two-dimensional with a default value. /// - public static void Populate(this T[,] array, int rows, int columns, T defaultValue = default(T)) + public static void Populate(this T[,] array, int rows, int columns, T defaultValue = default) { for (int i = 0; i < rows; ++i) { diff --git a/DataStructures/Common/PrimesList.cs b/DataStructures/Common/PrimesList.cs index 1f47c946..5a9d1c23 100644 --- a/DataStructures/Common/PrimesList.cs +++ b/DataStructures/Common/PrimesList.cs @@ -93,10 +93,7 @@ private static void _initializeData() /// /// Return count of primes. /// - public int Count - { - get { return _primes.Count; } - } + public int Count => _primes.Count; /// /// Returns prime number at the specified index. @@ -186,10 +183,7 @@ public int GetPreviousPrime(int number) /// /// Returns the read-only IList of primes /// - public IList GetAll - { - get { return _primes.AsReadOnly(); } - } + public IList GetAll => _primes.AsReadOnly(); /// /// Copy the primes list to an array, starting from a specified index. diff --git a/DataStructures/DataStructures.csproj b/DataStructures/DataStructures.csproj index 0a534884..3288f419 100644 --- a/DataStructures/DataStructures.csproj +++ b/DataStructures/DataStructures.csproj @@ -1,6 +1,7 @@  - netcoreapp2.0 + net6.0 + 10 diff --git a/DataStructures/Dictionaries/ChainedHashTable.cs b/DataStructures/Dictionaries/ChainedHashTable.cs index cfc2330d..2d135928 100644 --- a/DataStructures/Dictionaries/ChainedHashTable.cs +++ b/DataStructures/Dictionaries/ChainedHashTable.cs @@ -30,7 +30,7 @@ public enum CapacityManagementMode /// INSTANCE VARIABLES. /// private int _size; - private int _freeSlotsCount; + private decimal _slotsLoadFactor; private const int _defaultCapacity = 8; private DLinkedList[] _hashTableStore; @@ -54,14 +54,13 @@ public enum CapacityManagementMode /// public ChainedHashTable() { - this._size = 0; - this._hashTableStore = new DLinkedList[_defaultCapacity]; - this._freeSlotsCount = this._hashTableStore.Length; - this._keysComparer = EqualityComparer.Default; - this._valuesComparer = EqualityComparer.Default; - - this._keysCollection = new List(); - this._valuesCollection = new List(); + _size = 0; + _hashTableStore = new DLinkedList[_defaultCapacity]; + _keysComparer = EqualityComparer.Default; + _valuesComparer = EqualityComparer.Default; + + _keysCollection = new List(); + _valuesCollection = new List(); } @@ -71,7 +70,6 @@ public ChainedHashTable() private void _rehash(ref DLinkedList[] newHashTableStore, int oldHashTableSize) { // Reset the free slots count - this._freeSlotsCount = newHashTableStore.Length; for (int i = 0; i < oldHashTableSize; ++i) { @@ -87,7 +85,6 @@ private void _rehash(ref DLinkedList[] newHashTableStore, int oldH if (newHashTableStore[hash] == null) { - _freeSlotsCount--; newHashTableStore[hash] = new DLinkedList(); } @@ -216,7 +213,7 @@ private uint _divisionMethodHashFunction(TKey key, int length) if (length < 0) throw new IndexOutOfRangeException(); - if (key is string && key.IsEqualTo(default(TKey)) == false) + if (key is string && key.IsEqualTo(default) == false) { var stringKey = Convert.ToString(key); @@ -266,26 +263,17 @@ private uint _getHashOfKey(TKey key) /// /// Return count of elements in the hash table. /// - public int Count - { - get { return _size; } - } + public int Count => _size; /// /// Checks if the hash table is readonly. /// - public bool IsReadOnly - { - get { return false; } - } + public bool IsReadOnly => false; /// /// Checks if the hash table is empty. /// - public bool IsEmpty - { - get { return Count == 0; } - } + public bool IsEmpty => Count == 0; /// /// Checks whether key exists in the hash table. @@ -336,18 +324,12 @@ public bool Contains(KeyValuePair item) /// /// List of hash table keys. /// - public ICollection Keys - { - get { return _keysCollection; } - } + public ICollection Keys => _keysCollection; /// /// List of hash table values. /// - public ICollection Values - { - get { return _valuesCollection; } - } + public ICollection Values => _valuesCollection; /// @@ -374,7 +356,7 @@ public bool TryGetValue(TKey key, out TValue value) } // NOT FOUND - value = default(TValue); + value = default; return false; } @@ -439,7 +421,6 @@ public void Add(TKey key, TValue value) _hashTableStore[hashcode] = new DLinkedList(); // Decrease the number of free slots. - _freeSlotsCount--; } else if (_hashTableStore[hashcode].Count > 0) { @@ -500,7 +481,6 @@ public bool Remove(TKey key) _hashTableStore[hashcode] = null; // Increase the number of free slots. - _freeSlotsCount++; // Capacity management _ensureCapacity(CapacityManagementMode.Contract); @@ -549,7 +529,6 @@ public bool Remove(KeyValuePair item) _hashTableStore[hashcode] = null; // Increase the number of free slots. - _freeSlotsCount++; // Capacity management _ensureCapacity(CapacityManagementMode.Contract); @@ -623,7 +602,6 @@ public void Clear() _size = 0; _slotsLoadFactor = 0; - _freeSlotsCount = _hashTableStore.Length; } diff --git a/DataStructures/Dictionaries/CuckooHashTable.cs b/DataStructures/Dictionaries/CuckooHashTable.cs index 8d8579c6..53711cc1 100644 --- a/DataStructures/Dictionaries/CuckooHashTable.cs +++ b/DataStructures/Dictionaries/CuckooHashTable.cs @@ -28,7 +28,7 @@ private class CHashEntry where TKey : IComparable public TValue Value { get; set; } public bool IsActive { get; set; } - public CHashEntry() : this(default(TKey), default(TValue), false) { } + public CHashEntry() : this(default, default, false) { } public CHashEntry(TKey key, TValue value, bool isActive) { @@ -117,11 +117,11 @@ private void _rehash(int newCapacity) int primeCapacity = PRIMES.GetNextPrime(newCapacity); var oldSize = _size; - var oldCollection = this._collection; + var oldCollection = _collection; try { - this._collection = new CHashEntry[newCapacity]; + _collection = new CHashEntry[newCapacity]; // Reset size _size = 0; @@ -351,7 +351,7 @@ public bool Remove(TKey key) /// public void Clear() { - this._size = 0; + _size = 0; Parallel.ForEach(_collection, (item) => diff --git a/DataStructures/Dictionaries/OpenAddressingHashTable.cs b/DataStructures/Dictionaries/OpenAddressingHashTable.cs index c9191f41..d24b9513 100644 --- a/DataStructures/Dictionaries/OpenAddressingHashTable.cs +++ b/DataStructures/Dictionaries/OpenAddressingHashTable.cs @@ -54,7 +54,7 @@ public OpenAddressingHashTable(int size) for (int i = 0; i < _table.Length; i++) { //initialize each slot - _table[i] = new OAHashEntry(default(TKey), default(TValue), false); + _table[i] = new OAHashEntry(default, default, false); } } @@ -70,7 +70,7 @@ private void _expand() for (int i = 0; i < exp.Length; i++) { //initialize each slot - exp[i] = new OAHashEntry(default(TKey), default(TValue), false); + exp[i] = new OAHashEntry(default, default, false); } _inTable = 0; @@ -95,7 +95,7 @@ private void _rehash() for (int i = 0; i < rehash.Length; i++) { //initialize each slot - rehash[i] = new OAHashEntry(default(TKey), default(TValue), false); + rehash[i] = new OAHashEntry(default, default, false); } _inTable = 0; @@ -252,8 +252,8 @@ public bool Remove(TKey key) _keys.Clear(); _values.Clear(); - _table[index].key = default(TKey); - _table[index].value = default(TValue); + _table[index].key = default; + _table[index].value = default; _table[index].occupied = false; //number of items in the table decreases @@ -280,8 +280,8 @@ public void Clear() _values.Clear(); for (int i = 0; i < _table.Length; i++) { - _table[i].key = default(TKey); - _table[i].value = default(TValue); + _table[i].key = default; + _table[i].value = default; _table[i].occupied = false; } _inTable = 0; @@ -300,7 +300,7 @@ public bool TryGetValue(TKey key, out TValue value) } //not found - value = default(TValue); + value = default; return false; } @@ -313,7 +313,7 @@ public int search(TKey key) { //calculate index int index = _double_hash(key, i); - if (IComparable.Equals(_table[index].key, key)) + if (Equals(_table[index].key, key)) { return index; } @@ -346,28 +346,16 @@ public bool Contains(KeyValuePair item) } //returns the number of items in the table - public int Count - { - get { return _inTable;} - } + public int Count => _inTable; //returns bool depending on whether or not the table is read only - public bool IsReadOnly - { - get { return false; } - } + public bool IsReadOnly => false; //returns a list of keys in the table - public ICollection Keys - { - get { return _keys; } - } + public ICollection Keys => _keys; //returns a list of values in the table - public ICollection Values - { - get { return _values; } - } + public ICollection Values => _values; //---------------------------------------------------------------------- //-----------------------NOT IMPLEMENTED YET---------------------------- diff --git a/DataStructures/Dictionaries/OpenScatterHashTable.cs b/DataStructures/Dictionaries/OpenScatterHashTable.cs index a220c72f..efc11f6d 100644 --- a/DataStructures/Dictionaries/OpenScatterHashTable.cs +++ b/DataStructures/Dictionaries/OpenScatterHashTable.cs @@ -19,7 +19,7 @@ private class HashTableEntry where TKey : IComparable public TValue Value { get; set; } public EntryStatus Status { get; set; } - public HashTableEntry() : this(default(TKey), default(TValue)) { } + public HashTableEntry() : this(default, default) { } public HashTableEntry(TKey key, TValue value, EntryStatus status = EntryStatus.Occupied) { Key = key; @@ -27,11 +27,11 @@ public HashTableEntry(TKey key, TValue value, EntryStatus status = EntryStatus.O Status = status; } - public bool IsEmpty { get { return this.Status == EntryStatus.Empty; } } + public bool IsEmpty => Status == EntryStatus.Empty; - public bool IsOccupied { get { return this.Status == EntryStatus.Occupied; } } + public bool IsOccupied => Status == EntryStatus.Occupied; - public bool IsDeleted { get { return this.Status == EntryStatus.Deleted; } } + public bool IsDeleted => Status == EntryStatus.Deleted; } @@ -203,10 +203,7 @@ public bool ContainsKey(TKey key) throw new NotImplementedException(); } - public ICollection Keys - { - get { throw new NotImplementedException(); } - } + public ICollection Keys => throw new NotImplementedException(); public bool Remove(TKey key) { @@ -218,21 +215,12 @@ public bool TryGetValue(TKey key, out TValue value) throw new NotImplementedException(); } - public ICollection Values - { - get { throw new NotImplementedException(); } - } + public ICollection Values => throw new NotImplementedException(); public TValue this[TKey key] { - get - { - throw new NotImplementedException(); - } - set - { - throw new NotImplementedException(); - } + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); } public void Add(KeyValuePair item) @@ -255,15 +243,9 @@ public void CopyTo(KeyValuePair[] array, int arrayIndex) throw new NotImplementedException(); } - public int Count - { - get { throw new NotImplementedException(); } - } + public int Count => throw new NotImplementedException(); - public bool IsReadOnly - { - get { throw new NotImplementedException(); } - } + public bool IsReadOnly => throw new NotImplementedException(); public bool Remove(KeyValuePair item) { diff --git a/DataStructures/Graphs/CliqueGraph.cs b/DataStructures/Graphs/CliqueGraph.cs index 2d075564..03c76a3d 100644 --- a/DataStructures/Graphs/CliqueGraph.cs +++ b/DataStructures/Graphs/CliqueGraph.cs @@ -235,7 +235,7 @@ int IEqualityComparer>.GetHashCode(UnordererPair obj) ISet> getPairs(ICollection vertices) { T[] arr = new T[vertices.Count]; - ISet> ret = new System.Collections.Generic.HashSet>(new PairComparer()); + ISet> ret = new HashSet>(new PairComparer()); vertices.CopyTo(arr, 0); for (int i = 0; i < vertices.Count; i++) { @@ -476,9 +476,9 @@ public bool HasVertex(T vertex) /// Returns the neighbours doubly-linked list for the specified vertex. /// /// Vertex. - public DataStructures.Lists.DLinkedList Neighbours(T vertex) + public DLinkedList Neighbours(T vertex) { - DataStructures.Lists.DLinkedList returnList = new DataStructures.Lists.DLinkedList(); + DLinkedList returnList = new DLinkedList(); foreach (var c in _cliques) { @@ -538,45 +538,21 @@ public void Clear() /// Returns true, if graph is directed; false otherwise. /// /// true if this instance is directed; otherwise, false. - public bool IsDirected - { - get - { - return false; - } - } + public bool IsDirected => false; /// /// Returns true, if graph is weighted; false otherwise. /// /// true if this instance is weighted; otherwise, false. - public bool IsWeighted - { - get - { - return false; - } - } + public bool IsWeighted => false; /// /// Gets the count of vetices. /// /// The vertices count. - public int VerticesCount - { - get - { - return _vertices.Count; - } - } + public int VerticesCount => _vertices.Count; - public int EdgesCount - { - get - { - return getEdges().Count; - } - } + public int EdgesCount => getEdges().Count; /// /// Returns the list of edges. @@ -598,25 +574,13 @@ ICollection> getEdges() /// Returns the list of Vertices. /// /// The vertices. - IEnumerable IGraph.Vertices - { - get - { - return _vertices; - } - } + IEnumerable IGraph.Vertices => _vertices; /// /// Returns the list of Vertices. /// /// The vertices. - public ICollection Vertices - { - get - { - return _vertices; - } - } + public ICollection Vertices => _vertices; /// /// Gets the cloud of a collection of vetices. @@ -691,27 +655,16 @@ public ICollection GetConnectedComponent(T vertex) /// Returns the list of maximal cliques /// /// The get cliques. - public IReadOnlyCollection getCliques - { - get - { - // TODO: getCliques, this does not return all the maximal cliques; - // only return enough of them. - return (IReadOnlyCollection)_cliques; - } - } + public IReadOnlyCollection getCliques => + // TODO: getCliques, this does not return all the maximal cliques; + // only return enough of them. + (IReadOnlyCollection)_cliques; /// /// Returns the clique number of the current graph. /// /// The clique number. - public int cliqueNumber - { - get - { - return Pick(getMaximumCliques).Count; - } - } + public int cliqueNumber => Pick(getMaximumCliques).Count; /// /// Returns the collection of the maxium-sized cliques @@ -804,7 +757,7 @@ public IEnumerable ReturnPathFromCliquePath(IEnumerable path) intersection = new HashSet(listPath[i]); intersection.IntersectWith(listPath[i + 1]); // intersection is never empty because 'path' should be a path in a dual graph. - returnPath.Add(CliqueGraph.Pick(intersection)); + returnPath.Add(Pick(intersection)); } return returnPath; diff --git a/DataStructures/Graphs/DirectedDenseGraph.cs b/DataStructures/Graphs/DirectedDenseGraph.cs index 264dff1c..1b509efd 100644 --- a/DataStructures/Graphs/DirectedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedDenseGraph.cs @@ -59,34 +59,22 @@ protected virtual bool _doesEdgeExist(int source, int destination) /// /// Returns true, if graph is directed; false otherwise. /// - public virtual bool IsDirected - { - get { return true; } - } + public virtual bool IsDirected => true; /// /// Returns true, if graph is weighted; false otherwise. /// - public virtual bool IsWeighted - { - get { return false; } - } + public virtual bool IsWeighted => false; /// /// Gets the count of vetices. /// - public virtual int VerticesCount - { - get { return _verticesCount; } - } + public virtual int VerticesCount => _verticesCount; /// /// Gets the count of edges. /// - public virtual int EdgesCount - { - get { return _edgesCount; } - } + public virtual int EdgesCount => _edgesCount; /// /// Returns the list of Vertices. @@ -102,19 +90,16 @@ public virtual IEnumerable Vertices } - IEnumerable> IGraph.Edges - { - get { return this.Edges; } - } + IEnumerable> IGraph.Edges => Edges; IEnumerable> IGraph.IncomingEdges(T vertex) { - return this.IncomingEdges(vertex); + return IncomingEdges(vertex); } IEnumerable> IGraph.OutgoingEdges(T vertex) { - return this.OutgoingEdges(vertex); + return OutgoingEdges(vertex); } @@ -337,7 +322,7 @@ public virtual bool HasVertex(T vertex) /// /// Returns the neighbours doubly-linked list for the specified vertex. /// - public virtual DataStructures.Lists.DLinkedList Neighbours(T vertex) + public virtual DLinkedList Neighbours(T vertex) { var neighbors = new DLinkedList(); int source = _vertices.IndexOf(vertex); diff --git a/DataStructures/Graphs/DirectedSparseGraph.cs b/DataStructures/Graphs/DirectedSparseGraph.cs index e8ce7df9..9b821208 100644 --- a/DataStructures/Graphs/DirectedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedSparseGraph.cs @@ -50,34 +50,22 @@ protected virtual bool _doesEdgeExist(T vertex1, T vertex2) /// /// Returns true, if graph is directed; false otherwise. /// - public virtual bool IsDirected - { - get { return true; } - } + public virtual bool IsDirected => true; /// /// Returns true, if graph is weighted; false otherwise. /// - public virtual bool IsWeighted - { - get { return false; } - } + public virtual bool IsWeighted => false; /// /// Gets the count of vetices. /// - public virtual int VerticesCount - { - get { return _adjacencyList.Count; } - } + public virtual int VerticesCount => _adjacencyList.Count; /// /// Gets the count of edges. /// - public virtual int EdgesCount - { - get { return _edgesCount; } - } + public virtual int EdgesCount => _edgesCount; /// /// Returns the list of Vertices. @@ -92,19 +80,16 @@ public virtual IEnumerable Vertices } - IEnumerable> IGraph.Edges - { - get { return this.Edges; } - } + IEnumerable> IGraph.Edges => Edges; IEnumerable> IGraph.IncomingEdges(T vertex) { - return this.IncomingEdges(vertex); + return IncomingEdges(vertex); } IEnumerable> IGraph.OutgoingEdges(T vertex) { - return this.OutgoingEdges(vertex); + return OutgoingEdges(vertex); } @@ -341,7 +326,7 @@ public virtual IEnumerable DepthFirstWalk(T source) throw new KeyNotFoundException("The source vertex doesn't exist."); var visited = new HashSet(); - var stack = new DataStructures.Lists.Stack(); + var stack = new Lists.Stack(); var listOfNodes = new ArrayList(VerticesCount); stack.Push(source); @@ -386,7 +371,7 @@ public virtual IEnumerable BreadthFirstWalk(T source) throw new KeyNotFoundException("The source vertex doesn't exist."); var visited = new HashSet(); - var queue = new DataStructures.Lists.Queue(); + var queue = new Lists.Queue(); var listOfNodes = new ArrayList(VerticesCount); listOfNodes.Add(source); diff --git a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs index 68ea3c5e..3ede25f0 100644 --- a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs @@ -72,10 +72,7 @@ private long _getEdgeWeight(int source, int destination) /// /// Returns true, if graph is weighted; false otherwise. /// - public override bool IsWeighted - { - get { return true; } - } + public override bool IsWeighted => true; /// /// An enumerable collection of all weighted directed edges in graph. diff --git a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs index 66c0ccfe..8d34393f 100644 --- a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs @@ -81,34 +81,22 @@ private long _getEdgeWeight(T source, T destination) /// /// Returns true, if graph is directed; false otherwise. /// - public virtual bool IsDirected - { - get { return true; } - } + public virtual bool IsDirected => true; /// /// Returns true, if graph is weighted; false otherwise. /// - public virtual bool IsWeighted - { - get { return true; } - } + public virtual bool IsWeighted => true; /// /// Gets the count of vetices. /// - public int EdgesCount - { - get { return _edgesCount; } - } + public int EdgesCount => _edgesCount; /// /// Gets the count of edges. /// - public int VerticesCount - { - get { return _adjacencyList.Count; } - } + public int VerticesCount => _adjacencyList.Count; /// /// Returns the list of Vertices. @@ -123,19 +111,16 @@ public IEnumerable Vertices } - IEnumerable> IGraph.Edges - { - get { return this.Edges; } - } + IEnumerable> IGraph.Edges => Edges; IEnumerable> IGraph.IncomingEdges(T vertex) { - return this.IncomingEdges(vertex); + return IncomingEdges(vertex); } IEnumerable> IGraph.OutgoingEdges(T vertex) { - return this.OutgoingEdges(vertex); + return OutgoingEdges(vertex); } @@ -455,7 +440,7 @@ public virtual IEnumerable DepthFirstWalk(T source) throw new KeyNotFoundException("The source vertex doesn't exist."); var visited = new HashSet(); - var stack = new DataStructures.Lists.Stack(); + var stack = new Lists.Stack(); var listOfNodes = new ArrayList(VerticesCount); stack.Push(source); @@ -500,7 +485,7 @@ public virtual IEnumerable BreadthFirstWalk(T source) throw new KeyNotFoundException("The source vertex doesn't exist."); var visited = new HashSet(); - var queue = new DataStructures.Lists.Queue(); + var queue = new Lists.Queue(); var listOfNodes = new ArrayList(VerticesCount); listOfNodes.Add(source); diff --git a/DataStructures/Graphs/UndirectedDenseGraph.cs b/DataStructures/Graphs/UndirectedDenseGraph.cs index 54de9f1c..4b6a773d 100644 --- a/DataStructures/Graphs/UndirectedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedDenseGraph.cs @@ -65,34 +65,22 @@ protected virtual bool _doesVertexExist(T vertex) /// /// Returns true, if graph is directed; false otherwise. /// - public virtual bool IsDirected - { - get { return false; } - } + public virtual bool IsDirected => false; /// /// Returns true, if graph is weighted; false otherwise. /// - public virtual bool IsWeighted - { - get { return false; } - } + public virtual bool IsWeighted => false; /// /// Gets the count of vetices. /// - public virtual int VerticesCount - { - get { return _verticesCount; } - } + public virtual int VerticesCount => _verticesCount; /// /// Gets the count of edges. /// - public virtual int EdgesCount - { - get { return _edgesCount; } - } + public virtual int EdgesCount => _edgesCount; /// /// Returns the list of Vertices. @@ -108,19 +96,16 @@ public virtual IEnumerable Vertices } - IEnumerable> IGraph.Edges - { - get { return this.Edges; } - } + IEnumerable> IGraph.Edges => Edges; IEnumerable> IGraph.IncomingEdges(T vertex) { - return this.IncomingEdges(vertex); + return IncomingEdges(vertex); } IEnumerable> IGraph.OutgoingEdges(T vertex) { - return this.OutgoingEdges(vertex); + return OutgoingEdges(vertex); } @@ -256,7 +241,7 @@ public virtual void AddVertices(IList collection) throw new ArgumentNullException(); foreach (var item in collection) - this.AddVertex(item); + AddVertex(item); } /// @@ -352,7 +337,7 @@ public virtual bool HasVertex(T vertex) /// /// Returns the neighbours doubly-linked list for the specified vertex. /// - public virtual DataStructures.Lists.DLinkedList Neighbours(T vertex) + public virtual DLinkedList Neighbours(T vertex) { var neighbours = new DLinkedList(); int source = _vertices.IndexOf(vertex); diff --git a/DataStructures/Graphs/UndirectedSparseGraph.cs b/DataStructures/Graphs/UndirectedSparseGraph.cs index 3593c0ec..5bd7d594 100644 --- a/DataStructures/Graphs/UndirectedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedSparseGraph.cs @@ -48,34 +48,22 @@ protected virtual bool _doesEdgeExist(T vertex1, T vertex2) /// /// Returns true, if graph is directed; false otherwise. /// - public virtual bool IsDirected - { - get { return false; } - } + public virtual bool IsDirected => false; /// /// Returns true, if graph is weighted; false otherwise. /// - public virtual bool IsWeighted - { - get { return false; } - } + public virtual bool IsWeighted => false; /// /// Gets the count of vetices. /// - public virtual int VerticesCount - { - get { return _adjacencyList.Count; } - } + public virtual int VerticesCount => _adjacencyList.Count; /// /// Gets the count of edges. /// - public virtual int EdgesCount - { - get { return _edgesCount; } - } + public virtual int EdgesCount => _edgesCount; /// /// Returns the list of Vertices. @@ -93,19 +81,16 @@ public virtual IEnumerable Vertices } - IEnumerable> IGraph.Edges - { - get { return this.Edges; } - } + IEnumerable> IGraph.Edges => Edges; IEnumerable> IGraph.IncomingEdges(T vertex) { - return this.IncomingEdges(vertex); + return IncomingEdges(vertex); } IEnumerable> IGraph.OutgoingEdges(T vertex) { - return this.OutgoingEdges(vertex); + return OutgoingEdges(vertex); } @@ -207,7 +192,7 @@ public virtual void AddVertices(IList collection) throw new ArgumentNullException(); foreach (var item in collection) - this.AddVertex(item); + AddVertex(item); } /// diff --git a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs index a5086a3f..f2941a35 100644 --- a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs @@ -65,10 +65,7 @@ private long _getEdgeWeight(int source, int destination) /// /// Returns true, if graph is weighted; false otherwise. /// - public override bool IsWeighted - { - get { return true; } - } + public override bool IsWeighted => true; /// /// An enumerable collection of edges. diff --git a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs index 20859241..f6b9f872 100644 --- a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs @@ -82,34 +82,22 @@ private long _getEdgeWeight(T source, T destination) /// /// Returns true, if graph is undirected; false otherwise. /// - public virtual bool IsDirected - { - get { return false; } - } + public virtual bool IsDirected => false; /// /// Returns true, if graph is weighted; false otherwise. /// - public virtual bool IsWeighted - { - get { return true; } - } + public virtual bool IsWeighted => true; /// /// Gets the count of vetices. /// - public int EdgesCount - { - get { return _edgesCount; } - } + public int EdgesCount => _edgesCount; /// /// Gets the count of edges. /// - public int VerticesCount - { - get { return _adjacencyList.Count; } - } + public int VerticesCount => _adjacencyList.Count; /// /// Returns the list of Vertices. @@ -124,19 +112,16 @@ public IEnumerable Vertices } - IEnumerable> IGraph.Edges - { - get { return this.Edges; } - } + IEnumerable> IGraph.Edges => Edges; IEnumerable> IGraph.IncomingEdges(T vertex) { - return this.IncomingEdges(vertex); + return IncomingEdges(vertex); } IEnumerable> IGraph.OutgoingEdges(T vertex) { - return this.OutgoingEdges(vertex); + return OutgoingEdges(vertex); } @@ -486,7 +471,7 @@ public virtual IEnumerable DepthFirstWalk(T source) throw new KeyNotFoundException("The source vertex doesn't exist."); var visited = new HashSet(); - var stack = new DataStructures.Lists.Stack(); + var stack = new Lists.Stack(); var listOfNodes = new ArrayList(VerticesCount); stack.Push(source); @@ -531,7 +516,7 @@ public virtual IEnumerable BreadthFirstWalk(T source) throw new KeyNotFoundException("The source vertex doesn't exist."); var visited = new HashSet(); - var queue = new DataStructures.Lists.Queue(); + var queue = new Lists.Queue(); var listOfNodes = new ArrayList(VerticesCount); listOfNodes.Add(source); diff --git a/DataStructures/Graphs/UnweightedEdge.cs b/DataStructures/Graphs/UnweightedEdge.cs index 8bffc61f..83e98f4a 100644 --- a/DataStructures/Graphs/UnweightedEdge.cs +++ b/DataStructures/Graphs/UnweightedEdge.cs @@ -29,18 +29,14 @@ public class UnweightedEdge : IEdge where TVertex : IComparabl /// The weight. public Int64 Weight { - get { throw new NotImplementedException("Unweighted edges don't have weights."); } - set { throw new NotImplementedException("Unweighted edges can't have weights."); } + get => throw new NotImplementedException("Unweighted edges don't have weights."); + set => throw new NotImplementedException("Unweighted edges can't have weights."); } /// /// Gets a value indicating whether this edge is weighted. /// - public bool IsWeighted - { - get - { return false; } - } + public bool IsWeighted => false; /// /// CONSTRUCTOR diff --git a/DataStructures/Graphs/WeightedEdge.cs b/DataStructures/Graphs/WeightedEdge.cs index f073d50e..a249e67d 100644 --- a/DataStructures/Graphs/WeightedEdge.cs +++ b/DataStructures/Graphs/WeightedEdge.cs @@ -30,10 +30,7 @@ public class WeightedEdge : IEdge where TVertex : IComparable< /// /// Gets a value indicating whether this edge is weighted. /// - public bool IsWeighted - { - get { return true; } - } + public bool IsWeighted => true; /// /// CONSTRUCTOR diff --git a/DataStructures/Hashing/PrimeHashingFamily.cs b/DataStructures/Hashing/PrimeHashingFamily.cs index 80bba669..62bd758f 100644 --- a/DataStructures/Hashing/PrimeHashingFamily.cs +++ b/DataStructures/Hashing/PrimeHashingFamily.cs @@ -39,10 +39,7 @@ public PrimeHashingFamily(int numberOfHashFunctions) /// /// Returns number of member hash functions. /// - public int NumberOfFunctions - { - get { return _numberOfHashFunctions; } - } + public int NumberOfFunctions => _numberOfHashFunctions; /// /// Generates new hash functions with new randomized multipliers. diff --git a/DataStructures/Hashing/UniversalHashingFamily.cs b/DataStructures/Hashing/UniversalHashingFamily.cs index f0689ca4..860e8eda 100644 --- a/DataStructures/Hashing/UniversalHashingFamily.cs +++ b/DataStructures/Hashing/UniversalHashingFamily.cs @@ -47,10 +47,7 @@ public UniversalHashingFamily(int numberOfHashFunctions) /// /// Returns number of member hash functions. /// - public int NumberOfFunctions - { - get { return _numberOfHashFunctions; } - } + public int NumberOfFunctions => _numberOfHashFunctions; /// /// Generates new hash functions with new randomized multipliers. diff --git a/DataStructures/Heaps/BinaryMaxHeap.cs b/DataStructures/Heaps/BinaryMaxHeap.cs index 29d77043..e1793fd3 100644 --- a/DataStructures/Heaps/BinaryMaxHeap.cs +++ b/DataStructures/Heaps/BinaryMaxHeap.cs @@ -88,18 +88,12 @@ private void _maxHeapify(int nodeIndex, int lastIndex) /// /// Returns the number of elements in heap /// - public int Count - { - get { return _collection.Count; } - } + public int Count => _collection.Count; /// /// Checks whether this heap is empty /// - public bool IsEmpty - { - get { return (_collection.Count == 0); } - } + public bool IsEmpty => (_collection.Count == 0); /// /// Gets or sets the at the specified index. @@ -108,7 +102,7 @@ public T this[int index] { get { - if (index < 0 || index > this.Count || this.Count == 0) + if (index < 0 || index > Count || Count == 0) { throw new IndexOutOfRangeException(); } @@ -117,7 +111,7 @@ public T this[int index] } set { - if (index < 0 || index >= this.Count) + if (index < 0 || index >= Count) { throw new IndexOutOfRangeException(); } @@ -275,8 +269,8 @@ public BinaryMaxHeap Union(ref BinaryMaxHeap firstMaxHeap, ref BinaryMaxHe /// public IMinHeap ToMinHeap() { - BinaryMinHeap newMinHeap = new BinaryMinHeap(this.Count, this._heapComparer); - newMinHeap.Initialize(this._collection.ToArray()); + BinaryMinHeap newMinHeap = new BinaryMinHeap(Count, _heapComparer); + newMinHeap.Initialize(_collection.ToArray()); return newMinHeap; } diff --git a/DataStructures/Heaps/BinaryMinHeap.cs b/DataStructures/Heaps/BinaryMinHeap.cs index 90c8fd01..99f31209 100644 --- a/DataStructures/Heaps/BinaryMinHeap.cs +++ b/DataStructures/Heaps/BinaryMinHeap.cs @@ -92,18 +92,12 @@ private void _minHeapify(int nodeIndex, int lastIndex) /// /// Returns the number of elements in heap /// - public int Count - { - get { return _collection.Count; } - } + public int Count => _collection.Count; /// /// Checks whether this heap is empty /// - public bool IsEmpty - { - get { return (_collection.Count == 0); } - } + public bool IsEmpty => (_collection.Count == 0); /// /// Gets or sets the at the specified index. @@ -113,7 +107,7 @@ public T this[int index] { get { - if (index < 0 || index > this.Count || this.Count == 0) + if (index < 0 || index > Count || Count == 0) { throw new IndexOutOfRangeException(); } @@ -122,7 +116,7 @@ public T this[int index] } set { - if (index < 0 || index >= this.Count) + if (index < 0 || index >= Count) { throw new IndexOutOfRangeException(); } @@ -284,8 +278,8 @@ public BinaryMinHeap Union(ref BinaryMinHeap firstMinHeap, ref BinaryMinHe /// public IMaxHeap ToMaxHeap() { - BinaryMaxHeap newMaxHeap = new BinaryMaxHeap(this.Count, this._heapComparer); - newMaxHeap.Initialize(this._collection.ToArray()); + BinaryMaxHeap newMaxHeap = new BinaryMaxHeap(Count, _heapComparer); + newMaxHeap.Initialize(_collection.ToArray()); return newMaxHeap; } diff --git a/DataStructures/Heaps/BinomialMinHeap.cs b/DataStructures/Heaps/BinomialMinHeap.cs index 49646d0f..057b5bbe 100644 --- a/DataStructures/Heaps/BinomialMinHeap.cs +++ b/DataStructures/Heaps/BinomialMinHeap.cs @@ -22,7 +22,7 @@ private class BinomialNode where T : IComparable public BinomialNode Child { get; set; } // Left-Child // Constructors - public BinomialNode() : this(default(T), null, null, null) { } + public BinomialNode() : this(default, null, null, null) { } public BinomialNode(T value) : this(value, null, null, null) { } public BinomialNode(T value, BinomialNode parent, BinomialNode sibling, BinomialNode child) { @@ -33,15 +33,9 @@ public BinomialNode(T value, BinomialNode parent, BinomialNode sibling, Bi } // Helper boolean flags - public bool HasSiblings - { - get { return this.Sibling != null; } - } + public bool HasSiblings => Sibling != null; - public bool HasChildren - { - get { return this.Child != null; } - } + public bool HasChildren => Child != null; } @@ -168,19 +162,13 @@ private BinomialNode _cloneTree(BinomialNode treeRoot) /// /// Returns count of elements in heap. /// - public int Count - { - get { return _size; } - } + public int Count => _size; /// /// Checks if heap is empty /// /// - public bool IsEmpty - { - get { return (_size == 0); } - } + public bool IsEmpty => (_size == 0); /// /// Initializes this heap with a collection of elements. @@ -196,7 +184,7 @@ public void Initialize(IList newCollection) _forest = new ArrayList>(newCollection.Count + 1); for (int i = 0; i < newCollection.Count; ++i) - this.Add(newCollection[i]); + Add(newCollection[i]); } /// @@ -277,8 +265,8 @@ public void Merge(BinomialMinHeap otherHeap) // One capacity-change step if (_size > _forest.Count) { - int newSize = Math.Max(this._forest.Count, otherHeap._forest.Count) + 1; - this._forest.Resize(newSize); + int newSize = Math.Max(_forest.Count, otherHeap._forest.Count) + 1; + _forest.Resize(newSize); } for (int i = 0, j = 1; j <= _size; i++, j *= 2) @@ -297,29 +285,29 @@ public void Merge(BinomialMinHeap otherHeap) case 1: /* Only this */ break; case 2: /* Only otherHeap */ - this._forest[i] = treeRoot2; + _forest[i] = treeRoot2; otherHeap._forest[i] = null; break; case 4: /* Only carryNode */ - this._forest[i] = carryNode; + _forest[i] = carryNode; carryNode = null; break; /*** BINARY CASES ***/ case 3: /* this and otherHeap */ carryNode = _combineTrees(treeRoot1, treeRoot2); - this._forest[i] = otherHeap._forest[i] = null; + _forest[i] = otherHeap._forest[i] = null; break; case 5: /* this and carryNode */ carryNode = _combineTrees(treeRoot1, carryNode); - this._forest[i] = null; + _forest[i] = null; break; case 6: /* otherHeap and carryNode */ carryNode = _combineTrees(treeRoot2, carryNode); otherHeap._forest[i] = null; break; case 7: /* all the nodes */ - this._forest[i] = carryNode; + _forest[i] = carryNode; carryNode = _combineTrees(treeRoot1, treeRoot2); otherHeap._forest[i] = null; break; diff --git a/DataStructures/Heaps/KeyedPriorityQueue.cs b/DataStructures/Heaps/KeyedPriorityQueue.cs index e96d7333..de97035f 100644 --- a/DataStructures/Heaps/KeyedPriorityQueue.cs +++ b/DataStructures/Heaps/KeyedPriorityQueue.cs @@ -49,7 +49,7 @@ public PriorityQueue(int capacity, Comparer> priority _priorityComparer = priorityComparer; } - _heap = new BinaryMaxHeap>(capacity, this._priorityComparer); + _heap = new BinaryMaxHeap>(capacity, _priorityComparer); _keysMap = new Dictionary(); } else @@ -62,20 +62,14 @@ public PriorityQueue(int capacity, Comparer> priority /// /// Returns the count of elements in the queue. /// - public int Count - { - get { return _heap.Count; } - } + public int Count => _heap.Count; /// /// Checks if the queue is empty /// True if queue is empty; false otherwise. /// - public bool IsEmpty - { - get { return _heap.IsEmpty; } - } + public bool IsEmpty => _heap.IsEmpty; /// @@ -114,7 +108,7 @@ public V PeekAtHighestPriority() /// Value. public void Enqueue(K key, V value) { - Enqueue(key, value, default(P)); + Enqueue(key, value, default); } @@ -263,13 +257,13 @@ public class PriorityQueueNode : IComparable public V Value { get; set; } public P Priority { get; set; } - public PriorityQueueNode() : this(default(K), default(V), default(P)) { } + public PriorityQueueNode() : this(default, default, default) { } public PriorityQueueNode(K key, V value, P priority) { - this.Key = key; - this.Value = value; - this.Priority = priority; + Key = key; + Value = value; + Priority = priority; } public int CompareTo(PriorityQueueNode other) @@ -277,7 +271,7 @@ public int CompareTo(PriorityQueueNode other) if (other == null) return -1; - return this.Priority.CompareTo(other.Priority); + return Priority.CompareTo(other.Priority); } }//end-of-node-class diff --git a/DataStructures/Heaps/MinPriorityQueue.cs b/DataStructures/Heaps/MinPriorityQueue.cs index 11aeb91a..294c3f03 100644 --- a/DataStructures/Heaps/MinPriorityQueue.cs +++ b/DataStructures/Heaps/MinPriorityQueue.cs @@ -48,7 +48,7 @@ public MinPriorityQueue(uint capacity, Comparer(); - _heap = new BinaryMinHeap>((int)capacity, this._priorityComparer); + _heap = new BinaryMinHeap>((int)capacity, _priorityComparer); } @@ -90,18 +90,12 @@ private bool _validPriorityType() /// /// Returns the count of elements in the queue. /// - public int Count - { - get { return _heap.Count; } - } + public int Count => _heap.Count; /// /// Checks if the queue is empty /// - public bool IsEmpty - { - get { return _heap.IsEmpty; } - } + public bool IsEmpty => _heap.IsEmpty; /// /// Get the default max priority, if set, raises an exception if not set. @@ -269,12 +263,12 @@ public class PriorityQueueNode : IComparable other) @@ -282,7 +276,7 @@ public int CompareTo(PriorityQueueNode other) if (other == null) return -1; - return this.Priority.CompareTo(other.Priority); + return Priority.CompareTo(other.Priority); } }//end-of-node-class diff --git a/DataStructures/Lists/ArrayList.cs b/DataStructures/Lists/ArrayList.cs index 8e7acc53..17897e83 100644 --- a/DataStructures/Lists/ArrayList.cs +++ b/DataStructures/Lists/ArrayList.cs @@ -90,7 +90,7 @@ private void _ensureCapacity(int minCapacity) IsMaximumCapacityReached = true; } - this._resizeCapacity(newCapacity); + _resizeCapacity(newCapacity); } } @@ -125,35 +125,20 @@ private void _resizeCapacity(int newCapacity) /// Gets the the number of elements in list. /// /// Int. - public int Count - { - get - { - return _size; - } - } + public int Count => _size; /// /// Returns the capacity of list, which is the total number of slots. /// - public int Capacity - { - get { return _collection.Length; } - } + public int Capacity => _collection.Length; /// /// Determines whether this list is empty. /// /// true if list is empty; otherwise, false. - public bool IsEmpty - { - get - { - return (Count == 0); - } - } + public bool IsEmpty => (Count == 0); /// @@ -256,7 +241,7 @@ public void AddRange(IEnumerable elements) _ensureCapacity(_size + elements.Count()); foreach (var element in elements) - this.Add(element); + Add(element); } } @@ -278,7 +263,7 @@ public void AddRepeatedly(T value, int count) _ensureCapacity(_size + count); for (int i = 0; i < count; i++) - this.Add(value); + Add(value); } } @@ -359,7 +344,7 @@ public void RemoveAt(int index) } // Reset the writable cell to the default value of type T. - _collection[_size] = default(T); + _collection[_size] = default; } @@ -382,7 +367,7 @@ public void Clear() /// public void Resize(int newSize) { - Resize(newSize, default(T)); + Resize(newSize, default); } @@ -391,20 +376,20 @@ public void Resize(int newSize) /// public void Resize(int newSize, T defaultValue) { - int currentSize = this.Count; + int currentSize = Count; if (newSize < currentSize) { - this._ensureCapacity(newSize); + _ensureCapacity(newSize); } else if (newSize > currentSize) { // Optimisation step. // This is just to avoid multiple automatic capacity changes. - if (newSize > this._collection.Length) - this._ensureCapacity(newSize + 1); + if (newSize > _collection.Length) + _ensureCapacity(newSize + 1); - this.AddRange(Enumerable.Repeat(defaultValue, newSize - currentSize)); + AddRange(Enumerable.Repeat(defaultValue, newSize - currentSize)); } } @@ -677,7 +662,7 @@ public T Find(Predicate searchMatch) } // Not found, return the default value of the type T. - return default(T); + return default; } @@ -765,11 +750,11 @@ public T[] ToArray() /// Array. public List ToList() { - var newList = new List(this.Count); + var newList = new List(Count); - if (this.Count > 0) + if (Count > 0) { - for (int i = 0; i < this.Count; ++i) + for (int i = 0; i < Count; ++i) { newList.Add(_collection[i]); } @@ -818,7 +803,7 @@ public IEnumerator GetEnumerator() System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { - return this.GetEnumerator(); + return GetEnumerator(); } } diff --git a/DataStructures/Lists/CircularBuffer.cs b/DataStructures/Lists/CircularBuffer.cs index b49c7534..a38c74d1 100644 --- a/DataStructures/Lists/CircularBuffer.cs +++ b/DataStructures/Lists/CircularBuffer.cs @@ -15,35 +15,17 @@ public class CircularBuffer : IEnumerable, ICollection where T : ICompa /// /// Returns the length of the buffer /// - public int Length - { - get - { - return _circularBuffer.Length - 1; - } - } + public int Length => _circularBuffer.Length - 1; /// /// Checks if no element is inserted into the buffer /// - public bool IsEmpty - { - get - { - return _count == 0; - } - } + public bool IsEmpty => Count == 0; /// /// Checks if the buffer is filled up /// - public bool IsFilledUp - { - get - { - return ((_end + 1) % _circularBuffer.Length == _start) && !_circularBuffer[_start].Equals(_circularBuffer[_end]); - } - } + public bool IsFilledUp => ((_end + 1) % _circularBuffer.Length == _start) && !_circularBuffer[_start].Equals(_circularBuffer[_end]); /// /// Controls whether data should be overridden when it is continously inserted without reading @@ -100,7 +82,7 @@ private void innerInsert(T value) } // Count should not be greater than the length of the buffer when overriding - _count = _count < Length ? ++_count : _count; + Count = Count < Length ? ++Count : Count; } /// @@ -112,7 +94,7 @@ public T Pop() _circularBuffer[_start] = _circularBuffer[_end]; _start = (_start + 1) % _circularBuffer.Length; //Count should not go below Zero when poping an empty buffer. - _count = _count > 0 ? --_count : _count; + Count = Count > 0 ? --Count : Count; return result; } @@ -132,33 +114,23 @@ IEnumerator IEnumerable.GetEnumerator() #endregion #region ICollection Implementation - private int _count; + /// /// Returns the number of elements. /// - public int Count - { - get - { - return _count; - } - } + public int Count { get; private set; } + /// /// Checks whether this collection is readonly /// - public bool IsReadOnly - { - get - { - return false; - } - } + public bool IsReadOnly => false; + /// /// Clears this instance /// public void Clear() { - _count = 0; + Count = 0; _start = 0; _end = 0; _circularBuffer = new T[Length + 1]; @@ -216,12 +188,12 @@ public bool Remove(T item) if (!Equals(item,default(T))) { _end = sourceArray.Length - 1; - _count = sourceArray.Length-1; + Count = sourceArray.Length-1; } else { _end = sourceArray.Length; - _count = sourceArray.Length; + Count = sourceArray.Length; } return true; diff --git a/DataStructures/Lists/DLinkedList.cs b/DataStructures/Lists/DLinkedList.cs index e2fa6a1a..08d36041 100644 --- a/DataStructures/Lists/DLinkedList.cs +++ b/DataStructures/Lists/DLinkedList.cs @@ -11,11 +11,7 @@ namespace DataStructures.Lists /// Type public class DLinkedListNode : IComparable> where T : IComparable { - private T _data; - private DLinkedListNode _next; - private DLinkedListNode _previous; - - public DLinkedListNode() : this(default(T)) { } + public DLinkedListNode() : this(default) { } public DLinkedListNode(T dataItem) : this(dataItem, null, null) { } public DLinkedListNode(T dataItem, DLinkedListNode next, DLinkedListNode previous) { @@ -24,29 +20,17 @@ public DLinkedListNode(T dataItem, DLinkedListNode next, DLinkedListNode p Previous = previous; } - public virtual T Data - { - get { return this._data; } - set { this._data = value; } - } + public virtual T Data { get; set; } - public virtual DLinkedListNode Next - { - get { return this._next; } - set { this._next = value; } - } + public virtual DLinkedListNode Next { get; set; } - public virtual DLinkedListNode Previous - { - get { return this._previous; } - set { this._previous = value; } - } + public virtual DLinkedListNode Previous { get; set; } public int CompareTo(DLinkedListNode other) { if (other == null) return -1; - return this.Data.CompareTo(other.Data); + return Data.CompareTo(other.Data); } } @@ -67,15 +51,9 @@ public class DLinkedList : IEnumerable where T : IComparable private DLinkedListNode _firstNode { get; set; } private DLinkedListNode _lastNode { get; set; } - public virtual DLinkedListNode Head - { - get { return this._firstNode; } - } + public virtual DLinkedListNode Head => _firstNode; - public virtual int Count - { - get { return this._count; } - } + public virtual int Count => _count; /// @@ -105,7 +83,7 @@ protected virtual T _getElementAt(int index) // Otherwise, traverse it from the beginning (_firstNode refrence) if (index > (Count / 2)) { - currentNode = this._lastNode; + currentNode = _lastNode; for (int i = (Count - 1); i > index; --i) { currentNode = currentNode.Previous; @@ -113,7 +91,7 @@ protected virtual T _getElementAt(int index) } else { - currentNode = this._firstNode; + currentNode = _firstNode; for (int i = 0; i < index; ++i) { currentNode = currentNode.Next; @@ -150,7 +128,7 @@ protected virtual void _setElementAt(int index, T value) // Otherwise, traverse it from the beginning (_firstNode refrence) if (index > (Count / 2)) { - currentNode = this._lastNode; + currentNode = _lastNode; for (int i = (Count - 1); i > index; --i) { currentNode = currentNode.Previous; @@ -158,7 +136,7 @@ protected virtual void _setElementAt(int index, T value) } else { - currentNode = this._firstNode; + currentNode = _firstNode; for (int i = 0; i < index; ++i) { currentNode = currentNode.Next; @@ -239,8 +217,8 @@ public virtual T Last /// Index of element. public virtual T this[int index] { - get { return this._getElementAt(index); } - set { this._setElementAt(index, value); } + get => _getElementAt(index); + set => _setElementAt(index, value); } /// @@ -339,7 +317,7 @@ public virtual void InsertAt(T dataItem, int index) DLinkedListNode currentNode = null; DLinkedListNode newNode = new DLinkedListNode(dataItem); - currentNode = this._firstNode; + currentNode = _firstNode; for (int i = 0; i < index - 1; ++i) { currentNode = currentNode.Next; @@ -595,7 +573,7 @@ public virtual T Find(T dataItem) public virtual bool TryFindFirst(Predicate match, out T found) { // Initialize the output parameter - found = default(T); + found = default; if (IsEmpty()) return false; @@ -695,7 +673,7 @@ public virtual DLinkedList GetRange(int index, int countOfElements) // Otherwise, traverse it from the beginning (_firstNode refrence) if (index > (Count / 2)) { - currentNode = this._lastNode; + currentNode = _lastNode; for (int i = (Count - 1); i > index; --i) { currentNode = currentNode.Previous; @@ -703,7 +681,7 @@ public virtual DLinkedList GetRange(int index, int countOfElements) } else { - currentNode = this._firstNode; + currentNode = _firstNode; for (int i = 0; i < index; ++i) { currentNode = currentNode.Next; @@ -841,7 +819,7 @@ public IEnumerator GetEnumerator() System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { - return this.GetEnumerator(); + return GetEnumerator(); // Alternative: IEnumerator class instance // return new DLinkedListEnumerator(this); @@ -856,19 +834,13 @@ internal class DLinkedListEnumerator : IEnumerator public DLinkedListEnumerator(DLinkedList list) { - this._current = list.Head; - this._doublyLinkedList = list; + _current = list.Head; + _doublyLinkedList = list; } - public T Current - { - get { return this._current.Data; } - } + public T Current => _current.Data; - object System.Collections.IEnumerator.Current - { - get { return Current; } - } + object System.Collections.IEnumerator.Current => Current; public bool MoveNext() { diff --git a/DataStructures/Lists/DLinkedList_KeyValue.cs b/DataStructures/Lists/DLinkedList_KeyValue.cs index d1f8f915..e4424995 100644 --- a/DataStructures/Lists/DLinkedList_KeyValue.cs +++ b/DataStructures/Lists/DLinkedList_KeyValue.cs @@ -11,13 +11,8 @@ namespace DataStructures.Lists /// Type public class DLinkedListNode : IComparable> where TKey : IComparable { - private TKey _key; - private TValue _value; - private DLinkedListNode _next; - private DLinkedListNode _previous; - - public DLinkedListNode() : this(default(TKey), default(TValue)) { } - public DLinkedListNode(TKey key, TValue value) : this(key, value, null, null) { } + public DLinkedListNode() : this(default, default) { } + public DLinkedListNode(TKey key, TValue value) : this(key, value, next: null, null) { } public DLinkedListNode(TKey key, TValue value, DLinkedListNode next, DLinkedListNode previous) { Key = key; @@ -26,35 +21,19 @@ public DLinkedListNode(TKey key, TValue value, DLinkedListNode nex Previous = previous; } - public virtual TKey Key - { - get { return this._key; } - set { this._key = value; } - } + public virtual TKey Key { get; set; } - public virtual TValue Value - { - get { return this._value; } - set { this._value = value; } - } + public virtual TValue Value { get; set; } - public virtual DLinkedListNode Next - { - get { return this._next; } - set { this._next = value; } - } + public virtual DLinkedListNode Next { get; set; } - public virtual DLinkedListNode Previous - { - get { return this._previous; } - set { this._previous = value; } - } + public virtual DLinkedListNode Previous { get; set; } public int CompareTo(DLinkedListNode other) { if (other == null) return -1; - return this.Key.CompareTo(other.Key); + return Key.CompareTo(other.Key); } } @@ -72,15 +51,9 @@ public class DLinkedList where TKey : IComparable private DLinkedListNode _firstNode { get; set; } private DLinkedListNode _lastNode { get; set; } - public virtual DLinkedListNode Head - { - get { return this._firstNode; } - } + public virtual DLinkedListNode Head => _firstNode; - public virtual int Count - { - get { return this._count; } - } + public virtual int Count => _count; /// @@ -110,7 +83,7 @@ protected virtual DLinkedListNode _getNodeByIndex(int index) // Otherwise, traverse it from the beginning (_firstNode refrence) if (index > (Count / 2)) { - currentNode = this._lastNode; + currentNode = _lastNode; for (int i = (Count - 1); i > index; --i) { currentNode = currentNode.Previous; @@ -118,7 +91,7 @@ protected virtual DLinkedListNode _getNodeByIndex(int index) } else { - currentNode = this._firstNode; + currentNode = _firstNode; for (int i = 0; i < index; ++i) { currentNode = currentNode.Next; @@ -146,7 +119,7 @@ protected virtual DLinkedListNode _getNodeByKey(TKey key) return _lastNode; } - var currentNode = this._firstNode; + var currentNode = _firstNode; while (currentNode != null) { if (key.IsEqualTo(currentNode.Key)) @@ -186,7 +159,7 @@ protected virtual void _setValueByIndex(int index, TValue value) // Otherwise, traverse it from the beginning (_firstNode refrence) if (index > (Count / 2)) { - currentNode = this._lastNode; + currentNode = _lastNode; for (int i = (Count - 1); i > index; --i) { currentNode = currentNode.Previous; @@ -194,7 +167,7 @@ protected virtual void _setValueByIndex(int index, TValue value) } else { - currentNode = this._firstNode; + currentNode = _firstNode; for (int i = 0; i < index; ++i) { currentNode = currentNode.Next; @@ -223,7 +196,7 @@ protected virtual void _setValueByKey(TKey key, TValue value) } else { - var currentNode = this._firstNode; + var currentNode = _firstNode; while (currentNode != null) { if (currentNode.Key.IsEqualTo(key)) @@ -266,7 +239,7 @@ protected virtual void _setNodeByIndex(int index, TKey key, TValue value) // Otherwise, traverse it from the beginning (_firstNode refrence) if (index > (Count / 2)) { - currentNode = this._lastNode; + currentNode = _lastNode; for (int i = (Count - 1); i > index; --i) { currentNode = currentNode.Previous; @@ -274,7 +247,7 @@ protected virtual void _setNodeByIndex(int index, TKey key, TValue value) } else { - currentNode = this._firstNode; + currentNode = _firstNode; for (int i = 0; i < index; ++i) { currentNode = currentNode.Next; @@ -479,7 +452,7 @@ public virtual void InsertAt(int index, TKey key, TValue value) } else { - currentNode = this._firstNode; + currentNode = _firstNode; for (int i = 0; i < index - 1; ++i) { currentNode = currentNode.Next; @@ -760,7 +733,7 @@ public virtual List> GetRange(int index, int countOfE // Otherwise, traverse it from the beginning (_firstNode refrence) if (index > (Count / 2)) { - currentNode = this._lastNode; + currentNode = _lastNode; for (int i = (Count - 1); i > index; --i) { currentNode = currentNode.Previous; @@ -768,7 +741,7 @@ public virtual List> GetRange(int index, int countOfE } else { - currentNode = this._firstNode; + currentNode = _firstNode; for (int i = 0; i < index; ++i) { currentNode = currentNode.Next; diff --git a/DataStructures/Lists/Queue.cs b/DataStructures/Lists/Queue.cs index 903fc19e..8dccb827 100644 --- a/DataStructures/Lists/Queue.cs +++ b/DataStructures/Lists/Queue.cs @@ -100,18 +100,12 @@ private void _resize(int newSize) /// /// Returns count of elements in queue /// - public int Count - { - get { return _size; } - } + public int Count => _size; /// /// Checks whether the queue is empty. /// - public bool IsEmpty - { - get { return _size == 0; } - } + public bool IsEmpty => _size == 0; /// /// Returns the top element in queue @@ -166,7 +160,7 @@ public T Dequeue() throw new Exception("Queue is empty."); var topItem = _collection[_headPointer]; - _collection[_headPointer] = default(T); + _collection[_headPointer] = default; // Decrement the size _size--; @@ -240,7 +234,7 @@ public IEnumerator GetEnumerator() System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { - return this.GetEnumerator(); + return GetEnumerator(); } } diff --git a/DataStructures/Lists/SLinkedList.cs b/DataStructures/Lists/SLinkedList.cs index fdc34e07..261529a5 100644 --- a/DataStructures/Lists/SLinkedList.cs +++ b/DataStructures/Lists/SLinkedList.cs @@ -11,13 +11,10 @@ namespace DataStructures.Lists /// public class SLinkedListNode : IComparable> where T : IComparable { - private T _data; - private SLinkedListNode _next; - public SLinkedListNode() { Next = null; - Data = default(T); + Data = default; } public SLinkedListNode(T dataItem) @@ -26,23 +23,15 @@ public SLinkedListNode(T dataItem) Data = dataItem; } - public T Data - { - get { return this._data; } - set { this._data = value; } - } + public T Data { get; set; } - public SLinkedListNode Next - { - get { return this._next; } - set { this._next = value; } - } + public SLinkedListNode Next { get; set; } public int CompareTo(SLinkedListNode other) { if (other == null) return -1; - return this.Data.CompareTo(other.Data); + return Data.CompareTo(other.Data); } } @@ -52,22 +41,15 @@ public int CompareTo(SLinkedListNode other) /// public class SLinkedList : IEnumerable where T : IComparable { + private SLinkedListNode _firstNode { get; set; } + private SLinkedListNode _lastNode { get; set; } + /// /// Instance variables /// - private int _count; - private SLinkedListNode _firstNode { get; set; } - private SLinkedListNode _lastNode { get; set; } + public int Count { get; private set; } - public int Count - { - get { return _count; } - } - - public virtual SLinkedListNode Head - { - get { return this._firstNode; } - } + public virtual SLinkedListNode Head => _firstNode; /// /// CONSTRUCTOR @@ -76,7 +58,7 @@ public SLinkedList() { _firstNode = null; _lastNode = null; - _count = 0; + Count = 0; } /// @@ -91,13 +73,7 @@ public bool IsEmpty() /// /// Getter function that returns the first element /// - public T First - { - get - { - return (_firstNode == null ? default(T) : _firstNode.Data); - } - } + public T First => (_firstNode == null ? default : _firstNode.Data); /// /// Getter function that returns the last element @@ -146,7 +122,7 @@ public void Prepend(T dataItem) } // Increment the count. - _count++; + Count++; } /// @@ -169,7 +145,7 @@ public void Append(T dataItem) } // Increment the count. - _count++; + Count++; } /// @@ -203,7 +179,7 @@ public void InsertAt(T dataItem, int index) currentNode.Next = newNode; // Increment the count - _count++; + Count++; } else { @@ -227,7 +203,7 @@ public void RemoveAt(int index) _firstNode = _firstNode.Next; // Decrement count. - _count--; + Count--; } else if (index == Count - 1) { @@ -240,7 +216,7 @@ public void RemoveAt(int index) _lastNode = currentNode; // Decrement count. - _count--; + Count--; } else { @@ -253,7 +229,7 @@ public void RemoveAt(int index) currentNode.Next = currentNode.Next.Next; // Decrement the count. - _count--; + Count--; break; } @@ -270,7 +246,7 @@ public void Clear() { _firstNode = null; _lastNode = null; - _count = 0; + Count = 0; } /// @@ -312,7 +288,7 @@ public T GetAt(int index) public SLinkedList GetRange(int index, int countOfElements) { SLinkedList newList = new SLinkedList(); - var currentNode = this._firstNode; + var currentNode = _firstNode; // Handle Index out of Bound errors if (Count == 0) @@ -465,25 +441,19 @@ internal class SLinkedListEnumerator : IEnumerator public SLinkedListEnumerator(SLinkedList list) { - this._doublyLinkedList = list; - this._current = list.Head; + _doublyLinkedList = list; + _current = list.Head; } - public T Current - { - get { return this._current.Data; } - } + public T Current => _current.Data; - object System.Collections.IEnumerator.Current - { - get { return Current; } - } + object System.Collections.IEnumerator.Current => Current; public bool MoveNext() { _current = _current.Next; - return (this._current != null); + return (_current != null); } public void Reset() diff --git a/DataStructures/Lists/SkipList.cs b/DataStructures/Lists/SkipList.cs index 57822aca..1c463d5f 100644 --- a/DataStructures/Lists/SkipList.cs +++ b/DataStructures/Lists/SkipList.cs @@ -52,7 +52,7 @@ public SkipList() _count = 0; _currentMaxLevel = 1; _randomizer = new Random(); - _firstNode = new SkipListNode(default(T), MaxLevel); + _firstNode = new SkipListNode(default, MaxLevel); for (int i = 0; i < MaxLevel; ++i) _firstNode.Forwards[i] = _firstNode; @@ -62,46 +62,29 @@ public SkipList() /// /// Getter accessor for the first node /// - public SkipListNode Root - { - get { return _firstNode; } - } + public SkipListNode Root => _firstNode; /// /// Checks if list is empty or not /// - public bool IsEmpty - { - get { return Count == 0; } - } + public bool IsEmpty => Count == 0; /// /// Return count of elements /// - public int Count - { - get { return _count; } - } + public int Count => _count; /// /// Return current max-node level /// - public int Level - { - get { return _currentMaxLevel; } - } + public int Level => _currentMaxLevel; /// /// Access elements by index /// - public T this[int index] - { - get - { - // TODO: - throw new NotImplementedException(); - } - } + public T this[int index] => throw + // TODO: + new NotImplementedException(); /// /// Adds item to the list @@ -178,7 +161,7 @@ public bool Remove(T item, out T deleted) // Return default value of T if the item was not found if (current.Value.IsEqualTo(item) == false) { - deleted = default(T); + deleted = default; return false; } @@ -231,7 +214,7 @@ public bool Find(T item, out T result) return true; } - result = default(T); + result = default; return false; } @@ -257,7 +240,7 @@ public bool TryDeleteMin(out T result) { if (IsEmpty) { - result = default(T); + result = default; return false; } @@ -286,7 +269,7 @@ public bool TryPeek(out T result) { if (IsEmpty) { - result = default(T); + result = default; return false; } @@ -323,10 +306,7 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() /// /// Checks whether this collection is readonly /// - public bool IsReadOnly - { - get { return false; } - } + public bool IsReadOnly => false; /// /// Copy this list to an array @@ -340,7 +320,7 @@ public void CopyTo(T[] array, int arrayIndex) throw new IndexOutOfRangeException(); // Get enumerator - var enumarator = this.GetEnumerator(); + var enumarator = GetEnumerator(); // Copy elements as long as there is any in the list and as long as the index is within the valid range for (int i = arrayIndex; i < array.Length; ++i) @@ -360,7 +340,7 @@ public void Clear() _count = 0; _currentMaxLevel = 1; _randomizer = new Random(); - _firstNode = new SkipListNode(default(T), MaxLevel); + _firstNode = new SkipListNode(default, MaxLevel); for (int i = 0; i < MaxLevel; ++i) _firstNode.Forwards[i] = _firstNode; diff --git a/DataStructures/Lists/SkipListNode.cs b/DataStructures/Lists/SkipListNode.cs index 8188c747..3eace4f5 100644 --- a/DataStructures/Lists/SkipListNode.cs +++ b/DataStructures/Lists/SkipListNode.cs @@ -8,7 +8,6 @@ public class SkipListNode : IComparable> where T : IComparabl /// Instance variables /// private T _value; - private SkipListNode[] _forwards; /// /// CONSTRUCTORS @@ -27,26 +26,19 @@ public SkipListNode(T value, int level) /// public virtual T Value { - get { return this._value; } - private set { this._value = value; } + get => _value; + private set => _value = value; } /// /// Get and set node's forwards links /// - public virtual SkipListNode[] Forwards - { - get { return this._forwards; } - private set { this._forwards = value; } - } + public virtual SkipListNode[] Forwards { get; private set; } /// /// Return level of node. /// - public virtual int Level - { - get { return Forwards.Length; } - } + public virtual int Level => Forwards.Length; /// /// IComparable method implementation @@ -56,7 +48,7 @@ public int CompareTo(SkipListNode other) if (other == null) return -1; - return this.Value.CompareTo(other.Value); + return Value.CompareTo(other.Value); } } } diff --git a/DataStructures/Lists/Stack.cs b/DataStructures/Lists/Stack.cs index ab88a8f9..1913020a 100644 --- a/DataStructures/Lists/Stack.cs +++ b/DataStructures/Lists/Stack.cs @@ -15,7 +15,7 @@ public class Stack : IEnumerable where T : IComparable /// Count: Public Getter for returning the number of elements. /// private ArrayList _collection { get; set; } - public int Count { get { return _collection.Count; } } + public int Count => _collection.Count; /// @@ -46,13 +46,7 @@ public Stack(int initialCapacity) /// Checks whether the stack is empty. /// /// True if stack is empty, false otherwise. - public bool IsEmpty - { - get - { - return _collection.IsEmpty; - } - } + public bool IsEmpty => _collection.IsEmpty; /// @@ -130,7 +124,7 @@ public IEnumerator GetEnumerator() System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { - return this.GetEnumerator(); + return GetEnumerator(); } } diff --git a/DataStructures/SortedCollections/SortedDictionary.cs b/DataStructures/SortedCollections/SortedDictionary.cs index 4d86e7b9..190c64be 100644 --- a/DataStructures/SortedCollections/SortedDictionary.cs +++ b/DataStructures/SortedCollections/SortedDictionary.cs @@ -29,23 +29,14 @@ public SortedDictionary() /// /// Gets the count of enteries in dictionary. /// - public int Count - { - get { return _collection.Count; } - } + public int Count => _collection.Count; /// /// Returns true if dictionary is empty; otherwise, false. /// - public bool IsEmpty - { - get { return Count == 0; } - } + public bool IsEmpty => Count == 0; - public bool IsReadOnly - { - get { return false; } - } + public bool IsReadOnly => false; /// /// Determines whether the current dictionary contains an entry with the specified key. @@ -77,7 +68,7 @@ public bool Contains(KeyValuePair item) public bool TryGetValue(TKey key, out TValue value) { // Set value to the default value of type TValue - value = default(TValue); + value = default; try { @@ -132,7 +123,7 @@ public ICollection Keys { get { - var keys = new System.Collections.Generic.List(Count); + var keys = new List(Count); var enumerator = _collection.GetInOrderEnumerator(); while (enumerator.MoveNext()) @@ -149,7 +140,7 @@ public ICollection Values { get { - var values = new System.Collections.Generic.List(Count); + var values = new List(Count); var enumerator = _collection.GetInOrderEnumerator(); while (enumerator.MoveNext()) diff --git a/DataStructures/SortedCollections/SortedList.cs b/DataStructures/SortedCollections/SortedList.cs index f21cadff..2f91da62 100644 --- a/DataStructures/SortedCollections/SortedList.cs +++ b/DataStructures/SortedCollections/SortedList.cs @@ -22,29 +22,20 @@ public class SortedList : IEnumerable, ICollection, IList where T : /// public SortedList() { - this._collection = new RedBlackTree(); + _collection = new RedBlackTree(); } /// /// Returns true if list is empty; otherwise, false. /// - public bool IsEmpty - { - get { return this.Count == 0; } - } + public bool IsEmpty => Count == 0; /// /// Gets the count of items in list. /// - public int Count - { - get { return this._collection.Count; } - } + public int Count => _collection.Count; - public bool IsReadOnly - { - get { return false; } - } + public bool IsReadOnly => false; /// /// Determines whether the current collection contains a specific value. @@ -60,11 +51,11 @@ public bool Contains(T item) public int IndexOf(T item) { // If the item doesn't exist in collection, return -1 - if (!this.Contains(item)) + if (!Contains(item)) return -1; int index = 0; - var enumerator = this._collection.GetInOrderEnumerator(); + var enumerator = _collection.GetInOrderEnumerator(); while (enumerator.MoveNext()) { @@ -91,10 +82,10 @@ public T this[int index] throw new Exception("List is empty."); // Validate index range - if (index < 0 || index >= this.Count) + if (index < 0 || index >= Count) throw new IndexOutOfRangeException(); - var enumerator = this._collection.GetInOrderEnumerator(); + var enumerator = _collection.GetInOrderEnumerator(); // Keep moving to the next item until index becomes 0 while (enumerator.MoveNext() && index > 0) @@ -107,8 +98,8 @@ public T this[int index] { try { - this._collection.Remove(this[index]); - this.Add(value); + _collection.Remove(this[index]); + Add(value); } catch (IndexOutOfRangeException) { @@ -123,7 +114,7 @@ public T this[int index] /// public void Add(T item) { - this._collection.Insert(item); + _collection.Insert(item); } /// @@ -133,7 +124,7 @@ public bool Remove(T item) { try { - this._collection.Remove(item); + _collection.Remove(item); return true; } catch(Exception) @@ -160,17 +151,17 @@ public void Insert(int index, T item) public void RemoveAt(int index) { // Validate index range - if (index < 0 || index >= this.Count) + if (index < 0 || index >= Count) throw new IndexOutOfRangeException(); - var enumerator = this._collection.GetInOrderEnumerator(); + var enumerator = _collection.GetInOrderEnumerator(); // Keep moving to the next item until index becomes 0 while (enumerator.MoveNext() && index > 0) index--; // Remove the enumerator's Current value from collection - this.Remove(enumerator.Current); + Remove(enumerator.Current); } /// @@ -182,7 +173,7 @@ public void CopyTo(T[] array, int arrayIndex) if(array == null) throw new ArgumentNullException("Array cannot be Null."); - var enumerator = this._collection.GetInOrderEnumerator(); + var enumerator = _collection.GetInOrderEnumerator(); // Copy the items from the inorder-walker of the tree to the passed array while (enumerator.MoveNext() && arrayIndex < array.Length) @@ -197,7 +188,7 @@ public void CopyTo(T[] array, int arrayIndex) /// public void Clear() { - this._collection = new RedBlackTree(); + _collection = new RedBlackTree(); } @@ -205,12 +196,12 @@ public void Clear() public IEnumerator GetEnumerator() { - return this._collection.GetInOrderEnumerator(); + return _collection.GetInOrderEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { - return this.GetEnumerator(); + return GetEnumerator(); } #endregion diff --git a/DataStructures/Trees/AVLTree.cs b/DataStructures/Trees/AVLTree.cs index b4e93224..a737f4e3 100644 --- a/DataStructures/Trees/AVLTree.cs +++ b/DataStructures/Trees/AVLTree.cs @@ -13,8 +13,8 @@ public class AVLTree : BinarySearchTree where T : IComparable /// public new AVLTreeNode Root { - get { return (AVLTreeNode)base.Root; } - internal set { base.Root = value; } + get => (AVLTreeNode)base.Root; + internal set => base.Root = value; } /// @@ -96,7 +96,7 @@ private void _rotateLeftAt(AVLTreeNode currentNode) bool isLeftChild = currentNode.IsLeftChild; // Check if currentNode is the Root - bool isRootNode = (currentNode == this.Root); + bool isRootNode = (currentNode == Root); // Perform the rotation currentNode.RightChild = pivotNode.LeftChild; @@ -111,7 +111,7 @@ private void _rotateLeftAt(AVLTreeNode currentNode) //Update the entire tree's Root if necessary if (isRootNode) - this.Root = pivotNode; + Root = pivotNode; // Update the original parent's child node if (isLeftChild) @@ -143,7 +143,7 @@ private void _rotateRightAt(AVLTreeNode currentNode) bool isLeftChild = currentNode.IsLeftChild; // Check if currentNode is the Root - bool isRootNode = (currentNode == this.Root); + bool isRootNode = (currentNode == Root); // Perform the rotation currentNode.LeftChild = pivotNode.RightChild; @@ -158,7 +158,7 @@ private void _rotateRightAt(AVLTreeNode currentNode) // Update the entire tree's Root if necessary if (isRootNode) - this.Root = pivotNode; + Root = pivotNode; // Update the original parent's child node if (isLeftChild) @@ -301,7 +301,7 @@ public override void Insert(T[] collection) if (collection.Length > 0) for (int i = 0; i < collection.Length; ++i) - this.Insert(collection[i]); + Insert(collection[i]); } /// @@ -314,7 +314,7 @@ public override void Insert(List collection) if (collection.Count > 0) for (int i = 0; i < collection.Count; ++i) - this.Insert(collection[i]); + Insert(collection[i]); } /// diff --git a/DataStructures/Trees/AVLTreeNode.cs b/DataStructures/Trees/AVLTreeNode.cs index b053836a..a288cf65 100644 --- a/DataStructures/Trees/AVLTreeNode.cs +++ b/DataStructures/Trees/AVLTreeNode.cs @@ -5,9 +5,7 @@ /// public class AVLTreeNode : BSTNode where T : System.IComparable { - private int _height = 0; - - public AVLTreeNode() : this(default(T), 0, null, null, null) { } + public AVLTreeNode() : this(default, 0, null, null, null) { } public AVLTreeNode(T value) : this(value, 0, null, null, null) { } public AVLTreeNode(T value, int height, AVLTreeNode parent, AVLTreeNode left, AVLTreeNode right) { @@ -18,28 +16,24 @@ public AVLTreeNode(T value, int height, AVLTreeNode parent, AVLTreeNode le RightChild = right; } - public virtual int Height - { - get { return this._height; } - set { this._height = value; } - } + public virtual int Height { get; set; } = 0; public new AVLTreeNode Parent { - get { return (AVLTreeNode)base.Parent; } - set { base.Parent = value; } + get => (AVLTreeNode)base.Parent; + set => base.Parent = value; } public new AVLTreeNode LeftChild { - get { return (AVLTreeNode)base.LeftChild; } - set { base.LeftChild = value; } + get => (AVLTreeNode)base.LeftChild; + set => base.LeftChild = value; } public new AVLTreeNode RightChild { - get { return (AVLTreeNode)base.RightChild; } - set { base.RightChild = value; } + get => (AVLTreeNode)base.RightChild; + set => base.RightChild = value; } } } diff --git a/DataStructures/Trees/AugmentedBinarySearchTree.cs b/DataStructures/Trees/AugmentedBinarySearchTree.cs index 70202746..c36451ba 100644 --- a/DataStructures/Trees/AugmentedBinarySearchTree.cs +++ b/DataStructures/Trees/AugmentedBinarySearchTree.cs @@ -11,9 +11,7 @@ namespace DataStructures.Trees public class BSTRankedNode : BSTNode where T : IComparable { - private int _subtreeSize = 0; - - public BSTRankedNode() : this(default(T), 0, null, null, null) { } + public BSTRankedNode() : this(default, 0, null, null, null) { } public BSTRankedNode(T value) : this(value, 0, null, null, null) { } public BSTRankedNode(T value, int subtreeSize, BSTRankedNode parent, BSTRankedNode left, BSTRankedNode right) { @@ -25,28 +23,24 @@ public BSTRankedNode(T value, int subtreeSize, BSTRankedNode parent, BSTRanke } // Size of subtrees - public virtual int SubtreeSize - { - get { return this._subtreeSize; } - set { this._subtreeSize = value; } - } + public virtual int SubtreeSize { get; set; } = 0; public new BSTRankedNode Parent { - get { return (BSTRankedNode)base.Parent; } - set { base.Parent = value; } + get => (BSTRankedNode)base.Parent; + set => base.Parent = value; } public new BSTRankedNode LeftChild { - get { return (BSTRankedNode)base.LeftChild; } - set { base.LeftChild = value; } + get => (BSTRankedNode)base.LeftChild; + set => base.LeftChild = value; } public new BSTRankedNode RightChild { - get { return (BSTRankedNode)base.RightChild; } - set { base.RightChild = value; } + get => (BSTRankedNode)base.RightChild; + set => base.RightChild = value; } } @@ -66,8 +60,8 @@ public class AugmentedBinarySearchTree : BinarySearchTree where T : ICompa /// public new BSTRankedNode Root { - get { return (BSTRankedNode)base.Root; } - set { base.Root = value; } + get => (BSTRankedNode)base.Root; + set => base.Root = value; } @@ -95,8 +89,8 @@ public override int Height if (IsEmpty) return 0; - var currentNode = this.Root; - return this._getTreeHeight(currentNode); + var currentNode = Root; + return _getTreeHeight(currentNode); } } @@ -231,7 +225,7 @@ public override void Insert(T[] collection) if (collection.Length > 0) for (int i = 0; i < collection.Length; ++i) - this.Insert(collection[i]); + Insert(collection[i]); } /// @@ -244,7 +238,7 @@ public override void Insert(List collection) if (collection.Count > 0) for (int i = 0; i < collection.Count; ++i) - this.Insert(collection[i]); + Insert(collection[i]); } /// @@ -256,9 +250,9 @@ public override void Remove(T item) if (IsEmpty) throw new Exception("Tree is empty."); - var node = (BSTRankedNode)base._findNode(this.Root, item); + var node = (BSTRankedNode)base._findNode(Root, item); bool status = _remove(node); - this._updateSubtreeSize(node.Parent); + _updateSubtreeSize(node.Parent); // If the element was found, remove it. if (status == false) @@ -273,12 +267,12 @@ public override void RemoveMin() if (IsEmpty) throw new Exception("Tree is empty."); - var node = (BSTRankedNode)_findMinNode(this.Root); + var node = (BSTRankedNode)_findMinNode(Root); var parent = node.Parent; - this._remove(node); + _remove(node); // Update the subtrees-sizes - this._updateSubtreeSize(parent); + _updateSubtreeSize(parent); } /// @@ -289,12 +283,12 @@ public override void RemoveMax() if (IsEmpty) throw new Exception("Tree is empty."); - var node = (BSTRankedNode)_findMaxNode(this.Root); + var node = (BSTRankedNode)_findMaxNode(Root); var parent = node.Parent; - this._remove(node); + _remove(node); // Update the subtrees-sizes - this._updateSubtreeSize(parent); + _updateSubtreeSize(parent); } /// @@ -304,11 +298,11 @@ public override void RemoveMax() /// Rank(item) if found; otherwise throws an exception. public virtual int Rank(T item) { - var node = (BSTRankedNode)base._findNode(this.Root, item); + var node = (BSTRankedNode)base._findNode(Root, item); if (node == null) throw new Exception("Item was not found."); - return (this._subtreeSize(node.LeftChild) + 1); + return (_subtreeSize(node.LeftChild) + 1); } } diff --git a/DataStructures/Trees/BTree.cs b/DataStructures/Trees/BTree.cs index fcc1f7a5..0a4bc502 100644 --- a/DataStructures/Trees/BTree.cs +++ b/DataStructures/Trees/BTree.cs @@ -17,32 +17,29 @@ public class BTree where T : IComparable /// CONSTRUCTOR. /// public BTree(int minDegree) { - this._minDegree = minDegree; - this._count = 0; + _minDegree = minDegree; + _count = 0; } - public BTreeNode Root - { - get { return this._root; } - } + public BTreeNode Root => _root; /// /// Inserts an item to the tree. /// public void Insert(T value) { - if (this._root == null) + if (_root == null) { - this._root = new BTreeNode(this._minDegree); - this._root.Keys.Add(value); + _root = new BTreeNode(_minDegree); + _root.Keys.Add(value); } else { - if (this._root.Keys.Count >= 2*this._minDegree-1) + if (_root.Keys.Count >= 2*_minDegree-1) { - var newRoot = new BTreeNode(this._minDegree); - newRoot.Children.Add(this._root); - newRoot.SplitChild(0, this._root); + var newRoot = new BTreeNode(_minDegree); + newRoot.Children.Add(_root); + newRoot.SplitChild(0, _root); // Which of the 2 children should hold the new value? var i = 0; @@ -52,11 +49,11 @@ public void Insert(T value) } newRoot.Children[i].InsertNonFull(value); - this._root = newRoot; + _root = newRoot; } else { - this._root.InsertNonFull(value); + _root.InsertNonFull(value); } } } @@ -66,10 +63,10 @@ public void Insert(T value) /// public BTreeNode Search(T value) { - if (this._root == null) + if (_root == null) return null; - return this._root.Search(value); + return _root.Search(value); } /// @@ -77,63 +74,45 @@ public BTreeNode Search(T value) /// public void Remove(T item) { - if (this._root == null) + if (_root == null) { Console.WriteLine("The B Tree is empty."); return; } - this._root.Remove(item); - if (this._root.Keys.Count == 0) + _root.Remove(item); + if (_root.Keys.Count == 0) { - if (this._root.IsLeaf) + if (_root.IsLeaf) { - this._root = null; + _root = null; } else { - this._root = this.Root.Children[0]; + _root = Root.Children[0]; } } } } - public class BTreeNode : System.IComparable> where T : System.IComparable + public class BTreeNode : IComparable> where T : IComparable { - private BTreeNode _parent; - private List> _children; private int _degree; - private List _keys; public BTreeNode(int degree) { - this._degree = degree; - this._children = new List>(degree*2-1); - this._keys = new List(degree*2-1); + _degree = degree; + Children = new List>(degree*2-1); + Keys = new List(degree*2-1); } - public BTreeNode Parent - { - get { return this._parent; } - set { this._parent = value; } - } + public BTreeNode Parent { get; set; } - public List Keys - { - set { this._keys = value; } - get { return this._keys; } - } + public List Keys { set; get; } - public List> Children - { - set { this._children = value; } - get { return this._children; } - } + public List> Children { set; get; } - public bool IsLeaf - { - get { return (this._children.Count == 0); } - } + public bool IsLeaf => (Children.Count == 0); /// /// A utility function that returns the index of the first key @@ -141,38 +120,38 @@ public bool IsLeaf /// public int FindKey(T value) { - return this.Keys.FindLastIndex(searching => value.CompareTo(searching) > 0) + 1; + return Keys.FindLastIndex(searching => value.CompareTo(searching) > 0) + 1; } public void Remove(T value) { - var index = this.FindKey(value); + var index = FindKey(value); // We found the key! - if (index < this.Keys.Count && value.CompareTo(this.Keys[index]) == 0) + if (index < Keys.Count && value.CompareTo(Keys[index]) == 0) { - if (this.IsLeaf) - this.RemoveFromLeaf(index); + if (IsLeaf) + RemoveFromLeaf(index); else - this.RemoveFromNonLeaf(index); + RemoveFromNonLeaf(index); } else { - if (this.IsLeaf) + if (IsLeaf) return; - var didMergeLast = (index == this.Children.Count); + var didMergeLast = (index == Children.Count); - if (this.Children[index].Keys.Count < this._degree) - this.Fill(index); + if (Children[index].Keys.Count < _degree) + Fill(index); // If the last child has been merged, it must have merged with the previous // child and so we recurse on the (idx-1)th child. Else, we recurse on the // (idx)th child which now has atleast t keys - if (didMergeLast && index > this.Children.Count) - this.Children[index-1].Remove(value); + if (didMergeLast && index > Children.Count) + Children[index-1].Remove(value); else - this.Children[index].Remove(value); + Children[index].Remove(value); } } @@ -181,7 +160,7 @@ public void Remove(T value) /// public void RemoveFromLeaf(int index) { - this.Keys.RemoveAt(index); + Keys.RemoveAt(index); } /// @@ -193,21 +172,21 @@ public void RemoveFromNonLeaf(int index) // find the predecessor of our key in the subtree rooted at the child // at index. Replace our key by it's pred. Recursively delete pred in // the list of children. - if (this.Children[index].Keys.Count >= this._degree) + if (Children[index].Keys.Count >= _degree) { - var pred = this.GetPredecessor(index); - this.Keys[index] = pred; - this.Children[index].Remove(pred); + var pred = GetPredecessor(index); + Keys[index] = pred; + Children[index].Remove(pred); } // If the child has less than this._degree keys, examine the child on // the other side. If it has atleast this._degree keys, find the successor // of the key in the subtree rooted at our next child. Replace the key with // the successor. Recursively delete the successor in the next child. - else if (this.Children[index+1].Keys.Count >= this._degree) + else if (Children[index+1].Keys.Count >= _degree) { - var succ = this.GetSuccessor(index); - this.Keys[index] = succ; - this.Children[index+1].Remove(succ); + var succ = GetSuccessor(index); + Keys[index] = succ; + Children[index+1].Remove(succ); } // If both the previous child and the next child has less than this._degree // keys, merge our key and all of the next child into the previous child. @@ -215,8 +194,8 @@ public void RemoveFromNonLeaf(int index) // delete our key from the previous child. else { - this.Merge(index); - this.Children[index].Remove(this.Keys[index]); + Merge(index); + Children[index].Remove(Keys[index]); } } @@ -226,19 +205,19 @@ public void RemoveFromNonLeaf(int index) private void Fill(int index) { // If the previous child has keys to spare, take them. - if (index != 0 && this.Children[index-1].Keys.Count >= this._degree) - this.BorrowFromPrevious(index); + if (index != 0 && Children[index-1].Keys.Count >= _degree) + BorrowFromPrevious(index); // If the next child has keys to spare, take them. - else if (index != this.Keys.Count && this.Children[index].Keys.Count >= this._degree) - this.BorrowFromNext(index); + else if (index != Keys.Count && Children[index].Keys.Count >= _degree) + BorrowFromNext(index); // Merge this sibling with the next, or previous in the event that this // is the last child. else { - if (index != this.Children.Count-1) - this.Merge(index); + if (index != Children.Count-1) + Merge(index); else - this.Merge(index-1); + Merge(index-1); } } @@ -247,7 +226,7 @@ private void Fill(int index) /// private T GetPredecessor(int index) { - var node = this.Children[index]; + var node = Children[index]; while (!node.IsLeaf) node = node.Children[node.Children.Count-1]; return node.Keys[node.Keys.Count-1]; @@ -258,7 +237,7 @@ private T GetPredecessor(int index) /// private T GetSuccessor(int index) { - var node = this.Children[index+1]; + var node = Children[index+1]; while (!node.IsLeaf) node = node.Children[0]; return node.Keys[0]; @@ -269,19 +248,19 @@ private T GetSuccessor(int index) /// private void Merge(int index) { - var child = this.Children[index]; - var sibling = this.Children[index+1]; + var child = Children[index]; + var sibling = Children[index+1]; // Add our key and the siblings keys to the child. - child.Keys.Insert(this._degree-1, this.Keys[index]); - this.Keys.RemoveAt(index); + child.Keys.Insert(_degree-1, Keys[index]); + Keys.RemoveAt(index); child.Keys.AddRange(sibling.Keys); // Now move the children. if (!child.IsLeaf) child.Children.AddRange(sibling.Children); - this.Children.RemoveAt(index+1); + Children.RemoveAt(index+1); } /// @@ -290,12 +269,12 @@ private void Merge(int index) /// private void BorrowFromPrevious(int index) { - var child = this.Children[index]; - var sibling = this.Children[index-1]; + var child = Children[index]; + var sibling = Children[index-1]; // Rotate keys: sibling > parent > child - child.Keys.Insert(0, this.Keys[index-1]); - this.Keys[index-1] = sibling.Keys[sibling.Keys.Count-1]; + child.Keys.Insert(0, Keys[index-1]); + Keys[index-1] = sibling.Keys[sibling.Keys.Count-1]; sibling.Keys.RemoveAt(sibling.Keys.Count-1); // Rotate children, if its not a leaf node @@ -312,12 +291,12 @@ private void BorrowFromPrevious(int index) /// private void BorrowFromNext(int index) { - var child = this.Children[index]; - var sibling = this.Children[index+1]; + var child = Children[index]; + var sibling = Children[index+1]; // Rotate keys sibling > parent > child - child.Keys.Add(this.Keys[index]); - this.Keys[index] = sibling.Keys[0]; + child.Keys.Add(Keys[index]); + Keys[index] = sibling.Keys[0]; sibling.Keys.RemoveAt(0); // Rotate children if it's not a leaf node @@ -333,15 +312,15 @@ private void BorrowFromNext(int index) /// public BTreeNode Search(T value) { - var found = this.Keys.FindIndex(searching => value.CompareTo(searching) == 0); + var found = Keys.FindIndex(searching => value.CompareTo(searching) == 0); if (found != -1) return this; - if (found == -1 && this.IsLeaf) + if (found == -1 && IsLeaf) return null; // Find the child - found = this.Keys.FindLastIndex(searching => value.CompareTo(searching) > 0) + 1; - return this.Children[found].Search(value); + found = Keys.FindLastIndex(searching => value.CompareTo(searching) > 0) + 1; + return Children[found].Search(value); } /// @@ -350,36 +329,36 @@ public BTreeNode Search(T value) /// public void InsertNonFull(T value) { - if (this.IsLeaf) + if (IsLeaf) { // Find where the new key should be inserted. - var i = this.Keys.FindLastIndex( + var i = Keys.FindLastIndex( delegate(T compare) { return value.CompareTo(compare) > 0; } ) + 1; - this.Keys.Insert(i, value); + Keys.Insert(i, value); } else { // Find which child to explore - var i = this.Keys.FindLastIndex( + var i = Keys.FindLastIndex( delegate(T compare) { return value.CompareTo(compare) > 0; } ) + 1; - if (this.Children[i].Keys.Count >= 2*this._degree-1) + if (Children[i].Keys.Count >= 2*_degree-1) { - this.SplitChild(i, this.Children[i]); + SplitChild(i, Children[i]); // One of the new nodes will need to have our value. - if (value.CompareTo(this.Keys[i]) > 0) + if (value.CompareTo(Keys[i]) > 0) i++; } - this.Children[i].InsertNonFull(value); + Children[i].InsertNonFull(value); } } @@ -405,10 +384,10 @@ public void SplitChild(int i, BTreeNode child) // Insert the new node in this list of children. // Keep in mind the index i is for the keys, not children. - this.Children.Insert(i+1, node); + Children.Insert(i+1, node); // One of the keys of child will move up to this node. - this.Keys.Insert(i, mid); + Keys.Insert(i, mid); } /// @@ -419,7 +398,7 @@ public virtual int CompareTo(BTreeNode other) if (other == null) return -1; - if (other.Children.Count != this.Children.Count) + if (other.Children.Count != Children.Count) return -1; return 0; diff --git a/DataStructures/Trees/BinarySearchTree.cs b/DataStructures/Trees/BinarySearchTree.cs index 99169607..a4e0fcb2 100644 --- a/DataStructures/Trees/BinarySearchTree.cs +++ b/DataStructures/Trees/BinarySearchTree.cs @@ -34,8 +34,8 @@ public enum TraversalMode public virtual BSTNode Root { - get { return this._root; } - internal set { this._root = value; } + get => _root; + internal set => _root = value; } @@ -133,7 +133,7 @@ protected virtual bool _remove(BSTNode node) protected virtual bool _insertNode(BSTNode newNode) { // Handle empty trees - if (this.Root == null) + if (Root == null) { Root = newNode; _count++; @@ -141,7 +141,7 @@ protected virtual bool _insertNode(BSTNode newNode) } if (newNode.Parent == null) - newNode.Parent = this.Root; + newNode.Parent = Root; // Check for value equality and whether inserting duplicates is allowed if (_allowDuplicates == false && newNode.Parent.Value.IsEqualTo(newNode.Value)) @@ -356,19 +356,13 @@ protected virtual void _inOrderTraverse(BSTNode currentNode, ref List list /// Return the number of elements in this tree /// /// - public virtual int Count - { - get { return _count; } - } + public virtual int Count => _count; /// /// Checks if tree is empty. /// /// - public virtual bool IsEmpty - { - get { return (_count == 0); } - } + public virtual bool IsEmpty => (_count == 0); /// /// Returns the height of the tree. @@ -387,10 +381,7 @@ public virtual int Height } } - public virtual bool AllowsDuplicates - { - get { return _allowDuplicates; } - } + public virtual bool AllowsDuplicates => _allowDuplicates; /// /// Inserts an element to the tree @@ -419,7 +410,7 @@ public virtual void Insert(T[] collection) { for (int i = 0; i < collection.Length; ++i) { - this.Insert(collection[i]); + Insert(collection[i]); } } } @@ -436,7 +427,7 @@ public virtual void Insert(List collection) { for (int i = 0; i < collection.Count; ++i) { - this.Insert(collection[i]); + Insert(collection[i]); } } } @@ -587,7 +578,7 @@ public virtual IEnumerable FindAll(Predicate searchPredicate) /// The array. public virtual T[] ToArray() { - return this.ToList().ToArray(); + return ToList().ToArray(); } /// @@ -660,15 +651,9 @@ private void visitNode(BSTNode node) visitNode(node.RightChild); } - public T Current - { - get { return current.Value; } - } + public T Current => current.Value; - object IEnumerator.Current - { - get { return Current; } - } + object IEnumerator.Current => Current; public void Dispose() { @@ -720,15 +705,9 @@ private void visitNode(BSTNode node) visitNode(node.RightChild); } - public T Current - { - get { return current.Value; } - } + public T Current => current.Value; - object IEnumerator.Current - { - get { return Current; } - } + object IEnumerator.Current => Current; public void Dispose() { @@ -779,15 +758,9 @@ private void visitNode(BSTNode node) traverseQueue.Enqueue(node); } - public T Current - { - get { return current.Value; } - } + public T Current => current.Value; - object IEnumerator.Current - { - get { return Current; } - } + object IEnumerator.Current => Current; public void Dispose() { diff --git a/DataStructures/Trees/BinarySearchTreeMap.cs b/DataStructures/Trees/BinarySearchTreeMap.cs index 3afb5b98..8e3d5af7 100644 --- a/DataStructures/Trees/BinarySearchTreeMap.cs +++ b/DataStructures/Trees/BinarySearchTreeMap.cs @@ -31,8 +31,8 @@ public enum TraversalMode public virtual BSTMapNode Root { - get { return this._root; } - internal set { this._root = value; } + get => _root; + internal set => _root = value; } @@ -86,7 +86,7 @@ protected virtual int _getTreeHeight(BSTMapNode node) protected virtual bool _insertNode(BSTMapNode newNode) { // Handle empty trees - if (this.Root == null) + if (Root == null) { Root = newNode; _count++; @@ -94,7 +94,7 @@ protected virtual bool _insertNode(BSTMapNode newNode) } if (newNode.Parent == null) - newNode.Parent = this.Root; + newNode.Parent = Root; // Check for value equality and whether inserting duplicates is allowed if (_allowDuplicates == false && newNode.Parent.Key.IsEqualTo(newNode.Key)) @@ -327,18 +327,12 @@ protected virtual void _inOrderTraverse(BSTMapNode currentNode, re /// /// Return the number of elements in this tree /// - public virtual int Count - { - get { return _count; } - } + public virtual int Count => _count; /// /// Checks if tree is empty. /// - public virtual bool IsEmpty - { - get { return (_count == 0); } - } + public virtual bool IsEmpty => (_count == 0); /// /// Returns the height of the tree. @@ -356,10 +350,7 @@ public virtual int Height } } - public virtual bool AllowsDuplicates - { - get { return _allowDuplicates; } - } + public virtual bool AllowsDuplicates => _allowDuplicates; /// /// Inserts a key-value pair to the tree @@ -395,7 +386,7 @@ public virtual void Insert(TKey[] collection) { for (int i = 0; i < collection.Length; ++i) { - this.Insert(collection[i], default(TValue)); + Insert(collection[i], default); } } } @@ -412,7 +403,7 @@ public virtual void Insert(KeyValuePair[] collection) { for (int i = 0; i < collection.Length; ++i) { - this.Insert(collection[i].Key, collection[i].Value); + Insert(collection[i].Key, collection[i].Value); } } } @@ -429,7 +420,7 @@ public virtual void Insert(List collection) { for (int i = 0; i < collection.Count; ++i) { - this.Insert(collection[i], default(TValue)); + Insert(collection[i], default); } } } @@ -446,7 +437,7 @@ public virtual void Insert(List> collection) { for (int i = 0; i < collection.Count; ++i) { - this.Insert(collection[i].Key, collection[i].Value); + Insert(collection[i].Key, collection[i].Value); } } } @@ -613,7 +604,7 @@ public virtual IEnumerable> FindAll(Predicate s /// The array. public virtual KeyValuePair[] ToArray() { - return this.ToList().ToArray(); + return ToList().ToArray(); } /// @@ -685,15 +676,9 @@ private void visitNode(BSTMapNode node) visitNode(node.RightChild); } - public KeyValuePair Current - { - get { return new KeyValuePair(current.Key, current.Value); } - } + public KeyValuePair Current => new KeyValuePair(current.Key, current.Value); - object IEnumerator.Current - { - get { return Current; } - } + object IEnumerator.Current => Current; public void Dispose() { @@ -745,15 +730,9 @@ private void visitNode(BSTMapNode node) visitNode(node.RightChild); } - public KeyValuePair Current - { - get { return new KeyValuePair(current.Key, current.Value); } - } + public KeyValuePair Current => new KeyValuePair(current.Key, current.Value); - object IEnumerator.Current - { - get { return Current; } - } + object IEnumerator.Current => Current; public void Dispose() { @@ -804,15 +783,9 @@ private void visitNode(BSTMapNode node) traverseQueue.Enqueue(node); } - public KeyValuePair Current - { - get { return new KeyValuePair(current.Key, current.Value); } - } + public KeyValuePair Current => new KeyValuePair(current.Key, current.Value); - object IEnumerator.Current - { - get { return Current; } - } + object IEnumerator.Current => Current; public void Dispose() { diff --git a/DataStructures/Trees/BinarySearchTreeMapNode.cs b/DataStructures/Trees/BinarySearchTreeMapNode.cs index 7e8cbf9e..e06af3f6 100644 --- a/DataStructures/Trees/BinarySearchTreeMapNode.cs +++ b/DataStructures/Trees/BinarySearchTreeMapNode.cs @@ -7,14 +7,8 @@ namespace DataStructures.Trees /// public class BSTMapNode : IComparable> where TKey : IComparable { - private TKey _key; - private TValue _value; - private BSTMapNode _parent; - private BSTMapNode _left; - private BSTMapNode _right; - public BSTMapNode() { } - public BSTMapNode(TKey key) : this(key, default(TValue), 0, null, null, null) { } + public BSTMapNode(TKey key) : this(key, default, 0, null, null, null) { } public BSTMapNode(TKey key, TValue value) : this(key, value, 0, null, null, null) { } public BSTMapNode(TKey key, TValue value, int subTreeSize, BSTMapNode parent, BSTMapNode left, BSTMapNode right) { @@ -25,83 +19,45 @@ public BSTMapNode(TKey key, TValue value, int subTreeSize, BSTMapNode Parent - { - get { return this._parent; } - set { this._parent = value; } - } + public virtual BSTMapNode Parent { get; set; } - public virtual BSTMapNode LeftChild - { - get { return this._left; } - set { this._left = value; } - } + public virtual BSTMapNode LeftChild { get; set; } - public virtual BSTMapNode RightChild - { - get { return this._right; } - set { this._right = value; } - } + public virtual BSTMapNode RightChild { get; set; } /// /// Checks whether this node has any children. /// - public virtual bool HasChildren - { - get { return (this.ChildrenCount > 0); } - } + public virtual bool HasChildren => (ChildrenCount > 0); /// /// Checks whether this node has left child. /// - public virtual bool HasLeftChild - { - get { return (this.LeftChild != null); } - } + public virtual bool HasLeftChild => (LeftChild != null); /// /// Checks whether this node has right child. /// - public virtual bool HasRightChild - { - get { return (this.RightChild != null); } - } + public virtual bool HasRightChild => (RightChild != null); /// /// Checks whether this node is the left child of it's parent. /// - public virtual bool IsLeftChild - { - get { return (this.Parent != null && this.Parent.LeftChild == this); } - } + public virtual bool IsLeftChild => (Parent != null && Parent.LeftChild == this); /// /// Checks whether this node is the left child of it's parent. /// - public virtual bool IsRightChild - { - get { return (this.Parent != null && this.Parent.RightChild == this); } - } + public virtual bool IsRightChild => (Parent != null && Parent.RightChild == this); /// /// Checks whether this node is a leaf node. /// - public virtual bool IsLeafNode - { - get { return (this.ChildrenCount == 0); } - } + public virtual bool IsLeafNode => (ChildrenCount == 0); /// /// Returns number of direct descendents: 0, 1, 2 (none, left or right, or both). @@ -113,10 +69,10 @@ public virtual int ChildrenCount { int count = 0; - if (this.HasLeftChild) + if (HasLeftChild) count++; - if (this.HasRightChild) + if (HasRightChild) count++; return count; @@ -131,7 +87,7 @@ public virtual int CompareTo(BSTMapNode other) if (other == null) return -1; - return this.Key.CompareTo(other.Key); + return Key.CompareTo(other.Key); } }//end-of-bstnode } diff --git a/DataStructures/Trees/BinarySearchTreeNode.cs b/DataStructures/Trees/BinarySearchTreeNode.cs index dad2455a..45c3708e 100644 --- a/DataStructures/Trees/BinarySearchTreeNode.cs +++ b/DataStructures/Trees/BinarySearchTreeNode.cs @@ -5,12 +5,7 @@ /// public class BSTNode : System.IComparable> where T : System.IComparable { - private T _value; - private BSTNode _parent; - private BSTNode _left; - private BSTNode _right; - - public BSTNode() : this(default(T), 0, null, null, null) { } + public BSTNode() : this(default, 0, null, null, null) { } public BSTNode(T value) : this(value, 0, null, null, null) { } public BSTNode(T value, int subTreeSize, BSTNode parent, BSTNode left, BSTNode right) { @@ -20,87 +15,53 @@ public BSTNode(T value, int subTreeSize, BSTNode parent, BSTNode left, BST RightChild = right; } - public virtual T Value - { - get { return this._value; } - set { this._value = value; } - } + public virtual T Value { get; set; } - public virtual BSTNode Parent - { - get { return this._parent; } - set { this._parent = value; } - } + public virtual BSTNode Parent { get; set; } - public virtual BSTNode LeftChild - { - get { return this._left; } - set { this._left = value; } - } + public virtual BSTNode LeftChild { get; set; } - public virtual BSTNode RightChild - { - get { return this._right; } - set { this._right = value; } - } + public virtual BSTNode RightChild { get; set; } /// /// Checks whether this node has any children. /// - public virtual bool HasChildren - { - get { return (this.ChildrenCount > 0); } - } + public virtual bool HasChildren => (ChildrenCount > 0); /// /// Checks whether this node has left child. /// - public virtual bool HasLeftChild - { - get { return (this.LeftChild != null); } - } + public virtual bool HasLeftChild => (LeftChild != null); /// /// Check if this node has only one child and whether it is the right child. /// - public virtual bool HasOnlyRightChild => !this.HasLeftChild && this.HasRightChild; + public virtual bool HasOnlyRightChild => !HasLeftChild && HasRightChild; /// /// Checks whether this node has right child. /// - public virtual bool HasRightChild - { - get { return (this.RightChild != null); } - } + public virtual bool HasRightChild => (RightChild != null); /// /// Check if this node has only one child and whether it is the left child. /// - public virtual bool HasOnlyLeftChild => !this.HasRightChild && this.HasLeftChild; + public virtual bool HasOnlyLeftChild => !HasRightChild && HasLeftChild; /// /// Checks whether this node is the left child of it's parent. /// - public virtual bool IsLeftChild - { - get { return (this.Parent != null && this.Parent.LeftChild == this); } - } + public virtual bool IsLeftChild => (Parent != null && Parent.LeftChild == this); /// /// Checks whether this node is the left child of it's parent. /// - public virtual bool IsRightChild - { - get { return (this.Parent != null && this.Parent.RightChild == this); } - } + public virtual bool IsRightChild => (Parent != null && Parent.RightChild == this); /// /// Checks whether this node is a leaf node. /// - public virtual bool IsLeafNode - { - get { return (this.ChildrenCount == 0); } - } + public virtual bool IsLeafNode => (ChildrenCount == 0); /// /// Returns number of direct descendents: 0, 1, 2 (none, left or right, or both). @@ -112,9 +73,9 @@ public virtual int ChildrenCount { int count = 0; - if (this.HasLeftChild) + if (HasLeftChild) count++; - if (this.HasRightChild) + if (HasRightChild) count++; return count; @@ -129,7 +90,7 @@ public virtual int CompareTo(BSTNode other) if (other == null) return -1; - return this.Value.CompareTo(other.Value); + return Value.CompareTo(other.Value); } }//end-of-bstnode } diff --git a/DataStructures/Trees/RedBlackTree.cs b/DataStructures/Trees/RedBlackTree.cs index 00617df2..21b967eb 100644 --- a/DataStructures/Trees/RedBlackTree.cs +++ b/DataStructures/Trees/RedBlackTree.cs @@ -23,13 +23,13 @@ public class RedBlackTree : BinarySearchTree where TKey : IComparabl /// public new RedBlackTreeNode Root { - get { return (RedBlackTreeNode)base.Root; } - internal set { base.Root = value; } + get => (RedBlackTreeNode)base.Root; + internal set => base.Root = value; } private bool IsRoot(RedBlackTreeNode node) { - return node == this.Root; + return node == Root; } /// @@ -148,7 +148,7 @@ protected virtual void _rotateLeftAt(RedBlackTreeNode currentNode) bool isLeftChild = currentNode.IsLeftChild; // Check if currentNode is the Root - bool isRootNode = (currentNode == this.Root); + bool isRootNode = (currentNode == Root); // Perform the rotation currentNode.RightChild = pivotNode.LeftChild; @@ -163,7 +163,7 @@ protected virtual void _rotateLeftAt(RedBlackTreeNode currentNode) //Update the entire tree's Root if necessary if (isRootNode) - this.Root = pivotNode; + Root = pivotNode; // Update the original parent's child node if (isLeftChild) @@ -191,7 +191,7 @@ protected virtual void _rotateRightAt(RedBlackTreeNode currentNode) bool isLeftChild = currentNode.IsLeftChild; // Check if currentNode is the Root - bool isRootNode = (currentNode == this.Root); + bool isRootNode = (currentNode == Root); // Perform the rotation currentNode.LeftChild = pivotNode.RightChild; @@ -206,7 +206,7 @@ protected virtual void _rotateRightAt(RedBlackTreeNode currentNode) // Update the entire tree's Root if necessary if (isRootNode) - this.Root = pivotNode; + Root = pivotNode; // Update the original parent's child node if (isLeftChild) @@ -453,7 +453,7 @@ protected virtual void _adjustTreeAfterRemoval(RedBlackTreeNode currentNod /// protected override bool _remove(BSTNode nodeToDelete) { - return this._remove((RedBlackTreeNode)nodeToDelete); + return _remove((RedBlackTreeNode)nodeToDelete); } /// @@ -530,7 +530,7 @@ protected bool _remove(RedBlackTreeNode nodeToDelete) } } - base._count--; + _count--; return true; } @@ -544,7 +544,7 @@ private void Transplant(RedBlackTreeNode replaced, RedBlackTreeNode { if (replaced.Parent == null) { - this.Root = replacement; + Root = replacement; } else if (replaced == replaced.Parent.LeftChild) { @@ -597,7 +597,7 @@ public override void Insert(TKey[] collection) if (collection.Length > 0) for (int i = 0; i < collection.Length; ++i) - this.Insert(collection[i]); + Insert(collection[i]); } /// @@ -610,7 +610,7 @@ public override void Insert(List collection) if (collection.Count > 0) for (int i = 0; i < collection.Count; ++i) - this.Insert(collection[i]); + Insert(collection[i]); } /// @@ -625,7 +625,7 @@ public override void Remove(TKey item) var node = (RedBlackTreeNode)base._findNode(Root, item); // Invoke the internal remove node method. - bool status = this._remove(node); + bool status = _remove(node); if (status == false) throw new Exception("Item was not found."); @@ -643,7 +643,7 @@ public override void RemoveMin() var node = (RedBlackTreeNode)base._findMinNode(Root); // Invoke the internal remove node method. - this._remove(node); + _remove(node); } /// @@ -658,7 +658,7 @@ public override void RemoveMax() var node = (RedBlackTreeNode)base._findMaxNode(Root); // Invoke the internal remove node method. - this._remove(node); + _remove(node); } } } diff --git a/DataStructures/Trees/RedBlackTreeMap.cs b/DataStructures/Trees/RedBlackTreeMap.cs index 82901572..8c317250 100644 --- a/DataStructures/Trees/RedBlackTreeMap.cs +++ b/DataStructures/Trees/RedBlackTreeMap.cs @@ -15,8 +15,8 @@ public class RedBlackTreeMap : BinarySearchTreeMap w /// public new RedBlackTreeMapNode Root { - get { return (RedBlackTreeMapNode)base.Root; } - internal set { base.Root = value; } + get => (RedBlackTreeMapNode)base.Root; + internal set => base.Root = value; } @@ -136,7 +136,7 @@ protected virtual void _rotateLeftAt(RedBlackTreeMapNode currentNo bool isLeftChild = currentNode.IsLeftChild; // Check if currentNode is the Root - bool isRootNode = (currentNode == this.Root); + bool isRootNode = (currentNode == Root); // Perform the rotation currentNode.RightChild = pivotNode.LeftChild; @@ -151,7 +151,7 @@ protected virtual void _rotateLeftAt(RedBlackTreeMapNode currentNo //Update the entire tree's Root if necessary if (isRootNode) - this.Root = pivotNode; + Root = pivotNode; // Update the original parent's child node if (isLeftChild) @@ -179,7 +179,7 @@ protected virtual void _rotateRightAt(RedBlackTreeMapNode currentN bool isLeftChild = currentNode.IsLeftChild; // Check if currentNode is the Root - bool isRootNode = (currentNode == this.Root); + bool isRootNode = (currentNode == Root); // Perform the rotation currentNode.LeftChild = pivotNode.RightChild; @@ -194,7 +194,7 @@ protected virtual void _rotateRightAt(RedBlackTreeMapNode currentN // Update the entire tree's Root if necessary if (isRootNode) - this.Root = pivotNode; + Root = pivotNode; // Update the original parent's child node if (isLeftChild) @@ -441,7 +441,7 @@ protected virtual void _adjustTreeAfterRemoval(RedBlackTreeMapNode /// protected override bool _remove(BSTMapNode nodeToDelete) { - return this._remove((RedBlackTreeMapNode)nodeToDelete); + return _remove((RedBlackTreeMapNode)nodeToDelete); } /// @@ -514,7 +514,7 @@ protected bool _remove(RedBlackTreeMapNode nodeToDelete) } // Decrement the count - base._count--; + _count--; return true; } @@ -557,7 +557,7 @@ public override void Insert(TKey[] collection) if (collection.Length > 0) for (int i = 0; i < collection.Length; ++i) - this.Insert(collection[i], default(TValue)); + Insert(collection[i], default); } /// @@ -570,7 +570,7 @@ public override void Insert(KeyValuePair[] collection) if (collection.Length > 0) for (int i = 0; i < collection.Length; ++i) - this.Insert(collection[i].Key, collection[i].Value); + Insert(collection[i].Key, collection[i].Value); } /// @@ -583,7 +583,7 @@ public override void Insert(List collection) if (collection.Count > 0) for (int i = 0; i < collection.Count; ++i) - this.Insert(collection[i], default(TValue)); + Insert(collection[i], default); } /// @@ -596,7 +596,7 @@ public override void Insert(List> collection) if (collection.Count > 0) for (int i = 0; i < collection.Count; ++i) - this.Insert(collection[i].Key, collection[i].Value); + Insert(collection[i].Key, collection[i].Value); } /// @@ -611,7 +611,7 @@ public override void Remove(TKey key) var node = (RedBlackTreeMapNode)base._findNode(Root, key); // Invoke the internal remove node method. - bool status = this._remove(node); + bool status = _remove(node); if (status == false) throw new Exception("Item was not found."); @@ -629,7 +629,7 @@ public override void RemoveMin() var node = (RedBlackTreeMapNode)base._findMinNode(Root); // Invoke the internal remove node method. - this._remove(node); + _remove(node); } /// @@ -644,7 +644,7 @@ public override void RemoveMax() var node = (RedBlackTreeMapNode)base._findMaxNode(Root); // Invoke the internal remove node method. - this._remove(node); + _remove(node); } } diff --git a/DataStructures/Trees/RedBlackTreeMapNode.cs b/DataStructures/Trees/RedBlackTreeMapNode.cs index acb94934..ba52033c 100644 --- a/DataStructures/Trees/RedBlackTreeMapNode.cs +++ b/DataStructures/Trees/RedBlackTreeMapNode.cs @@ -5,12 +5,10 @@ /// public class RedBlackTreeMapNode : BSTMapNode where TKey : System.IComparable { - private RedBlackTreeColors _color; - /// /// CONSTRUCTORS /// - public RedBlackTreeMapNode(TKey key) : this(key, default(TValue), 0, null, null, null) { } + public RedBlackTreeMapNode(TKey key) : this(key, default, 0, null, null, null) { } public RedBlackTreeMapNode(TKey key, TValue value) : this(key, value, 0, null, null, null) { } public RedBlackTreeMapNode(TKey key, TValue value, int height, RedBlackTreeMapNode parent, RedBlackTreeMapNode left, RedBlackTreeMapNode right) { @@ -22,28 +20,24 @@ public RedBlackTreeMapNode(TKey key, TValue value, int height, RedBlackTreeMapNo RightChild = right; } - public virtual RedBlackTreeColors Color - { - get { return this._color; } - set { this._color = value; } - } + public virtual RedBlackTreeColors Color { get; set; } public new RedBlackTreeMapNode Parent { - get { return (RedBlackTreeMapNode)base.Parent; } - set { base.Parent = value; } + get => (RedBlackTreeMapNode)base.Parent; + set => base.Parent = value; } public new RedBlackTreeMapNode LeftChild { - get { return (RedBlackTreeMapNode)base.LeftChild; } - set { base.LeftChild = value; } + get => (RedBlackTreeMapNode)base.LeftChild; + set => base.LeftChild = value; } public new RedBlackTreeMapNode RightChild { - get { return (RedBlackTreeMapNode)base.RightChild; } - set { base.RightChild = value; } + get => (RedBlackTreeMapNode)base.RightChild; + set => base.RightChild = value; } @@ -53,35 +47,22 @@ public virtual RedBlackTreeColors Color /// /// Returns if this node is colored red. /// - public virtual bool IsRed - { - get { return Color == RedBlackTreeColors.Red; } - } + public virtual bool IsRed => Color == RedBlackTreeColors.Red; /// /// Checks whether this node is colored black. /// - public virtual bool IsBlack - { - get { return Color == RedBlackTreeColors.Black; } - } + public virtual bool IsBlack => Color == RedBlackTreeColors.Black; /// /// Returns the sibling of this node. /// - public virtual RedBlackTreeMapNode Sibling - { - get { return (this.Parent == null ? null : (this.IsLeftChild ? this.Parent.RightChild : this.Parent.LeftChild)); } - } + public virtual RedBlackTreeMapNode Sibling => (Parent == null ? null : (IsLeftChild ? Parent.RightChild : Parent.LeftChild)); /// /// Returns the grandparent of this node. /// - public virtual RedBlackTreeMapNode GrandParent - { - get { return (this.Parent == null ? null : this.Parent.Parent); } - } - + public virtual RedBlackTreeMapNode GrandParent => (Parent == null ? null : Parent.Parent); } } diff --git a/DataStructures/Trees/RedBlackTreeNode.cs b/DataStructures/Trees/RedBlackTreeNode.cs index e0b356a5..6d961685 100644 --- a/DataStructures/Trees/RedBlackTreeNode.cs +++ b/DataStructures/Trees/RedBlackTreeNode.cs @@ -5,12 +5,10 @@ /// public class RedBlackTreeNode : BSTNode where TKey : System.IComparable { - private RedBlackTreeColors _color; - /// /// CONSTRUCTORS /// - public RedBlackTreeNode() : this(default(TKey), 0, null, null, null) { } + public RedBlackTreeNode() : this(default, 0, null, null, null) { } public RedBlackTreeNode(TKey value) : this(value, 0, null, null, null) { } public RedBlackTreeNode(TKey value, int height, RedBlackTreeNode parent, RedBlackTreeNode left, RedBlackTreeNode right) { @@ -21,28 +19,24 @@ public RedBlackTreeNode(TKey value, int height, RedBlackTreeNode parent, R RightChild = right; } - public virtual RedBlackTreeColors Color - { - get { return this._color; } - set { this._color = value; } - } + public virtual RedBlackTreeColors Color { get; set; } public new RedBlackTreeNode Parent { - get { return (RedBlackTreeNode)base.Parent; } - set { base.Parent = value; } + get => (RedBlackTreeNode)base.Parent; + set => base.Parent = value; } public new RedBlackTreeNode LeftChild { - get { return (RedBlackTreeNode)base.LeftChild; } - set { base.LeftChild = value; } + get => (RedBlackTreeNode)base.LeftChild; + set => base.LeftChild = value; } public new RedBlackTreeNode RightChild { - get { return (RedBlackTreeNode)base.RightChild; } - set { base.RightChild = value; } + get => (RedBlackTreeNode)base.RightChild; + set => base.RightChild = value; } @@ -52,35 +46,22 @@ public virtual RedBlackTreeColors Color /// /// Returns if this node is colored red. /// - public virtual bool IsRed - { - get { return Color == RedBlackTreeColors.Red; } - } + public virtual bool IsRed => Color == RedBlackTreeColors.Red; /// /// Checks whether this node is colored black. /// - public virtual bool IsBlack - { - get { return Color == RedBlackTreeColors.Black; } - } + public virtual bool IsBlack => Color == RedBlackTreeColors.Black; /// /// Returns the sibling of this node. /// - public virtual RedBlackTreeNode Sibling - { - get { return (this.Parent == null ? null : (this.IsLeftChild ? this.Parent.RightChild : this.Parent.LeftChild)); } - } + public virtual RedBlackTreeNode Sibling => (Parent == null ? null : (IsLeftChild ? Parent.RightChild : Parent.LeftChild)); /// /// Returns the grandparent of this node. /// - public virtual RedBlackTreeNode GrandParent - { - get { return (this.Parent == null ? null : this.Parent.Parent); } - } - + public virtual RedBlackTreeNode GrandParent => (Parent == null ? null : Parent.Parent); } } diff --git a/DataStructures/Trees/TernaryTreeNode.cs b/DataStructures/Trees/TernaryTreeNode.cs index a433e55c..3c08c662 100644 --- a/DataStructures/Trees/TernaryTreeNode.cs +++ b/DataStructures/Trees/TernaryTreeNode.cs @@ -9,24 +9,24 @@ public class TernaryTreeNode public virtual TernaryTreeNode Parent { get; private set; } protected virtual TernaryTreeNode[] childs { get; set; } - public virtual TernaryTreeNode GetLeftChild { get { return childs[0]; } } - public virtual TernaryTreeNode GetMiddleChild { get { return childs[1]; } } - public virtual TernaryTreeNode GetRightChild { get { return childs[2]; } } + public virtual TernaryTreeNode GetLeftChild => childs[0]; + public virtual TernaryTreeNode GetMiddleChild => childs[1]; + public virtual TernaryTreeNode GetRightChild => childs[2]; public virtual bool FinalLetter { get; set; } public virtual char Value { get; set; } public TernaryTreeNode(TernaryTreeNode parent) { - this.Parent = parent; + Parent = parent; childs = new TernaryTreeNode[3]; } public TernaryTreeNode(TernaryTreeNode parent, char value, bool isFinal) { - this.Parent = parent; - this.Value = value; - this.FinalLetter = isFinal; + Parent = parent; + Value = value; + FinalLetter = isFinal; childs = new TernaryTreeNode[3]; } diff --git a/DataStructures/Trees/Trie.cs b/DataStructures/Trees/Trie.cs index 627dc705..641068b8 100644 --- a/DataStructures/Trees/Trie.cs +++ b/DataStructures/Trees/Trie.cs @@ -32,18 +32,12 @@ public Trie() /// /// Return count of words. /// - public int Count - { - get { return _count; } - } + public int Count => _count; /// /// Checks if element is empty. /// - public bool IsEmpty - { - get { return _count == 0; } - } + public bool IsEmpty => _count == 0; /// /// Add word to trie diff --git a/DataStructures/Trees/TrieMap.cs b/DataStructures/Trees/TrieMap.cs index 3780188a..950ab255 100644 --- a/DataStructures/Trees/TrieMap.cs +++ b/DataStructures/Trees/TrieMap.cs @@ -31,24 +31,18 @@ public class TrieMap : IDictionary, IEnumerable(' ', default(TRecord), false); + _root = new TrieMapNode(' ', default, false); } /// /// Return count of words. /// - public int Count - { - get { return _count; } - } + public int Count => _count; /// /// Checks if element is empty. /// - public bool IsEmpty - { - get { return _count == 0; } - } + public bool IsEmpty => _count == 0; /// /// Add word to trie @@ -64,7 +58,7 @@ public void Add(string word, TRecord record) { if (!current.Children.ContainsKey(word[i])) { - var newTrieNode = new TrieMapNode(word[i], default(TRecord)); + var newTrieNode = new TrieMapNode(word[i], default); newTrieNode.Parent = current; current.Children.Add(word[i], newTrieNode); } @@ -135,7 +129,7 @@ public void Remove(string word) public bool ContainsWord(string word) { TRecord record; - return this.SearchByWord(word, out record); + return SearchByWord(word, out record); } /// @@ -167,7 +161,7 @@ public bool SearchByWord(string word, out TRecord record) if (string.IsNullOrEmpty(word)) throw new InvalidOperationException("Word is either null or empty."); - record = default(TRecord); + record = default; var current = _root; for (int i = 0; i < word.Length; ++i) @@ -213,15 +207,12 @@ public void Clear() { _count = 0; _root.Clear(); - _root = new TrieMapNode(' ', default(TRecord), false); + _root = new TrieMapNode(' ', default, false); } #region IDictionary implementation - bool ICollection>.IsReadOnly - { - get { return false; } - } + bool ICollection>.IsReadOnly => false; /// /// Checks whether a specific key exists in trie as a word (terminal word). @@ -305,15 +296,12 @@ TRecord IDictionary.this[string key] return record; throw new KeyNotFoundException(); } - set - { - UpdateWord(key, value); - } + set => UpdateWord(key, value); } void ICollection>.Add(KeyValuePair item) { - this.Add(item.Key, item.Value); + Add(item.Key, item.Value); } /// @@ -323,7 +311,7 @@ bool IDictionary.Remove(string key) { try { - this.Remove(word: key); + Remove(word: key); return true; } catch @@ -339,7 +327,7 @@ bool ICollection>.Remove(KeyValuePair other) if (other == null) return -1; - return this.Key.CompareTo(other.Key); + return Key.CompareTo(other.Key); } diff --git a/DataStructures/Trees/TrieNode.cs b/DataStructures/Trees/TrieNode.cs index aba67082..5b43eb9a 100644 --- a/DataStructures/Trees/TrieNode.cs +++ b/DataStructures/Trees/TrieNode.cs @@ -105,7 +105,7 @@ public int CompareTo(TrieNode other) if (other == null) return -1; - return this.Key.CompareTo(other.Key); + return Key.CompareTo(other.Key); } diff --git a/UnitTest/DataStructuresTests/CircularBufferTest.cs b/UnitTest/DataStructuresTests/CircularBufferTest.cs index efb0bb30..a385e813 100644 --- a/UnitTest/DataStructuresTests/CircularBufferTest.cs +++ b/UnitTest/DataStructuresTests/CircularBufferTest.cs @@ -175,7 +175,7 @@ public static void TestingRemoveMethod() { circularBuffer.Add(14); //Removing default(T) from the buffer. buffer should not be affected since default is not contained - circularBuffer.Remove(default(byte)); + circularBuffer.Remove(default); Assert.Equal(3, circularBuffer.Pop()); Assert.Equal(34, circularBuffer.Pop()); Assert.Equal(24, circularBuffer.Pop()); diff --git a/UnitTest/DataStructuresTests/CliqueGraphTest.cs b/UnitTest/DataStructuresTests/CliqueGraphTest.cs index 3958ed53..d05f61d3 100644 --- a/UnitTest/DataStructuresTests/CliqueGraphTest.cs +++ b/UnitTest/DataStructuresTests/CliqueGraphTest.cs @@ -117,15 +117,7 @@ public ComparableTuple(int item1, int item2) } - int ToInt - { - get - { - return Item1 * multiplier + Item2; - } - } - - + int ToInt => Item1 * multiplier + Item2; } } diff --git a/UnitTest/UnitTest.csproj b/UnitTest/UnitTest.csproj index ad90fe4a..2d8f4762 100644 --- a/UnitTest/UnitTest.csproj +++ b/UnitTest/UnitTest.csproj @@ -1,13 +1,17 @@  - netcoreapp2.0 + net6.0 + 10 - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/global.json b/global.json new file mode 100644 index 00000000..87aef9f1 --- /dev/null +++ b/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "6.0.0", + "rollForward": "latestMajor", + "allowPrerelease": false + } +} \ No newline at end of file From ed2ed913b0bb430fda9b30d69ea21248a231a1f9 Mon Sep 17 00:00:00 2001 From: Mohamed Fazrin Date: Wed, 12 Oct 2022 09:49:25 +0300 Subject: [PATCH 2/5] IsNumber Comparer method converted to switch case from multiple if conditions --- DataStructures/Common/Comparers.cs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/DataStructures/Common/Comparers.cs b/DataStructures/Common/Comparers.cs index 8bdaeeaa..2b0869b9 100644 --- a/DataStructures/Common/Comparers.cs +++ b/DataStructures/Common/Comparers.cs @@ -13,18 +13,23 @@ public static class Comparers /// The Type of value. public static bool IsNumber(this T value) { - if (value is sbyte) return true; - if (value is byte) return true; - if (value is short) return true; - if (value is ushort) return true; - if (value is int) return true; - if (value is uint) return true; - if (value is long) return true; - if (value is ulong) return true; - if (value is float) return true; - if (value is double) return true; - if (value is decimal) return true; - return false; + switch (value) + { + case sbyte: + case byte: + case short: + case ushort: + case int: + case uint: + case long: + case ulong: + case float: + case double: + case decimal: + return true; + default: + return false; + } } public static bool IsEqualTo(this T firstValue, T secondValue) where T : IComparable From ac4f241d30e34aaf76624d54714828188813db31 Mon Sep 17 00:00:00 2001 From: Mohamed Fazrin Date: Wed, 12 Oct 2022 09:50:56 +0300 Subject: [PATCH 3/5] Typo fixed in the comment and if condition simplified with return type --- DataStructures/Common/Comparers.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/DataStructures/Common/Comparers.cs b/DataStructures/Common/Comparers.cs index 2b0869b9..637b3a23 100644 --- a/DataStructures/Common/Comparers.cs +++ b/DataStructures/Common/Comparers.cs @@ -56,16 +56,12 @@ public static bool IsLessThanOrEqualTo(this T firstValue, T secondValue) wher { return (firstValue.IsEqualTo(secondValue) || firstValue.IsLessThan(secondValue)); } - - - // + // METHODS FOR BINARY SEARCH TREE - // COMAPRES THE VALUE OF TWO NODES TOGETHER + // COMPARES THE VALUE OF TWO NODES TOGETHER private static bool HandleNullCases(BSTNode first, BSTNode second) where T : IComparable { - if (first == null || second == null) - return false; - return true; + return first != null && second != null; } public static bool IsEqualTo(this BSTNode first, BSTNode second) where T : IComparable From f5b39460a7251d2af854e99fa1db05416ab2c2a6 Mon Sep 17 00:00:00 2001 From: Mohamed Fazrin Date: Wed, 12 Oct 2022 09:53:01 +0300 Subject: [PATCH 4/5] unnecessary parenthesis are removed --- Algorithms/Graphs/BellmanFordShortestPaths.cs | 6 ++-- Algorithms/Graphs/BipartiteColoring.cs | 2 +- .../Graphs/BreadthFirstShortestPaths.cs | 6 ++-- Algorithms/Numeric/CatalanNumbers.cs | 2 +- Algorithms/Search/BinarySearcher.cs | 2 +- Algorithms/Sorting/HeapSorter.cs | 4 +-- Algorithms/Sorting/InsertionSorter.cs | 2 +- Algorithms/Sorting/QuickSorter.cs | 2 +- Algorithms/Sorting/ShellSorter.cs | 8 ++--- DataStructures/Common/Comparers.cs | 14 ++++---- DataStructures/Common/PrimesList.cs | 12 +++---- .../Dictionaries/ChainedHashTable.cs | 14 ++++---- .../Dictionaries/CuckooHashTable.cs | 8 ++--- .../Dictionaries/OpenAddressingHashTable.cs | 8 ++--- .../Dictionaries/OpenScatterHashTable.cs | 8 ++--- DataStructures/Graphs/DirectedDenseGraph.cs | 12 +++---- DataStructures/Graphs/DirectedSparseGraph.cs | 16 ++++----- .../Graphs/DirectedWeightedDenseGraph.cs | 12 +++---- .../Graphs/DirectedWeightedSparseGraph.cs | 2 +- DataStructures/Graphs/UndirectedDenseGraph.cs | 12 +++---- .../Graphs/UndirectedSparseGraph.cs | 10 +++--- .../Graphs/UndirectedWeightedDenseGraph.cs | 16 ++++----- .../Graphs/UndirectedWeightedSparseGraph.cs | 4 +-- DataStructures/Hashing/PrimeHashingFamily.cs | 2 +- .../Hashing/UniversalHashingFamily.cs | 2 +- DataStructures/Heaps/BinaryMaxHeap.cs | 6 ++-- DataStructures/Heaps/BinaryMinHeap.cs | 6 ++-- DataStructures/Heaps/BinomialMinHeap.cs | 18 +++++----- DataStructures/Lists/ArrayList.cs | 28 +++++++-------- DataStructures/Lists/CircularBuffer.cs | 2 +- DataStructures/Lists/DLinkedList.cs | 20 +++++------ DataStructures/Lists/DLinkedList_KeyValue.cs | 34 +++++++++---------- DataStructures/Lists/Queue.cs | 6 ++-- DataStructures/Lists/SLinkedList.cs | 10 +++--- DataStructures/Trees/AVLTree.cs | 6 ++-- .../Trees/AugmentedBinarySearchTree.cs | 12 +++---- DataStructures/Trees/BTree.cs | 4 +-- DataStructures/Trees/BinarySearchTree.cs | 18 +++++----- DataStructures/Trees/BinarySearchTreeMap.cs | 18 +++++----- .../Trees/BinarySearchTreeMapNode.cs | 12 +++---- DataStructures/Trees/BinarySearchTreeNode.cs | 12 +++---- DataStructures/Trees/RedBlackTree.cs | 8 ++--- DataStructures/Trees/RedBlackTreeMap.cs | 8 ++--- DataStructures/Trees/RedBlackTreeMapNode.cs | 4 +-- DataStructures/Trees/RedBlackTreeNode.cs | 4 +-- DataStructures/Trees/TreeDrawer.cs | 20 +++++------ DataStructures/Trees/TrieMap.cs | 2 +- .../AlgorithmsTests/LSDRadixSorterTest.cs | 4 +-- .../DataStructuresTests/CliqueGraphTest.cs | 2 +- .../DataStructuresTests/DLinkedListTest.cs | 2 +- .../DataStructuresTests/SortedListTests.cs | 4 +-- 51 files changed, 228 insertions(+), 228 deletions(-) diff --git a/Algorithms/Graphs/BellmanFordShortestPaths.cs b/Algorithms/Graphs/BellmanFordShortestPaths.cs index 684a6e40..96771291 100644 --- a/Algorithms/Graphs/BellmanFordShortestPaths.cs +++ b/Algorithms/Graphs/BellmanFordShortestPaths.cs @@ -80,7 +80,7 @@ private bool _bellmanFord(TGraph graph, TVertex source) // calculate a new possible weighted path if the edge weight is less than infinity var delta = Infinity; - if (edge.Weight < Infinity && (Infinity - edge.Weight) > _distances[fromIndex]) // Handles overflow + if (edge.Weight < Infinity && Infinity - edge.Weight > _distances[fromIndex]) // Handles overflow delta = _distances[fromIndex] + edge.Weight; // Relax the edge @@ -103,7 +103,7 @@ private bool _bellmanFord(TGraph graph, TVertex source) // calculate a new possible weighted path if the edge weight is less than infinity var delta = Infinity; - if (edge.Weight < Infinity && (Infinity - edge.Weight) > _distances[fromIndex]) // Handles overflow + if (edge.Weight < Infinity && Infinity - edge.Weight > _distances[fromIndex]) // Handles overflow delta = _distances[fromIndex] + edge.Weight; // if check is true a negative-weight cycle is detected @@ -209,7 +209,7 @@ private bool _checkOptimalityConditions(TGraph graph, TVertex source) if (!vertex.IsEqualTo(edge.Destination)) return false; - if ((_distances[v] + edge.Weight) != _distances[w]) + if (_distances[v] + edge.Weight != _distances[w]) { Console.WriteLine("edge " + edge.Source + "-" + edge.Destination + " on shortest path not tight"); return false; diff --git a/Algorithms/Graphs/BipartiteColoring.cs b/Algorithms/Graphs/BipartiteColoring.cs index acd6957c..8b041178 100644 --- a/Algorithms/Graphs/BipartiteColoring.cs +++ b/Algorithms/Graphs/BipartiteColoring.cs @@ -147,7 +147,7 @@ private bool _isBipartiteHelper(IGraph Graph, TVertex Source) if (!_visited[adjIndex]) { _visited[adjIndex] = true; - _nodesColors[adjIndex] = (_nodesColors[currIndex] == BipartiteColor.Red) ? BipartiteColor.Blue : BipartiteColor.Red; + _nodesColors[adjIndex] = _nodesColors[currIndex] == BipartiteColor.Red ? BipartiteColor.Blue : BipartiteColor.Red; queue.Enqueue(adjacent); } diff --git a/Algorithms/Graphs/BreadthFirstShortestPaths.cs b/Algorithms/Graphs/BreadthFirstShortestPaths.cs index 5d54a8fd..d53e6a92 100644 --- a/Algorithms/Graphs/BreadthFirstShortestPaths.cs +++ b/Algorithms/Graphs/BreadthFirstShortestPaths.cs @@ -213,7 +213,7 @@ private bool checkOptimalityConditions(IGraph graph, T source) Console.WriteLine("hasPathTo(" + adjacent + ") = " + HasPathTo(adjacent)); return false; } - if (HasPathTo(node) && (_distances[w] > _distances[v] + 1)) + if (HasPathTo(node) && _distances[w] > _distances[v] + 1) { Console.WriteLine("edge " + node + "-" + adjacent); Console.WriteLine("distanceTo[" + node + "] = " + _distances[v]); @@ -259,7 +259,7 @@ public bool HasPathTo(T destination) throw new Exception("Graph doesn't have the specified vertex."); int dstIndex = _nodesToIndices[destination]; - return (_visited[dstIndex]); + return _visited[dstIndex]; } /// @@ -271,7 +271,7 @@ public long DistanceTo(T destination) throw new Exception("Graph doesn't have the specified vertex."); int dstIndex = _nodesToIndices[destination]; - return (_distances[dstIndex]); + return _distances[dstIndex]; } /// diff --git a/Algorithms/Numeric/CatalanNumbers.cs b/Algorithms/Numeric/CatalanNumbers.cs index 36636e51..3aa698c0 100644 --- a/Algorithms/Numeric/CatalanNumbers.cs +++ b/Algorithms/Numeric/CatalanNumbers.cs @@ -39,7 +39,7 @@ private static BigInteger _recursiveHelper(uint rank) if (!CachedCatalanNumbers.ContainsKey(i)) CachedCatalanNumbers.Add(i, firstPart); if (!CachedCatalanNumbers.ContainsKey(lastRank - i)) CachedCatalanNumbers.Add(lastRank - i, secondPart); - number = number + (firstPart * secondPart); + number = number + firstPart * secondPart; } return number; diff --git a/Algorithms/Search/BinarySearcher.cs b/Algorithms/Search/BinarySearcher.cs index 918efc6a..e4940680 100644 --- a/Algorithms/Search/BinarySearcher.cs +++ b/Algorithms/Search/BinarySearcher.cs @@ -53,7 +53,7 @@ public int BinarySearch(T item) Reset(); _item = item; - while ((_leftIndex <= _rightIndex) && notFound) + while (_leftIndex <= _rightIndex && notFound) { notFound = MoveNext(); } diff --git a/Algorithms/Sorting/HeapSorter.cs b/Algorithms/Sorting/HeapSorter.cs index cb20fa11..7be00c7a 100644 --- a/Algorithms/Sorting/HeapSorter.cs +++ b/Algorithms/Sorting/HeapSorter.cs @@ -79,7 +79,7 @@ private static void BuildMaxHeap(this IList collection, int firstIndex, in private static void MaxHeapify(this IList collection, int nodeIndex, int lastIndex, Comparer comparer) { // assume left(i) and right(i) are max-heaps - int left = (nodeIndex * 2) + 1; + int left = nodeIndex * 2 + 1; int right = left + 1; int largest = nodeIndex; @@ -120,7 +120,7 @@ private static void BuildMinHeap(this IList collection, int firstIndex, in private static void MinHeapify(this IList collection, int nodeIndex, int lastIndex, Comparer comparer) { // assume left(i) and right(i) are max-heaps - int left = (nodeIndex * 2) + 1; + int left = nodeIndex * 2 + 1; int right = left + 1; int smallest = nodeIndex; diff --git a/Algorithms/Sorting/InsertionSorter.cs b/Algorithms/Sorting/InsertionSorter.cs index 28971f1c..b74bc986 100644 --- a/Algorithms/Sorting/InsertionSorter.cs +++ b/Algorithms/Sorting/InsertionSorter.cs @@ -24,7 +24,7 @@ public static void InsertionSort(this IList list, Comparer comparer = n T value = list[i]; j = i - 1; - while ((j >= 0) && (comparer.Compare(list[j], value) > 0)) + while (j >= 0 && comparer.Compare(list[j], value) > 0) { list[j + 1] = list[j]; j--; diff --git a/Algorithms/Sorting/QuickSorter.cs b/Algorithms/Sorting/QuickSorter.cs index a02afe7b..291485be 100644 --- a/Algorithms/Sorting/QuickSorter.cs +++ b/Algorithms/Sorting/QuickSorter.cs @@ -51,7 +51,7 @@ private static int InternalPartition(this IList collection, int leftmostIn wallIndex = leftmostIndex; // Loop until pivot: exclusive! - for (int i = leftmostIndex; i <= (rightmostIndex - 1); i++) + for (int i = leftmostIndex; i <= rightmostIndex - 1; i++) { // check if collection[i] <= pivotValue if (comparer.Compare(collection[i], pivotValue) <= 0) diff --git a/Algorithms/Sorting/ShellSorter.cs b/Algorithms/Sorting/ShellSorter.cs index c919523e..654f3588 100644 --- a/Algorithms/Sorting/ShellSorter.cs +++ b/Algorithms/Sorting/ShellSorter.cs @@ -18,11 +18,11 @@ public static void ShellSortAscending(this IList collection, Comparer c { bool flag = true; int d = collection.Count; - while (flag || (d > 1)) + while (flag || d > 1) { flag = false; d = (d + 1) / 2; - for (int i = 0; i < (collection.Count - d); i++) + for (int i = 0; i < collection.Count - d; i++) { if (comparer.Compare(collection[i + d], collection[i]) < 0) { @@ -40,11 +40,11 @@ public static void ShellSortDescending(this IList collection, Comparer { bool flag = true; int d = collection.Count; - while (flag || (d > 1)) + while (flag || d > 1) { flag = false; d = (d + 1) / 2; - for (int i = 0; i < (collection.Count - d); i++) + for (int i = 0; i < collection.Count - d; i++) { if (comparer.Compare(collection[i + d], collection[i])>0) { diff --git a/DataStructures/Common/Comparers.cs b/DataStructures/Common/Comparers.cs index 637b3a23..487c9155 100644 --- a/DataStructures/Common/Comparers.cs +++ b/DataStructures/Common/Comparers.cs @@ -49,12 +49,12 @@ public static bool IsLessThan(this T firstValue, T secondValue) where T : ICo public static bool IsGreaterThanOrEqualTo(this T firstValue, T secondValue) where T : IComparable { - return (firstValue.IsEqualTo(secondValue) || firstValue.IsGreaterThan(secondValue)); + return firstValue.IsEqualTo(secondValue) || firstValue.IsGreaterThan(secondValue); } public static bool IsLessThanOrEqualTo(this T firstValue, T secondValue) where T : IComparable { - return (firstValue.IsEqualTo(secondValue) || firstValue.IsLessThan(secondValue)); + return firstValue.IsEqualTo(secondValue) || firstValue.IsLessThan(secondValue); } // METHODS FOR BINARY SEARCH TREE @@ -66,27 +66,27 @@ private static bool HandleNullCases(BSTNode first, BSTNode second) wher public static bool IsEqualTo(this BSTNode first, BSTNode second) where T : IComparable { - return (HandleNullCases(first, second) && first.Value.CompareTo(second.Value) == 0); + return HandleNullCases(first, second) && first.Value.CompareTo(second.Value) == 0; } public static bool IsGreaterThan(this BSTNode first, BSTNode second) where T : IComparable { - return (HandleNullCases(first, second) && first.Value.CompareTo(second.Value) > 0); + return HandleNullCases(first, second) && first.Value.CompareTo(second.Value) > 0; } public static bool IsLessThan(this BSTNode first, BSTNode second) where T : IComparable { - return (HandleNullCases(first, second) && first.Value.CompareTo(second.Value) < 0); + return HandleNullCases(first, second) && first.Value.CompareTo(second.Value) < 0; } public static bool IsLessThanOrEqualTo(this BSTNode first, BSTNode second) where T : IComparable { - return (first.IsEqualTo(second) || first.IsLessThan(second)); + return first.IsEqualTo(second) || first.IsLessThan(second); } public static bool IsGreaterThanOrEqualTo(this BSTNode first, BSTNode second) where T : IComparable { - return (first.IsEqualTo(second) || first.IsGreaterThan(second)); + return first.IsEqualTo(second) || first.IsGreaterThan(second); } } diff --git a/DataStructures/Common/PrimesList.cs b/DataStructures/Common/PrimesList.cs index 5a9d1c23..d1e28702 100644 --- a/DataStructures/Common/PrimesList.cs +++ b/DataStructures/Common/PrimesList.cs @@ -120,14 +120,14 @@ public bool IsPrime(int candidate) for (int divisor = 3; divisor <= limit; divisor += 2) { - if ((candidate % divisor) == 0) + if (candidate % divisor == 0) return false; } return true; } - return (candidate == 2); + return candidate == 2; } /// @@ -147,9 +147,9 @@ public int GetNextPrime(int number) } // Outside of our predefined table. Compute the prime the hard way. - for (int i = (number | 1); i < Int32.MaxValue; i += 2) + for (int i = number | 1; i < Int32.MaxValue; i += 2) { - if (IsPrime(i) && ((i - 1) % HASH_PRIME != 0)) + if (IsPrime(i) && (i - 1) % HASH_PRIME != 0) return i; } @@ -171,9 +171,9 @@ public int GetPreviousPrime(int number) } // Outside of our predefined table. Compute the prime the hard way. - for (int i = (number | 1); i < Int32.MaxValue; i += 2) + for (int i = number | 1; i < Int32.MaxValue; i += 2) { - if (IsPrime(i) && ((i - 1) % HASH_PRIME != 0)) + if (IsPrime(i) && (i - 1) % HASH_PRIME != 0) return i; } diff --git a/DataStructures/Dictionaries/ChainedHashTable.cs b/DataStructures/Dictionaries/ChainedHashTable.cs index 2d135928..4d700091 100644 --- a/DataStructures/Dictionaries/ChainedHashTable.cs +++ b/DataStructures/Dictionaries/ChainedHashTable.cs @@ -101,12 +101,12 @@ private void _rehash(ref DLinkedList[] newHashTableStore, int oldH /// private void _contractCapacity() { - int oneThird = (_hashTableStore.Length / 3); + int oneThird = _hashTableStore.Length / 3; int twoThirds = 2 * oneThird; if (_size <= oneThird) { - int newCapacity = (_hashTableStore.Length == 0 ? _defaultCapacity : twoThirds); + int newCapacity = _hashTableStore.Length == 0 ? _defaultCapacity : twoThirds; // Try to expand the size DLinkedList[] newHashTableStore = new DLinkedList[newCapacity]; @@ -128,7 +128,7 @@ private void _expandCapacity(int minCapacity) { if (_hashTableStore.Length < minCapacity) { - int newCapacity = (_hashTableStore.Length == 0 ? _defaultCapacity : _hashTableStore.Length * 2); + int newCapacity = _hashTableStore.Length == 0 ? _defaultCapacity : _hashTableStore.Length * 2; // Make sure it doesn't divide by 2 or 10 if (newCapacity % 2 == 0 || newCapacity % 10 == 0) @@ -169,7 +169,7 @@ private void _ensureCapacity(CapacityManagementMode mode, int newSize = -1) { // If the size of the internal collection is less than or equal to third of // ... the total capacity then contract the internal collection - int oneThird = (_hashTableStore.Length / 3); + int oneThird = _hashTableStore.Length / 3; if (mode == CapacityManagementMode.Contract && _size <= oneThird) { @@ -197,7 +197,7 @@ private uint _universalHashFunction(TKey key, int length) int a = 197, b = 4049, p = 7199369; prehash = _getPreHashOfKey(key); - hash = Convert.ToUInt32(((a * prehash + b) % p) % length); + hash = Convert.ToUInt32((a * prehash + b) % p % length); return hash; } @@ -219,7 +219,7 @@ private uint _divisionMethodHashFunction(TKey key, int length) for (int i = 0; i < stringKey.Length; ++i) { - hash = (hash ^ stringKey[i]) + ((hash << 26) + (hash >> 6)); + hash = (hash ^ stringKey[i]) + (hash << 26) + (hash >> 6); } if (hash > length) @@ -228,7 +228,7 @@ private uint _divisionMethodHashFunction(TKey key, int length) else { prehash = _getPreHashOfKey(key); - hash = Convert.ToUInt32((37 * prehash) % length); + hash = Convert.ToUInt32(37 * prehash % length); } return hash; diff --git a/DataStructures/Dictionaries/CuckooHashTable.cs b/DataStructures/Dictionaries/CuckooHashTable.cs index 53711cc1..7efe114d 100644 --- a/DataStructures/Dictionaries/CuckooHashTable.cs +++ b/DataStructures/Dictionaries/CuckooHashTable.cs @@ -79,7 +79,7 @@ public CuckooHashTable() /// private void _expandCapacity(int minCapacity) { - int newCapacity = (_collection.Length == 0 ? DEFAULT_CAPACITY : _collection.Length * 2); + int newCapacity = _collection.Length == 0 ? DEFAULT_CAPACITY : _collection.Length * 2; // Handle overflow if (newCapacity >= MAX_ARRAY_LENGTH) @@ -166,7 +166,7 @@ private bool _isActive(int index) if (index < 0 || index > _collection.Length) throw new IndexOutOfRangeException(); - return (_collection[index] != null && _collection[index].IsActive == true); + return _collection[index] != null && _collection[index].IsActive == true; } /// @@ -264,7 +264,7 @@ public int Count() /// public bool IsEmpty() { - return (_size == 0); + return _size == 0; } /// @@ -297,7 +297,7 @@ public TValue this[TKey key] /// public bool ContainsKey(TKey key) { - return (_findPosition(key) != -1); + return _findPosition(key) != -1; } /// diff --git a/DataStructures/Dictionaries/OpenAddressingHashTable.cs b/DataStructures/Dictionaries/OpenAddressingHashTable.cs index d24b9513..67acc55b 100644 --- a/DataStructures/Dictionaries/OpenAddressingHashTable.cs +++ b/DataStructures/Dictionaries/OpenAddressingHashTable.cs @@ -135,7 +135,7 @@ private int _double_hash(TKey key, int i) //calculates first hash values hash_value = Convert.ToInt32(string_value) % _size; //calculate second hash value - second_hash_value = 1 + (Convert.ToInt32(string_value) % (_size - 1)); + second_hash_value = 1 + Convert.ToInt32(string_value) % (_size - 1); } //grabs a hash value for a char else if (typeof(TKey) == typeof(char)) @@ -149,18 +149,18 @@ private int _double_hash(TKey key, int i) //calculates first hash values hash_value = Convert.ToInt32(char_value) % _size; //calculate second hash value - second_hash_value = 1 + (Convert.ToInt32(char_value) % (_size - 1)); + second_hash_value = 1 + Convert.ToInt32(char_value) % (_size - 1); } else { //calculates first hash values hash_value = Convert.ToInt32(key) % _size; //calculate second hash value - second_hash_value = 1 + (Convert.ToInt32(key) % (_size - 1)); + second_hash_value = 1 + Convert.ToInt32(key) % (_size - 1); } //slot index based on first hash value, second hash value as an offset based on a counter, will also guarentee that the slot will be within the range 0 to size - slot = (hash_value + (i * second_hash_value)) % _size; + slot = (hash_value + i * second_hash_value) % _size; return slot; } diff --git a/DataStructures/Dictionaries/OpenScatterHashTable.cs b/DataStructures/Dictionaries/OpenScatterHashTable.cs index efc11f6d..3e2d698d 100644 --- a/DataStructures/Dictionaries/OpenScatterHashTable.cs +++ b/DataStructures/Dictionaries/OpenScatterHashTable.cs @@ -113,11 +113,11 @@ private int _getContractPrime(int oldSize) private void _contractCapacity() { // Only contract the array if the number of elements is less than 1/3 of the total array size. - int oneThird = (_hashTableStore.Length / 3); + int oneThird = _hashTableStore.Length / 3; if (_size <= oneThird) { - int newCapacity = (_hashTableStore.Length == 0 ? _defaultCapacity : _getContractPrime(_hashTableStore.Length)); + int newCapacity = _hashTableStore.Length == 0 ? _defaultCapacity : _getContractPrime(_hashTableStore.Length); // Try to expand the size HashTableEntry[] newKeysMap = new HashTableEntry[newCapacity]; @@ -138,7 +138,7 @@ private void _expandCapacity(int minCapacity) { if (_hashTableStore.Length < minCapacity) { - int newCapacity = (_hashTableStore.Length == 0 ? _defaultCapacity : _getExpandPrime(_hashTableStore.Length * 2)); + int newCapacity = _hashTableStore.Length == 0 ? _defaultCapacity : _getExpandPrime(_hashTableStore.Length * 2); if (newCapacity >= MAX_PRIME_ARRAY_LENGTH) newCapacity = MAX_PRIME_ARRAY_LENGTH; @@ -171,7 +171,7 @@ private void _ensureCapacity(CapacityManagementMode mode, int newSize = -1) { // If the size of the internal collection is less than or equal to third of // ... the total capacity then contract the internal collection - int oneThird = (_hashTableStore.Length / 3); + int oneThird = _hashTableStore.Length / 3; if (mode == CapacityManagementMode.Contract && _size <= oneThird) { diff --git a/DataStructures/Graphs/DirectedDenseGraph.cs b/DataStructures/Graphs/DirectedDenseGraph.cs index 1b509efd..5dd3bc93 100644 --- a/DataStructures/Graphs/DirectedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedDenseGraph.cs @@ -53,7 +53,7 @@ public DirectedDenseGraph(uint capacity = 10) /// protected virtual bool _doesEdgeExist(int source, int destination) { - return (_adjacencyMatrix[source, destination] == true); + return _adjacencyMatrix[source, destination] == true; } /// @@ -130,10 +130,10 @@ public virtual IEnumerable> IncomingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(adjacent, source)) { - yield return (new UnweightedEdge( + yield return new UnweightedEdge( (T)_vertices[adjacent], // from vertex // to - )); + ); } }//end-for } @@ -152,10 +152,10 @@ public virtual IEnumerable> OutgoingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - yield return (new UnweightedEdge( + yield return new UnweightedEdge( vertex, // from (T)_vertices[adjacent] // to - )); + ); } }//end-for } @@ -308,7 +308,7 @@ public virtual bool HasEdge(T source, T destination) int dstIndex = _vertices.IndexOf(destination); // Check the existence of vertices and the directed edge - return (srcIndex != -1 && dstIndex != -1 && _doesEdgeExist(srcIndex, dstIndex)); + return srcIndex != -1 && dstIndex != -1 && _doesEdgeExist(srcIndex, dstIndex); } /// diff --git a/DataStructures/Graphs/DirectedSparseGraph.cs b/DataStructures/Graphs/DirectedSparseGraph.cs index 9b821208..257020c3 100644 --- a/DataStructures/Graphs/DirectedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedSparseGraph.cs @@ -43,7 +43,7 @@ public DirectedSparseGraph(uint initialCapacity) /// protected virtual bool _doesEdgeExist(T vertex1, T vertex2) { - return (_adjacencyList[vertex1].Contains(vertex2)); + return _adjacencyList[vertex1].Contains(vertex2); } @@ -102,10 +102,10 @@ public virtual IEnumerable> Edges { foreach (var vertex in _adjacencyList) foreach (var adjacent in vertex.Value) - yield return (new UnweightedEdge( + yield return new UnweightedEdge( vertex.Key, // from adjacent // to - )); + ); } } @@ -120,10 +120,10 @@ public virtual IEnumerable> IncomingEdges(T vertex) foreach(var adjacent in _adjacencyList.Keys) { if (_adjacencyList[adjacent].Contains(vertex)) - yield return (new UnweightedEdge( + yield return new UnweightedEdge( adjacent, // from vertex // to - )); + ); }//end-foreach } @@ -136,10 +136,10 @@ public virtual IEnumerable> OutgoingEdges(T vertex) throw new KeyNotFoundException("Vertex doesn't belong to graph."); foreach(var adjacent in _adjacencyList[vertex]) - yield return (new UnweightedEdge( + yield return new UnweightedEdge( vertex, // from adjacent // to - )); + ); } @@ -246,7 +246,7 @@ public virtual bool RemoveVertex(T vertex) /// public virtual bool HasEdge(T source, T destination) { - return (_adjacencyList.ContainsKey(source) && _adjacencyList.ContainsKey(destination) && _doesEdgeExist(source, destination)); + return _adjacencyList.ContainsKey(source) && _adjacencyList.ContainsKey(destination) && _doesEdgeExist(source, destination); } /// diff --git a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs index 3ede25f0..6b187580 100644 --- a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs @@ -57,7 +57,7 @@ public DirectedWeightedDenseGraph(uint capacity = 10) /// protected override bool _doesEdgeExist(int source, int destination) { - return (_adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT); + return _adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT; } /// @@ -101,11 +101,11 @@ public virtual IEnumerable> IncomingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(adjacent, source)) { - yield return (new WeightedEdge( + yield return new WeightedEdge( (T)_vertices[adjacent], // from vertex, // to _getEdgeWeight(source, adjacent) // weight - )); + ); } }//end-for } @@ -124,11 +124,11 @@ public virtual IEnumerable> OutgoingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - yield return (new WeightedEdge( + yield return new WeightedEdge( vertex, // from (T)_vertices[adjacent], // to _getEdgeWeight(source, adjacent) // weight - )); + ); } }//end-for } @@ -280,7 +280,7 @@ public virtual WeightedEdge GetEdge(T source, T destination) if (!_doesEdgeExist(srcIndex, dstIndex)) throw new Exception("Edge doesn't exist."); - return (new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex))); + return new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex)); } /// diff --git a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs index 8d34393f..f7c3840d 100644 --- a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs @@ -337,7 +337,7 @@ public virtual bool RemoveVertex(T vertex) /// public virtual bool HasEdge(T source, T destination) { - return (_adjacencyList.ContainsKey(source) && _adjacencyList.ContainsKey(destination) && _doesEdgeExist(source, destination)); + return _adjacencyList.ContainsKey(source) && _adjacencyList.ContainsKey(destination) && _doesEdgeExist(source, destination); } /// diff --git a/DataStructures/Graphs/UndirectedDenseGraph.cs b/DataStructures/Graphs/UndirectedDenseGraph.cs index 4b6a773d..1fa19778 100644 --- a/DataStructures/Graphs/UndirectedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedDenseGraph.cs @@ -50,7 +50,7 @@ public UndirectedDenseGraph(uint capacity = 10) /// protected virtual bool _doesEdgeExist(int index1, int index2) { - return (_adjacencyMatrix[index1, index2] || _adjacencyMatrix[index2, index1]); + return _adjacencyMatrix[index1, index2] || _adjacencyMatrix[index2, index1]; } /// @@ -157,10 +157,10 @@ public IEnumerable> IncomingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - yield return (new UnweightedEdge( + yield return new UnweightedEdge( (T)_vertices[adjacent], // from vertex // to - )); + ); } }//end-for } @@ -179,10 +179,10 @@ public IEnumerable> OutgoingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - yield return (new UnweightedEdge( + yield return new UnweightedEdge( vertex, // from (T)_vertices[adjacent] // to - )); + ); } }//end-for } @@ -323,7 +323,7 @@ public virtual bool HasEdge(T firstVertex, T secondVertex) int indexOfSecond = _vertices.IndexOf(secondVertex); // Check the existence of vertices and the directed edge - return (indexOfFirst != -1 && indexOfSecond != -1 && _doesEdgeExist(indexOfFirst, indexOfSecond) == true); + return indexOfFirst != -1 && indexOfSecond != -1 && _doesEdgeExist(indexOfFirst, indexOfSecond) == true; } /// diff --git a/DataStructures/Graphs/UndirectedSparseGraph.cs b/DataStructures/Graphs/UndirectedSparseGraph.cs index 5bd7d594..8ae3a999 100644 --- a/DataStructures/Graphs/UndirectedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedSparseGraph.cs @@ -41,7 +41,7 @@ public UndirectedSparseGraph(uint initialCapacity) /// protected virtual bool _doesEdgeExist(T vertex1, T vertex2) { - return (_adjacencyList[vertex1].Contains(vertex2) || _adjacencyList[vertex2].Contains(vertex1)); + return _adjacencyList[vertex1].Contains(vertex2) || _adjacencyList[vertex2].Contains(vertex1); } @@ -114,7 +114,7 @@ public virtual IEnumerable> Edges continue; seen.Add(outgoingEdge); - yield return (new UnweightedEdge(outgoingEdge.Key, outgoingEdge.Value)); + yield return new UnweightedEdge(outgoingEdge.Key, outgoingEdge.Value); } }//end-foreach } @@ -129,7 +129,7 @@ public virtual IEnumerable> IncomingEdges(T vertex) throw new KeyNotFoundException("Vertex doesn't belong to graph."); foreach(var adjacent in _adjacencyList[vertex]) - yield return (new UnweightedEdge(adjacent, vertex)); + yield return new UnweightedEdge(adjacent, vertex); } /// @@ -141,7 +141,7 @@ public virtual IEnumerable> OutgoingEdges(T vertex) throw new KeyNotFoundException("Vertex doesn't belong to graph."); foreach(var adjacent in _adjacencyList[vertex]) - yield return (new UnweightedEdge(vertex, adjacent)); + yield return new UnweightedEdge(vertex, adjacent); } @@ -246,7 +246,7 @@ public virtual bool HasEdge(T firstVertex, T secondVertex) if (!_adjacencyList.ContainsKey(firstVertex) || !_adjacencyList.ContainsKey(secondVertex)) return false; - return (_adjacencyList[firstVertex].Contains(secondVertex) || _adjacencyList[secondVertex].Contains(firstVertex)); + return _adjacencyList[firstVertex].Contains(secondVertex) || _adjacencyList[secondVertex].Contains(firstVertex); } /// diff --git a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs index f2941a35..61de87af 100644 --- a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs @@ -51,7 +51,7 @@ public UndirectedWeightedDenseGraph(uint capacity = 10) /// protected override bool _doesEdgeExist(int source, int destination) { - return (_adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT) || (_adjacencyMatrix[destination, source] != EMPTY_EDGE_SLOT); + return _adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT || _adjacencyMatrix[destination, source] != EMPTY_EDGE_SLOT; } /// @@ -59,7 +59,7 @@ protected override bool _doesEdgeExist(int source, int destination) /// private long _getEdgeWeight(int source, int destination) { - return (_adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT ? _adjacencyMatrix[source, destination] : _adjacencyMatrix[destination, source]); + return _adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT ? _adjacencyMatrix[source, destination] : _adjacencyMatrix[destination, source]; } /// @@ -96,7 +96,7 @@ public virtual IEnumerable> Edges continue; seen.Add(outgoingEdge); - yield return (new WeightedEdge(outgoingEdge.Key, outgoingEdge.Value, weight)); + yield return new WeightedEdge(outgoingEdge.Key, outgoingEdge.Value, weight); } } }//end-foreach @@ -116,11 +116,11 @@ public virtual IEnumerable> IncomingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - yield return (new WeightedEdge( + yield return new WeightedEdge( (T)_vertices[adjacent], // from vertex, // to _getEdgeWeight(source, adjacent) // weight - )); + ); } } } @@ -138,11 +138,11 @@ public virtual IEnumerable> OutgoingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - yield return (new WeightedEdge( + yield return new WeightedEdge( vertex, // from (T)_vertices[adjacent], // to _getEdgeWeight(source, adjacent) // weight - )); + ); } } } @@ -269,7 +269,7 @@ public virtual WeightedEdge GetEdge(T source, T destination) if (!_doesEdgeExist(srcIndex, dstIndex)) return null; - return (new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex))); + return new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex)); } /// diff --git a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs index f6b9f872..d728593a 100644 --- a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs @@ -160,7 +160,7 @@ public virtual IEnumerable> IncomingEdges(T vertex) throw new KeyNotFoundException("Vertex doesn't belong to graph."); foreach(var edge in _adjacencyList[vertex]) - yield return (new WeightedEdge(edge.Destination, edge.Source, edge.Weight)); + yield return new WeightedEdge(edge.Destination, edge.Source, edge.Weight); } /// @@ -368,7 +368,7 @@ public virtual bool RemoveVertex(T vertex) /// public virtual bool HasEdge(T source, T destination) { - return (_adjacencyList.ContainsKey(source) && _adjacencyList.ContainsKey(destination) && _doesEdgeExist(source, destination)); + return _adjacencyList.ContainsKey(source) && _adjacencyList.ContainsKey(destination) && _doesEdgeExist(source, destination); } /// diff --git a/DataStructures/Hashing/PrimeHashingFamily.cs b/DataStructures/Hashing/PrimeHashingFamily.cs index 62bd758f..483776be 100644 --- a/DataStructures/Hashing/PrimeHashingFamily.cs +++ b/DataStructures/Hashing/PrimeHashingFamily.cs @@ -71,7 +71,7 @@ public int Hash(int preHashedKey, int whichHashFunction) int multiplier = _multipliersVector[whichHashFunction - 1]; var characters = preHashedKey.ToString().ToCharArray(); - return (multiplier * preHashValue); + return multiplier * preHashValue; } /// diff --git a/DataStructures/Hashing/UniversalHashingFamily.cs b/DataStructures/Hashing/UniversalHashingFamily.cs index 860e8eda..07876589 100644 --- a/DataStructures/Hashing/UniversalHashingFamily.cs +++ b/DataStructures/Hashing/UniversalHashingFamily.cs @@ -95,7 +95,7 @@ public int UniversalHash(int preHashedKey, int whichHashFunction) int a = _firstMultipliersVector[whichHashFunction - 1]; int b = _secondMultipliersVector[whichHashFunction - 1]; - return ((a * preHashedKey) + b) % BIG_PRIME; + return (a * preHashedKey + b) % BIG_PRIME; } /// diff --git a/DataStructures/Heaps/BinaryMaxHeap.cs b/DataStructures/Heaps/BinaryMaxHeap.cs index e1793fd3..a98798a7 100644 --- a/DataStructures/Heaps/BinaryMaxHeap.cs +++ b/DataStructures/Heaps/BinaryMaxHeap.cs @@ -36,7 +36,7 @@ public BinaryMaxHeap(int capacity, Comparer comparer) private void _buildMaxHeap() { int lastIndex = _collection.Count - 1; - int lastNodeWithChildren = (lastIndex / 2); + int lastNodeWithChildren = lastIndex / 2; for (int node = lastNodeWithChildren; node >= 0; node--) { @@ -64,7 +64,7 @@ private void _siftUp(int nodeIndex) private void _maxHeapify(int nodeIndex, int lastIndex) { // assume that the subtrees left(node) and right(node) are max-heaps - int left = (nodeIndex * 2) + 1; + int left = nodeIndex * 2 + 1; int right = left + 1; int largest = nodeIndex; @@ -93,7 +93,7 @@ private void _maxHeapify(int nodeIndex, int lastIndex) /// /// Checks whether this heap is empty /// - public bool IsEmpty => (_collection.Count == 0); + public bool IsEmpty => _collection.Count == 0; /// /// Gets or sets the at the specified index. diff --git a/DataStructures/Heaps/BinaryMinHeap.cs b/DataStructures/Heaps/BinaryMinHeap.cs index 99f31209..0679b401 100644 --- a/DataStructures/Heaps/BinaryMinHeap.cs +++ b/DataStructures/Heaps/BinaryMinHeap.cs @@ -37,7 +37,7 @@ public BinaryMinHeap(int capacity, Comparer comparer) private void _buildMinHeap() { int lastIndex = _collection.Count - 1; - int lastNodeWithChildren = (lastIndex / 2); + int lastNodeWithChildren = lastIndex / 2; for (int node = lastNodeWithChildren; node >= 0; node--) { @@ -68,7 +68,7 @@ private void _siftUp(int nodeIndex) private void _minHeapify(int nodeIndex, int lastIndex) { // assume that the subtrees left(node) and right(node) are max-heaps - int left = (nodeIndex * 2) + 1; + int left = nodeIndex * 2 + 1; int right = left + 1; int smallest = nodeIndex; @@ -97,7 +97,7 @@ private void _minHeapify(int nodeIndex, int lastIndex) /// /// Checks whether this heap is empty /// - public bool IsEmpty => (_collection.Count == 0); + public bool IsEmpty => _collection.Count == 0; /// /// Gets or sets the at the specified index. diff --git a/DataStructures/Heaps/BinomialMinHeap.cs b/DataStructures/Heaps/BinomialMinHeap.cs index 057b5bbe..d3ad7b4e 100644 --- a/DataStructures/Heaps/BinomialMinHeap.cs +++ b/DataStructures/Heaps/BinomialMinHeap.cs @@ -61,7 +61,7 @@ public BinomialMinHeap(int capacity) if (capacity <= 0) throw new ArgumentOutOfRangeException(); - capacity = (capacity < _defaultCapacity ? _defaultCapacity : capacity); + capacity = capacity < _defaultCapacity ? _defaultCapacity : capacity; _size = 0; _forest = new ArrayList>(capacity); @@ -90,7 +90,7 @@ private void _removeAtIndex(int minIndex) deletedForest._forest.Resize(minIndex + 1); deletedForest._size = (1 << minIndex) - 1; - for (int i = (minIndex - 1); i >= 0; --i) + for (int i = minIndex - 1; i >= 0; --i) { deletedForest._forest[i] = deletedTreeRoot; deletedTreeRoot = deletedTreeRoot.Sibling; @@ -120,7 +120,7 @@ private int _findMinIndex() // Loop over the trees in forest, and return the index of the slot that has the tree with the min-valued root for (minIndex = i; i < _forest.Count; ++i) - if (_forest[i] != null && (_forest[i].Value.IsLessThan(_forest[minIndex].Value))) + if (_forest[i] != null && _forest[i].Value.IsLessThan(_forest[minIndex].Value)) minIndex = i; return minIndex; @@ -168,7 +168,7 @@ private BinomialNode _cloneTree(BinomialNode treeRoot) /// Checks if heap is empty /// /// - public bool IsEmpty => (_size == 0); + public bool IsEmpty => _size == 0; /// /// Initializes this heap with a collection of elements. @@ -271,12 +271,12 @@ public void Merge(BinomialMinHeap otherHeap) for (int i = 0, j = 1; j <= _size; i++, j *= 2) { - BinomialNode treeRoot1 = (_forest.IsEmpty == true ? null : _forest[i]); - BinomialNode treeRoot2 = (i < otherHeap._forest.Count ? otherHeap._forest[i] : null); + BinomialNode treeRoot1 = _forest.IsEmpty == true ? null : _forest[i]; + BinomialNode treeRoot2 = i < otherHeap._forest.Count ? otherHeap._forest[i] : null; - int whichCase = (treeRoot1 == null ? 0 : 1); - whichCase += (treeRoot2 == null ? 0 : 2); - whichCase += (carryNode == null ? 0 : 4); + int whichCase = treeRoot1 == null ? 0 : 1; + whichCase += treeRoot2 == null ? 0 : 2; + whichCase += carryNode == null ? 0 : 4; switch (whichCase) { diff --git a/DataStructures/Lists/ArrayList.cs b/DataStructures/Lists/ArrayList.cs index 17897e83..9d174a40 100644 --- a/DataStructures/Lists/ArrayList.cs +++ b/DataStructures/Lists/ArrayList.cs @@ -75,11 +75,11 @@ private void _ensureCapacity(int minCapacity) // ... then maximize the inner collection. if (_collection.Length < minCapacity && IsMaximumCapacityReached == false) { - int newCapacity = (_collection.Length == 0 ? _defaultCapacity : _collection.Length * 2); + int newCapacity = _collection.Length == 0 ? _defaultCapacity : _collection.Length * 2; // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. // Note that this check works even when _items.Length overflowed thanks to the (uint) cast - int maxCapacity = (DefaultMaxCapacityIsX64 == true ? MAXIMUM_ARRAY_LENGTH_x64 : MAXIMUM_ARRAY_LENGTH_x86); + int maxCapacity = DefaultMaxCapacityIsX64 == true ? MAXIMUM_ARRAY_LENGTH_x64 : MAXIMUM_ARRAY_LENGTH_x86; if (newCapacity < minCapacity) newCapacity = minCapacity; @@ -138,7 +138,7 @@ private void _resizeCapacity(int newCapacity) /// Determines whether this list is empty. /// /// true if list is empty; otherwise, false. - public bool IsEmpty => (Count == 0); + public bool IsEmpty => Count == 0; /// @@ -232,7 +232,7 @@ public void AddRange(IEnumerable elements) throw new ArgumentNullException(); // make sure the size won't overflow by adding the range - if (((uint)_size + elements.Count()) > MAXIMUM_ARRAY_LENGTH_x64) + if ((uint)_size + elements.Count() > MAXIMUM_ARRAY_LENGTH_x64) throw new OverflowException(); // grow the internal collection once to avoid doing multiple redundant grows @@ -254,7 +254,7 @@ public void AddRepeatedly(T value, int count) if (count < 0) throw new ArgumentOutOfRangeException(); - if (((uint)_size + count) > MAXIMUM_ARRAY_LENGTH_x64) + if ((uint)_size + count > MAXIMUM_ARRAY_LENGTH_x64) throw new OverflowException(); // grow the internal collection once to avoid doing multiple redundant grows @@ -292,7 +292,7 @@ public void InsertAt(T dataItem, int index) // The cell at "index" will become available. if (index < _size) { - Array.Copy(_collection, index, _collection, index + 1, (_size - index)); + Array.Copy(_collection, index, _collection, index + 1, _size - index); } // Write the dataItem to the available cell. @@ -340,7 +340,7 @@ public void RemoveAt(int index) // This operation is O(N), where N = size - index. if (index < _size) { - Array.Copy(_collection, index + 1, _collection, index, (_size - index)); + Array.Copy(_collection, index + 1, _collection, index, _size - index); } // Reset the writable cell to the default value of type T. @@ -417,7 +417,7 @@ public void Reverse(int startIndex, int count) } // Handle the bounds of count and startIndex with respect to _size. - if (count < 0 || startIndex > (_size - count)) + if (count < 0 || startIndex > _size - count) { throw new ArgumentOutOfRangeException(); } @@ -521,7 +521,7 @@ public bool Exists(Predicate searchMatch) { // Use the FindIndex to look through the collection // If the returned index != -1 then it does exist, otherwise it doesn't. - return (FindIndex(searchMatch) != -1); + return FindIndex(searchMatch) != -1; } @@ -544,7 +544,7 @@ public int FindIndex(Predicate searchMatch) /// Match predicate. public int FindIndex(int startIndex, Predicate searchMatch) { - return FindIndex(startIndex, (_size - startIndex), searchMatch); + return FindIndex(startIndex, _size - startIndex, searchMatch); } @@ -564,7 +564,7 @@ public int FindIndex(int startIndex, int count, Predicate searchMatch) } // CHeck the bounds of count and startIndex with respect to _size - if (count < 0 || startIndex > (_size - count)) + if (count < 0 || startIndex > _size - count) { throw new ArgumentOutOfRangeException(); } @@ -626,7 +626,7 @@ public int IndexOf(T dataItem, int startIndex, int count) } // Check the bounds of count and starting index with respect to _size. - if (count < 0 || startIndex > (_size - count)) + if (count < 0 || startIndex > _size - count) { throw new ArgumentOutOfRangeException(); } @@ -710,7 +710,7 @@ public ArrayList GetRange(int startIndex, int count) } // Handle the bound errors of count and startIndex with respect to _size - if (count < 0 || startIndex > (_size - count)) + if (count < 0 || startIndex > _size - count) { throw new ArgumentOutOfRangeException(); } @@ -774,7 +774,7 @@ public string ToHumanReadable(bool addHeader = false) int i = 0; string listAsString = string.Empty; - string preLineIndent = (addHeader == false ? "" : "\t"); + string preLineIndent = addHeader == false ? "" : "\t"; for (i = 0; i < Count; ++i) { diff --git a/DataStructures/Lists/CircularBuffer.cs b/DataStructures/Lists/CircularBuffer.cs index a38c74d1..a35ecf5d 100644 --- a/DataStructures/Lists/CircularBuffer.cs +++ b/DataStructures/Lists/CircularBuffer.cs @@ -25,7 +25,7 @@ public class CircularBuffer : IEnumerable, ICollection where T : ICompa /// /// Checks if the buffer is filled up /// - public bool IsFilledUp => ((_end + 1) % _circularBuffer.Length == _start) && !_circularBuffer[_start].Equals(_circularBuffer[_end]); + public bool IsFilledUp => (_end + 1) % _circularBuffer.Length == _start && !_circularBuffer[_start].Equals(_circularBuffer[_end]); /// /// Controls whether data should be overridden when it is continously inserted without reading diff --git a/DataStructures/Lists/DLinkedList.cs b/DataStructures/Lists/DLinkedList.cs index 08d36041..aa102671 100644 --- a/DataStructures/Lists/DLinkedList.cs +++ b/DataStructures/Lists/DLinkedList.cs @@ -71,7 +71,7 @@ protected virtual T _getElementAt(int index) return First; } - if (index == (Count - 1)) + if (index == Count - 1) { return Last; } @@ -81,10 +81,10 @@ protected virtual T _getElementAt(int index) // Decide from which reference to traverse the list, and then move the currentNode reference to the index // If index > half then traverse it from the end (_lastNode reference) // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > (Count / 2)) + if (index > Count / 2) { currentNode = _lastNode; - for (int i = (Count - 1); i > index; --i) + for (int i = Count - 1; i > index; --i) { currentNode = currentNode.Previous; } @@ -115,7 +115,7 @@ protected virtual void _setElementAt(int index, T value) { _firstNode.Data = value; } - else if (index == (Count - 1)) + else if (index == Count - 1) { _lastNode.Data = value; } @@ -126,10 +126,10 @@ protected virtual void _setElementAt(int index, T value) // Decide from which reference to traverse the list, and then move the currentNode reference to the index // If index > half then traverse it from the end (_lastNode reference) // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > (Count / 2)) + if (index > Count / 2) { currentNode = _lastNode; - for (int i = (Count - 1); i > index; --i) + for (int i = Count - 1; i > index; --i) { currentNode = currentNode.Previous; } @@ -164,7 +164,7 @@ public DLinkedList() /// true if this list is empty; otherwise, false. public virtual bool IsEmpty() { - return (Count == 0); + return Count == 0; } /// @@ -243,7 +243,7 @@ public virtual int IndexOf(T dataItem) i++; }//end-while - return (found == true ? i : -1); + return found == true ? i : -1; } /// @@ -671,10 +671,10 @@ public virtual DLinkedList GetRange(int index, int countOfElements) // Decide from which reference to traverse the list, and then move the currentNode reference to the index // If index > half then traverse it from the end (_lastNode reference) // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > (Count / 2)) + if (index > Count / 2) { currentNode = _lastNode; - for (int i = (Count - 1); i > index; --i) + for (int i = Count - 1; i > index; --i) { currentNode = currentNode.Previous; } diff --git a/DataStructures/Lists/DLinkedList_KeyValue.cs b/DataStructures/Lists/DLinkedList_KeyValue.cs index e4424995..849dd023 100644 --- a/DataStructures/Lists/DLinkedList_KeyValue.cs +++ b/DataStructures/Lists/DLinkedList_KeyValue.cs @@ -69,22 +69,22 @@ protected virtual DLinkedListNode _getNodeByIndex(int index) return _firstNode; } - if (index == (Count - 1)) + if (index == Count - 1) { return _lastNode; } - if (index > 0 && index < (Count - 1)) + if (index > 0 && index < Count - 1) { DLinkedListNode currentNode = null; // Decide from which reference to traverse the list, and then move the currentNode reference to the index // If index > half then traverse it from the end (_lastNode reference) // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > (Count / 2)) + if (index > Count / 2) { currentNode = _lastNode; - for (int i = (Count - 1); i > index; --i) + for (int i = Count - 1; i > index; --i) { currentNode = currentNode.Previous; } @@ -146,21 +146,21 @@ protected virtual void _setValueByIndex(int index, TValue value) { _firstNode.Value = value; } - else if (index == (Count - 1)) + else if (index == Count - 1) { _lastNode.Value = value; } - else if (index > 0 && index < (Count - 1)) + else if (index > 0 && index < Count - 1) { DLinkedListNode currentNode = null; // Decide from which reference to traverse the list, and then move the currentNode reference to the index // If index > half then traverse it from the end (_lastNode reference) // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > (Count / 2)) + if (index > Count / 2) { currentNode = _lastNode; - for (int i = (Count - 1); i > index; --i) + for (int i = Count - 1; i > index; --i) { currentNode = currentNode.Previous; } @@ -225,22 +225,22 @@ protected virtual void _setNodeByIndex(int index, TKey key, TValue value) _firstNode.Key = key; _firstNode.Value = value; } - else if (index == (Count - 1)) + else if (index == Count - 1) { _lastNode.Key = key; _lastNode.Value = value; } - else if (index > 0 && index < (Count - 1)) + else if (index > 0 && index < Count - 1) { DLinkedListNode currentNode = null; // Decide from which reference to traverse the list, and then move the currentNode reference to the index // If index > half then traverse it from the end (_lastNode reference) // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > (Count / 2)) + if (index > Count / 2) { currentNode = _lastNode; - for (int i = (Count - 1); i > index; --i) + for (int i = Count - 1; i > index; --i) { currentNode = currentNode.Previous; } @@ -276,7 +276,7 @@ public DLinkedList() /// true if this list is empty; otherwise, false. public virtual bool IsEmpty() { - return (Count == 0); + return Count == 0; } /// @@ -442,10 +442,10 @@ public virtual void InsertAt(int index, TKey key, TValue value) // Decide from which reference to traverse the list, and then move the currentNode reference to the index // If index > half then traverse it from the end (_lastNode reference) // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > (Count / 2)) + if (index > Count / 2) { currentNode = _lastNode; - for (int i = (Count - 1); i > index - 1; --i) + for (int i = Count - 1; i > index - 1; --i) { currentNode = currentNode.Previous; } @@ -731,10 +731,10 @@ public virtual List> GetRange(int index, int countOfE // Decide from which reference to traverse the list, and then move the currentNode reference to the index // If index > half then traverse it from the end (_lastNode reference) // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > (Count / 2)) + if (index > Count / 2) { currentNode = _lastNode; - for (int i = (Count - 1); i > index; --i) + for (int i = Count - 1; i > index; --i) { currentNode = currentNode.Previous; } diff --git a/DataStructures/Lists/Queue.cs b/DataStructures/Lists/Queue.cs index 8dccb827..77a10515 100644 --- a/DataStructures/Lists/Queue.cs +++ b/DataStructures/Lists/Queue.cs @@ -56,11 +56,11 @@ private void _resize(int newSize) { if (newSize > _size && !IsMaximumCapacityReached) { - int capacity = (_collection.Length == 0 ? _defaultCapacity : _collection.Length * 2); + int capacity = _collection.Length == 0 ? _defaultCapacity : _collection.Length * 2; // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. // Note that this check works even when _items.Length overflowed thanks to the (uint) cast - int maxCapacity = (DefaultMaxCapacityIsX64 == true ? MAXIMUM_ARRAY_LENGTH_x64 : MAXIMUM_ARRAY_LENGTH_x86); + int maxCapacity = DefaultMaxCapacityIsX64 == true ? MAXIMUM_ARRAY_LENGTH_x64 : MAXIMUM_ARRAY_LENGTH_x86; // Handle the new proper size if (capacity < newSize) @@ -180,7 +180,7 @@ public T Dequeue() var tail = _collection[_tailPointer]; // Shrink - _resize((_collection.Length / 3) * 2); + _resize(_collection.Length / 3 * 2); // Update head and tail pointers _headPointer = Array.IndexOf(_collection, head); diff --git a/DataStructures/Lists/SLinkedList.cs b/DataStructures/Lists/SLinkedList.cs index 261529a5..66d2595b 100644 --- a/DataStructures/Lists/SLinkedList.cs +++ b/DataStructures/Lists/SLinkedList.cs @@ -67,13 +67,13 @@ public SLinkedList() /// true, if the list is empty, false otherwise. public bool IsEmpty() { - return (Count == 0); + return Count == 0; } /// /// Getter function that returns the first element /// - public T First => (_firstNode == null ? default : _firstNode.Data); + public T First => _firstNode == null ? default : _firstNode.Data; /// /// Getter function that returns the last element @@ -261,12 +261,12 @@ public T GetAt(int index) return First; } - if (index == (Count - 1)) + if (index == Count - 1) { return Last; } - if (index > 0 && index < (Count - 1)) + if (index > 0 && index < Count - 1) { var currentNode = _firstNode; for (int i = 0; i < index; ++i) @@ -453,7 +453,7 @@ public bool MoveNext() { _current = _current.Next; - return (_current != null); + return _current != null; } public void Reset() diff --git a/DataStructures/Trees/AVLTree.cs b/DataStructures/Trees/AVLTree.cs index a737f4e3..79b40015 100644 --- a/DataStructures/Trees/AVLTree.cs +++ b/DataStructures/Trees/AVLTree.cs @@ -74,7 +74,7 @@ private int _getBalanceFactor(AVLTreeNode node) if (node == null) return -1; - return (_getNodeHeight(node.RightChild) - _getNodeHeight(node.LeftChild)); + return _getNodeHeight(node.RightChild) - _getNodeHeight(node.LeftChild); } /// @@ -96,7 +96,7 @@ private void _rotateLeftAt(AVLTreeNode currentNode) bool isLeftChild = currentNode.IsLeftChild; // Check if currentNode is the Root - bool isRootNode = (currentNode == Root); + bool isRootNode = currentNode == Root; // Perform the rotation currentNode.RightChild = pivotNode.LeftChild; @@ -143,7 +143,7 @@ private void _rotateRightAt(AVLTreeNode currentNode) bool isLeftChild = currentNode.IsLeftChild; // Check if currentNode is the Root - bool isRootNode = (currentNode == Root); + bool isRootNode = currentNode == Root; // Perform the rotation currentNode.LeftChild = pivotNode.RightChild; diff --git a/DataStructures/Trees/AugmentedBinarySearchTree.cs b/DataStructures/Trees/AugmentedBinarySearchTree.cs index c36451ba..feb0dbc7 100644 --- a/DataStructures/Trees/AugmentedBinarySearchTree.cs +++ b/DataStructures/Trees/AugmentedBinarySearchTree.cs @@ -138,7 +138,7 @@ protected bool _remove(BSTRankedNode node) { var successor = _findNextLarger(node); node.Value = successor.Value; - return (true && _remove(successor)); + return true && _remove(successor); } if (node.HasLeftChild) // if the node has only a LEFT child @@ -177,18 +177,18 @@ protected int _getTreeHeight(BSTRankedNode node) if (node.ChildrenCount == 2) // it has both a right child and a left child { if (node.LeftChild.SubtreeSize > node.RightChild.SubtreeSize) - return (1 + _getTreeHeight(node.LeftChild)); - return (1 + _getTreeHeight(node.RightChild)); + return 1 + _getTreeHeight(node.LeftChild); + return 1 + _getTreeHeight(node.RightChild); } if (node.HasLeftChild) { - return (1 + _getTreeHeight(node.LeftChild)); + return 1 + _getTreeHeight(node.LeftChild); } if (node.HasRightChild) { - return (1 + _getTreeHeight(node.RightChild)); + return 1 + _getTreeHeight(node.RightChild); } // return-functions-fix @@ -302,7 +302,7 @@ public virtual int Rank(T item) if (node == null) throw new Exception("Item was not found."); - return (_subtreeSize(node.LeftChild) + 1); + return _subtreeSize(node.LeftChild) + 1; } } diff --git a/DataStructures/Trees/BTree.cs b/DataStructures/Trees/BTree.cs index 0a4bc502..55c6c568 100644 --- a/DataStructures/Trees/BTree.cs +++ b/DataStructures/Trees/BTree.cs @@ -112,7 +112,7 @@ public BTreeNode(int degree) public List> Children { set; get; } - public bool IsLeaf => (Children.Count == 0); + public bool IsLeaf => Children.Count == 0; /// /// A utility function that returns the index of the first key @@ -140,7 +140,7 @@ public void Remove(T value) if (IsLeaf) return; - var didMergeLast = (index == Children.Count); + var didMergeLast = index == Children.Count; if (Children[index].Keys.Count < _degree) Fill(index); diff --git a/DataStructures/Trees/BinarySearchTree.cs b/DataStructures/Trees/BinarySearchTree.cs index a4e0fcb2..f5a62a6a 100644 --- a/DataStructures/Trees/BinarySearchTree.cs +++ b/DataStructures/Trees/BinarySearchTree.cs @@ -102,7 +102,7 @@ protected virtual bool _remove(BSTNode node) { var successor = _findNextLarger(node); node.Value = successor.Value; - return (true && _remove(successor)); + return true && _remove(successor); } if (node.HasLeftChild) // if the node has only a LEFT child @@ -196,12 +196,12 @@ protected virtual int _getTreeHeight(BSTNode node) return 1; // Has two children if (node.ChildrenCount == 2) - return (1 + Math.Max(_getTreeHeight(node.LeftChild), _getTreeHeight(node.RightChild))); + return 1 + Math.Max(_getTreeHeight(node.LeftChild), _getTreeHeight(node.RightChild)); // Has only left if (node.HasLeftChild) - return (1 + _getTreeHeight(node.LeftChild)); + return 1 + _getTreeHeight(node.LeftChild); // Has only right - return (1 + _getTreeHeight(node.RightChild)); + return 1 + _getTreeHeight(node.RightChild); } /// @@ -362,7 +362,7 @@ protected virtual void _inOrderTraverse(BSTNode currentNode, ref List list /// Checks if tree is empty. /// /// - public virtual bool IsEmpty => (_count == 0); + public virtual bool IsEmpty => _count == 0; /// /// Returns the height of the tree. @@ -487,7 +487,7 @@ public virtual void Clear() /// public virtual bool Contains(T item) { - return (_findNode(_root, item) != null); + return _findNode(_root, item) != null; } /// @@ -673,7 +673,7 @@ public bool MoveNext() else current = null; - return (current != null); + return current != null; } } @@ -727,7 +727,7 @@ public bool MoveNext() else current = null; - return (current != null); + return current != null; } } @@ -780,7 +780,7 @@ public bool MoveNext() else current = null; - return (current != null); + return current != null; } } diff --git a/DataStructures/Trees/BinarySearchTreeMap.cs b/DataStructures/Trees/BinarySearchTreeMap.cs index 8e3d5af7..f9f4d2db 100644 --- a/DataStructures/Trees/BinarySearchTreeMap.cs +++ b/DataStructures/Trees/BinarySearchTreeMap.cs @@ -72,12 +72,12 @@ protected virtual int _getTreeHeight(BSTMapNode node) return 1; // Has two children if (node.ChildrenCount == 2) - return (1 + Math.Max(_getTreeHeight(node.LeftChild), _getTreeHeight(node.RightChild))); + return 1 + Math.Max(_getTreeHeight(node.LeftChild), _getTreeHeight(node.RightChild)); // Has only left if (node.HasLeftChild) - return (1 + _getTreeHeight(node.LeftChild)); + return 1 + _getTreeHeight(node.LeftChild); // Has only right - return (1 + _getTreeHeight(node.RightChild)); + return 1 + _getTreeHeight(node.RightChild); } /// @@ -167,7 +167,7 @@ protected virtual bool _remove(BSTMapNode node) var successor = node.RightChild; node.Key = successor.Key; node.Value = successor.Value; - return (true && _remove(successor)); + return true && _remove(successor); } if (node.HasLeftChild) // if the node has only a LEFT child @@ -332,7 +332,7 @@ protected virtual void _inOrderTraverse(BSTMapNode currentNode, re /// /// Checks if tree is empty. /// - public virtual bool IsEmpty => (_count == 0); + public virtual bool IsEmpty => _count == 0; /// /// Returns the height of the tree. @@ -512,7 +512,7 @@ public virtual void Clear() /// public virtual bool Contains(TKey key) { - return (_findNode(_root, key) != null); + return _findNode(_root, key) != null; } /// @@ -698,7 +698,7 @@ public bool MoveNext() else current = null; - return (current != null); + return current != null; } } @@ -752,7 +752,7 @@ public bool MoveNext() else current = null; - return (current != null); + return current != null; } } @@ -805,7 +805,7 @@ public bool MoveNext() else current = null; - return (current != null); + return current != null; } } diff --git a/DataStructures/Trees/BinarySearchTreeMapNode.cs b/DataStructures/Trees/BinarySearchTreeMapNode.cs index e06af3f6..147adc23 100644 --- a/DataStructures/Trees/BinarySearchTreeMapNode.cs +++ b/DataStructures/Trees/BinarySearchTreeMapNode.cs @@ -32,32 +32,32 @@ public BSTMapNode(TKey key, TValue value, int subTreeSize, BSTMapNode /// Checks whether this node has any children. /// - public virtual bool HasChildren => (ChildrenCount > 0); + public virtual bool HasChildren => ChildrenCount > 0; /// /// Checks whether this node has left child. /// - public virtual bool HasLeftChild => (LeftChild != null); + public virtual bool HasLeftChild => LeftChild != null; /// /// Checks whether this node has right child. /// - public virtual bool HasRightChild => (RightChild != null); + public virtual bool HasRightChild => RightChild != null; /// /// Checks whether this node is the left child of it's parent. /// - public virtual bool IsLeftChild => (Parent != null && Parent.LeftChild == this); + public virtual bool IsLeftChild => Parent != null && Parent.LeftChild == this; /// /// Checks whether this node is the left child of it's parent. /// - public virtual bool IsRightChild => (Parent != null && Parent.RightChild == this); + public virtual bool IsRightChild => Parent != null && Parent.RightChild == this; /// /// Checks whether this node is a leaf node. /// - public virtual bool IsLeafNode => (ChildrenCount == 0); + public virtual bool IsLeafNode => ChildrenCount == 0; /// /// Returns number of direct descendents: 0, 1, 2 (none, left or right, or both). diff --git a/DataStructures/Trees/BinarySearchTreeNode.cs b/DataStructures/Trees/BinarySearchTreeNode.cs index 45c3708e..04a04503 100644 --- a/DataStructures/Trees/BinarySearchTreeNode.cs +++ b/DataStructures/Trees/BinarySearchTreeNode.cs @@ -26,12 +26,12 @@ public BSTNode(T value, int subTreeSize, BSTNode parent, BSTNode left, BST /// /// Checks whether this node has any children. /// - public virtual bool HasChildren => (ChildrenCount > 0); + public virtual bool HasChildren => ChildrenCount > 0; /// /// Checks whether this node has left child. /// - public virtual bool HasLeftChild => (LeftChild != null); + public virtual bool HasLeftChild => LeftChild != null; /// /// Check if this node has only one child and whether it is the right child. @@ -41,7 +41,7 @@ public BSTNode(T value, int subTreeSize, BSTNode parent, BSTNode left, BST /// /// Checks whether this node has right child. /// - public virtual bool HasRightChild => (RightChild != null); + public virtual bool HasRightChild => RightChild != null; /// /// Check if this node has only one child and whether it is the left child. @@ -51,17 +51,17 @@ public BSTNode(T value, int subTreeSize, BSTNode parent, BSTNode left, BST /// /// Checks whether this node is the left child of it's parent. /// - public virtual bool IsLeftChild => (Parent != null && Parent.LeftChild == this); + public virtual bool IsLeftChild => Parent != null && Parent.LeftChild == this; /// /// Checks whether this node is the left child of it's parent. /// - public virtual bool IsRightChild => (Parent != null && Parent.RightChild == this); + public virtual bool IsRightChild => Parent != null && Parent.RightChild == this; /// /// Checks whether this node is a leaf node. /// - public virtual bool IsLeafNode => (ChildrenCount == 0); + public virtual bool IsLeafNode => ChildrenCount == 0; /// /// Returns number of direct descendents: 0, 1, 2 (none, left or right, or both). diff --git a/DataStructures/Trees/RedBlackTree.cs b/DataStructures/Trees/RedBlackTree.cs index 21b967eb..f415fcf9 100644 --- a/DataStructures/Trees/RedBlackTree.cs +++ b/DataStructures/Trees/RedBlackTree.cs @@ -112,12 +112,12 @@ protected virtual void _safeUpdateColor(RedBlackTreeNode node, RedBlackTre protected virtual bool _safeCheckIsBlack(RedBlackTreeNode node) { - return (node == null || (node != null && node.IsBlack)); + return node == null || (node != null && node.IsBlack); } protected virtual bool _safeCheckIsRed(RedBlackTreeNode node) { - return (node != null && node.IsRed); + return node != null && node.IsRed; } @@ -148,7 +148,7 @@ protected virtual void _rotateLeftAt(RedBlackTreeNode currentNode) bool isLeftChild = currentNode.IsLeftChild; // Check if currentNode is the Root - bool isRootNode = (currentNode == Root); + bool isRootNode = currentNode == Root; // Perform the rotation currentNode.RightChild = pivotNode.LeftChild; @@ -191,7 +191,7 @@ protected virtual void _rotateRightAt(RedBlackTreeNode currentNode) bool isLeftChild = currentNode.IsLeftChild; // Check if currentNode is the Root - bool isRootNode = (currentNode == Root); + bool isRootNode = currentNode == Root; // Perform the rotation currentNode.LeftChild = pivotNode.RightChild; diff --git a/DataStructures/Trees/RedBlackTreeMap.cs b/DataStructures/Trees/RedBlackTreeMap.cs index 8c317250..9f4b8ed6 100644 --- a/DataStructures/Trees/RedBlackTreeMap.cs +++ b/DataStructures/Trees/RedBlackTreeMap.cs @@ -100,12 +100,12 @@ protected virtual void _safeUpdateColor(RedBlackTreeMapNode node, protected virtual bool _safeCheckIsBlack(RedBlackTreeMapNode node) { - return (node == null || (node != null && node.IsBlack)); + return node == null || (node != null && node.IsBlack); } protected virtual bool _safeCheckIsRed(RedBlackTreeMapNode node) { - return (node != null && node.IsRed); + return node != null && node.IsRed; } @@ -136,7 +136,7 @@ protected virtual void _rotateLeftAt(RedBlackTreeMapNode currentNo bool isLeftChild = currentNode.IsLeftChild; // Check if currentNode is the Root - bool isRootNode = (currentNode == Root); + bool isRootNode = currentNode == Root; // Perform the rotation currentNode.RightChild = pivotNode.LeftChild; @@ -179,7 +179,7 @@ protected virtual void _rotateRightAt(RedBlackTreeMapNode currentN bool isLeftChild = currentNode.IsLeftChild; // Check if currentNode is the Root - bool isRootNode = (currentNode == Root); + bool isRootNode = currentNode == Root; // Perform the rotation currentNode.LeftChild = pivotNode.RightChild; diff --git a/DataStructures/Trees/RedBlackTreeMapNode.cs b/DataStructures/Trees/RedBlackTreeMapNode.cs index ba52033c..57f7f4ee 100644 --- a/DataStructures/Trees/RedBlackTreeMapNode.cs +++ b/DataStructures/Trees/RedBlackTreeMapNode.cs @@ -57,12 +57,12 @@ public RedBlackTreeMapNode(TKey key, TValue value, int height, RedBlackTreeMapNo /// /// Returns the sibling of this node. /// - public virtual RedBlackTreeMapNode Sibling => (Parent == null ? null : (IsLeftChild ? Parent.RightChild : Parent.LeftChild)); + public virtual RedBlackTreeMapNode Sibling => Parent == null ? null : IsLeftChild ? Parent.RightChild : Parent.LeftChild; /// /// Returns the grandparent of this node. /// - public virtual RedBlackTreeMapNode GrandParent => (Parent == null ? null : Parent.Parent); + public virtual RedBlackTreeMapNode GrandParent => Parent == null ? null : Parent.Parent; } } diff --git a/DataStructures/Trees/RedBlackTreeNode.cs b/DataStructures/Trees/RedBlackTreeNode.cs index 6d961685..2bece0a5 100644 --- a/DataStructures/Trees/RedBlackTreeNode.cs +++ b/DataStructures/Trees/RedBlackTreeNode.cs @@ -56,12 +56,12 @@ public RedBlackTreeNode(TKey value, int height, RedBlackTreeNode parent, R /// /// Returns the sibling of this node. /// - public virtual RedBlackTreeNode Sibling => (Parent == null ? null : (IsLeftChild ? Parent.RightChild : Parent.LeftChild)); + public virtual RedBlackTreeNode Sibling => Parent == null ? null : IsLeftChild ? Parent.RightChild : Parent.LeftChild; /// /// Returns the grandparent of this node. /// - public virtual RedBlackTreeNode GrandParent => (Parent == null ? null : Parent.Parent); + public virtual RedBlackTreeNode GrandParent => Parent == null ? null : Parent.Parent; } } diff --git a/DataStructures/Trees/TreeDrawer.cs b/DataStructures/Trees/TreeDrawer.cs index a83cb38d..518935ca 100644 --- a/DataStructures/Trees/TreeDrawer.cs +++ b/DataStructures/Trees/TreeDrawer.cs @@ -67,7 +67,7 @@ private static List _recursivelyDrawTree List rightLines = _recursivelyDrawTree(node.RightChild, out rightPosition, out rightWidth); // Calculate pads - int middle = Math.Max(Math.Max(2, nodeLabel.Length), (rightPosition + leftWidth - leftPosition + 1)); + int middle = Math.Max(Math.Max(2, nodeLabel.Length), rightPosition + leftWidth - leftPosition + 1); int position_out = leftPosition + middle / 2; int width_out = leftPosition + middle + rightWidth - rightPosition; @@ -77,7 +77,7 @@ private static List _recursivelyDrawTree while (rightLines.Count < leftLines.Count) rightLines.Add(new String(' ', rightWidth)); - if ((middle - nodeLabel.Length % 2 == 1) && (nodeLabel.Length < middle) && (node.Parent != null && node.IsLeftChild)) + if (middle - nodeLabel.Length % 2 == 1 && nodeLabel.Length < middle && node.Parent != null && node.IsLeftChild) nodeLabel += "."; // Format the node's label @@ -101,16 +101,16 @@ private static List _recursivelyDrawTree List listOfLines = new List() { // 0 - (new String(' ', leftPosition )) + nodeLabel + (new String(' ', (rightWidth - rightPosition))), + new String(' ', leftPosition ) + nodeLabel + new String(' ', rightWidth - rightPosition), // 1 - (new String(' ', leftPosition)) + leftBranch + (new String(' ', (middle - 2))) + rightBranch + (new String(' ', (rightWidth - rightPosition))) + new String(' ', leftPosition) + leftBranch + new String(' ', middle - 2) + rightBranch + new String(' ', rightWidth - rightPosition) }; // // Add the right lines and left lines to the final list of lines. listOfLines.AddRange(leftLines.Zip(rightLines, (leftLine, rightLine) => - leftLine + (new String(' ', (width_out - leftWidth - rightWidth))) + rightLine)); + leftLine + new String(' ', width_out - leftWidth - rightWidth) + rightLine)); // // Return @@ -165,7 +165,7 @@ private static List _recursivelyDrawTree rightLines = _recursivelyDrawTree(node.RightChild, out rightPosition, out rightWidth, includeValues); // Calculate pads - middle = Math.Max(Math.Max(padValue, nodeLabel.Length), (rightPosition + leftWidth - leftPosition + 1)); + middle = Math.Max(Math.Max(padValue, nodeLabel.Length), rightPosition + leftWidth - leftPosition + 1); position_out = leftPosition + middle; width_out = leftPosition + middle + rightWidth - rightPosition; @@ -175,7 +175,7 @@ private static List _recursivelyDrawTree while (rightLines.Count < leftLines.Count) rightLines.Add(new String(' ', rightWidth)); - if ((middle - nodeLabel.Length % padValue == 1) && (nodeLabel.Length < middle) && (node.Parent != null && node.IsLeftChild)) + if (middle - nodeLabel.Length % padValue == 1 && nodeLabel.Length < middle && node.Parent != null && node.IsLeftChild) nodeLabel += "."; // Format the node's label @@ -196,10 +196,10 @@ private static List _recursivelyDrawTree listOfLines = new List() { // 0 - (new String(' ', leftPosition )) + nodeLabel + (new String(' ', (rightWidth - rightPosition))), + new String(' ', leftPosition ) + nodeLabel + new String(' ', rightWidth - rightPosition), // 1 - (new String(' ', leftPosition)) + "/" + (new String(' ', (middle - padValue))) + "\\" + (new String(' ', (rightWidth - rightPosition))) + new String(' ', leftPosition) + "/" + new String(' ', middle - padValue) + "\\" + new String(' ', rightWidth - rightPosition) }; // @@ -208,7 +208,7 @@ private static List _recursivelyDrawTree listOfLines.Concat( leftLines.Zip( rightLines, (left_line, right_line) => - left_line + (new String(' ', (width_out - leftWidth - rightWidth))) + right_line) + left_line + new String(' ', width_out - leftWidth - rightWidth) + right_line) ).ToList(); // diff --git a/DataStructures/Trees/TrieMap.cs b/DataStructures/Trees/TrieMap.cs index 950ab255..e872c16b 100644 --- a/DataStructures/Trees/TrieMap.cs +++ b/DataStructures/Trees/TrieMap.cs @@ -272,7 +272,7 @@ bool ICollection>.Contains(KeyValuePair>.CopyTo(KeyValuePair[] array, int arrayIndex) diff --git a/UnitTest/AlgorithmsTests/LSDRadixSorterTest.cs b/UnitTest/AlgorithmsTests/LSDRadixSorterTest.cs index ff89ba01..b240f6cb 100644 --- a/UnitTest/AlgorithmsTests/LSDRadixSorterTest.cs +++ b/UnitTest/AlgorithmsTests/LSDRadixSorterTest.cs @@ -16,10 +16,10 @@ public static void DoTest() var number1 = "0987654321"; var number2 = "000999888777111222333777666555"; - name1 = (name1.LSDRadixSort()).Trim(); + name1 = name1.LSDRadixSort().Trim(); Assert.True(name1 == ".AAMadhhlmorru"); - name2 = (name2.LSDRadixSort()).Trim(); + name2 = name2.LSDRadixSort().Trim(); Assert.True(name2 == ".AHJMaacfhnnnooprrst"); number1 = number1.LSDRadixSort(); diff --git a/UnitTest/DataStructuresTests/CliqueGraphTest.cs b/UnitTest/DataStructuresTests/CliqueGraphTest.cs index d05f61d3..5028140b 100644 --- a/UnitTest/DataStructuresTests/CliqueGraphTest.cs +++ b/UnitTest/DataStructuresTests/CliqueGraphTest.cs @@ -95,7 +95,7 @@ int IComparable.CompareTo(ComparableTuple other) { int myInt = ToInt; int otherInt = other.ToInt; - return myInt < otherInt ? -1 : (myInt > otherInt ? 1 : 0); + return myInt < otherInt ? -1 : myInt > otherInt ? 1 : 0; } #endregion diff --git a/UnitTest/DataStructuresTests/DLinkedListTest.cs b/UnitTest/DataStructuresTests/DLinkedListTest.cs index 577fee4a..0045e650 100644 --- a/UnitTest/DataStructuresTests/DLinkedListTest.cs +++ b/UnitTest/DataStructuresTests/DLinkedListTest.cs @@ -51,7 +51,7 @@ public static void DoTest() listOfStrings.InsertAt("InsertedAtLast1", listOfStrings.Count); listOfStrings.InsertAt("InsertedAtLast2", listOfStrings.Count); - listOfStrings.InsertAt("InsertedAtMiddle", (listOfStrings.Count / 2)); + listOfStrings.InsertAt("InsertedAtMiddle", listOfStrings.Count / 2); listOfStrings.InsertAt("InsertedAt 4", 4); listOfStrings.InsertAt("InsertedAt 9", 9); listOfStrings.InsertAfter("InsertedAfter 11", 11); diff --git a/UnitTest/DataStructuresTests/SortedListTests.cs b/UnitTest/DataStructuresTests/SortedListTests.cs index 12ea1a3c..a79f991d 100644 --- a/UnitTest/DataStructuresTests/SortedListTests.cs +++ b/UnitTest/DataStructuresTests/SortedListTests.cs @@ -45,7 +45,7 @@ public static void DoTest() // // Compare sort order - while (enumerator.MoveNext() && (index < expectedSort.Length)) + while (enumerator.MoveNext() && index < expectedSort.Length) { Assert.Equal(enumerator.Current, expectedSort[index]); index++; @@ -113,7 +113,7 @@ public static void DoTest() Assert.True(sortedList.Count == newExpectedSort.Length, "Wrong number of items."); // Compare sort order - while (enumerator.MoveNext() && (index < newExpectedSort.Length)) + while (enumerator.MoveNext() && index < newExpectedSort.Length) { // TODO: Verify Assert.True(enumerator.Current == newExpectedSort[index], "Wrong sorting order."); From ae685434b381f3e9427d901934f9980635ca65a2 Mon Sep 17 00:00:00 2001 From: Mohamed Fazrin Date: Wed, 12 Oct 2022 10:08:09 +0300 Subject: [PATCH 5/5] file scoped namespaces utilized to reduce the nesting and improve the code readability --- Algorithms/Common/Comparers.cs | 114 +- Algorithms/Common/Helpers.cs | 72 +- Algorithms/Graphs/BellmanFordShortestPaths.cs | 394 +++-- Algorithms/Graphs/BipartiteColoring.cs | 275 ++-- Algorithms/Graphs/BreadthFirstSearcher.cs | 217 ++- .../Graphs/BreadthFirstShortestPaths.cs | 439 +++--- Algorithms/Graphs/ConnectedComponents.cs | 88 +- Algorithms/Graphs/CyclesDetector.cs | 166 ++- Algorithms/Graphs/DepthFirstSearcher.cs | 225 ++- .../Graphs/DijkstraAllPairsShortestPaths.cs | 104 +- Algorithms/Graphs/DijkstraShortestPaths.cs | 239 ++- Algorithms/Graphs/TopologicalSorter.cs | 75 +- Algorithms/Numeric/BinomialCoefficients.cs | 45 +- Algorithms/Numeric/CatalanNumbers.cs | 129 +- Algorithms/Numeric/GreatestCommonDivisor.cs | 101 +- Algorithms/Numeric/SieveOfAtkin.cs | 95 +- Algorithms/Numeric/SieveOfEratosthenes.cs | 67 +- Algorithms/Search/BinarySearcher.cs | 157 +- Algorithms/Sorting/BinarySearchTreeSorter.cs | 165 ++- Algorithms/Sorting/BubbleSorter.cs | 55 +- Algorithms/Sorting/BucketSorter.cs | 121 +- Algorithms/Sorting/CombSorter.cs | 91 +- Algorithms/Sorting/CountingSorter.cs | 71 +- Algorithms/Sorting/CycleSorter.cs | 113 +- Algorithms/Sorting/GnomeSorter.cs | 83 +- Algorithms/Sorting/HeapSorter.cs | 229 ++- Algorithms/Sorting/InsertionSorter.cs | 81 +- Algorithms/Sorting/LSDRadixSorter.cs | 153 +- Algorithms/Sorting/MergeSorter.cs | 114 +- Algorithms/Sorting/OddEvenSorter.cs | 95 +- Algorithms/Sorting/PigeonHoleSorter.cs | 87 +- Algorithms/Sorting/QuickSorter.cs | 95 +- Algorithms/Sorting/SelectionSorter.cs | 67 +- Algorithms/Sorting/ShellSorter.cs | 75 +- Algorithms/Strings/EditDistance.cs | 134 +- Algorithms/Strings/EditDistanceCostsMap.cs | 39 +- Algorithms/Strings/Permutations.cs | 138 +- Algorithms/Trees/BinaryTreeIterativeWalker.cs | 36 +- Algorithms/Trees/BinaryTreeRecursiveWalker.cs | 455 +++--- DataStructures/Common/Comparers.cs | 146 +- DataStructures/Common/Helpers.cs | 96 +- DataStructures/Common/PrimesList.cs | 335 +++-- .../Dictionaries/ChainedHashTable.cs | 892 ++++++----- .../Dictionaries/CuckooHashTable.cs | 548 ++++--- .../Dictionaries/OpenAddressingHashTable.cs | 567 ++++--- .../Dictionaries/OpenScatterHashTable.cs | 384 +++-- DataStructures/Graphs/CliqueGraph.cs | 1240 ++++++++-------- DataStructures/Graphs/DirectedDenseGraph.cs | 739 +++++----- DataStructures/Graphs/DirectedSparseGraph.cs | 614 ++++---- .../Graphs/DirectedWeightedDenseGraph.cs | 532 ++++--- .../Graphs/DirectedWeightedSparseGraph.cs | 794 +++++----- DataStructures/Graphs/IEdge.cs | 54 +- DataStructures/Graphs/IGraph.cs | 242 ++- DataStructures/Graphs/IWeightedGraph.cs | 52 +- DataStructures/Graphs/UndirectedDenseGraph.cs | 749 +++++----- .../Graphs/UndirectedSparseGraph.cs | 611 ++++---- .../Graphs/UndirectedWeightedDenseGraph.cs | 513 ++++--- .../Graphs/UndirectedWeightedSparseGraph.cs | 838 ++++++----- DataStructures/Graphs/UnweightedEdge.cs | 98 +- DataStructures/Graphs/WeightedEdge.cs | 97 +- DataStructures/Hashing/PrimeHashingFamily.cs | 138 +- .../Hashing/UniversalHashingFamily.cs | 171 ++- DataStructures/Heaps/BinaryMaxHeap.cs | 423 +++--- DataStructures/Heaps/BinaryMinHeap.cs | 440 +++--- DataStructures/Heaps/BinomialMinHeap.cs | 576 ++++---- DataStructures/Heaps/IMaxHeap.cs | 119 +- DataStructures/Heaps/IMinHeap.cs | 119 +- DataStructures/Heaps/KeyedPriorityQueue.cs | 454 +++--- DataStructures/Heaps/MinPriorityQueue.cs | 440 +++--- DataStructures/Lists/ArrayList.cs | 1176 ++++++++------- DataStructures/Lists/CircularBuffer.cs | 331 +++-- DataStructures/Lists/DLinkedList.cs | 1300 ++++++++--------- DataStructures/Lists/DLinkedList_KeyValue.cs | 1204 ++++++++------- DataStructures/Lists/Queue.cs | 362 +++-- DataStructures/Lists/SLinkedList.cs | 714 +++++---- DataStructures/Lists/SkipList.cs | 544 ++++--- DataStructures/Lists/SkipListNode.cs | 97 +- DataStructures/Lists/Stack.cs | 190 ++- .../SortedCollections/SortedDictionary.cs | 377 +++-- .../SortedCollections/SortedList.cs | 312 ++-- DataStructures/Trees/AVLTree.cs | 622 ++++---- DataStructures/Trees/AVLTreeNode.cs | 63 +- .../Trees/AugmentedBinarySearchTree.cs | 491 ++++--- DataStructures/Trees/BTree.cs | 648 ++++---- DataStructures/Trees/BinarySearchTree.cs | 1228 ++++++++-------- DataStructures/Trees/BinarySearchTreeMap.cs | 1260 ++++++++-------- .../Trees/BinarySearchTreeMapNode.cs | 139 +- DataStructures/Trees/BinarySearchTreeNode.cs | 149 +- DataStructures/Trees/IBinarySearchTree.cs | 195 ++- DataStructures/Trees/RedBlackTree.cs | 1003 +++++++------ DataStructures/Trees/RedBlackTreeMap.cs | 978 +++++++------ DataStructures/Trees/RedBlackTreeMapNode.cs | 104 +- DataStructures/Trees/RedBlackTreeNode.cs | 102 +- DataStructures/Trees/TernarySearchTree.cs | 115 +- DataStructures/Trees/TernaryTreeNode.cs | 75 +- DataStructures/Trees/TreeDrawer.cs | 365 +++-- DataStructures/Trees/Trie.cs | 264 ++-- DataStructures/Trees/TrieMap.cs | 515 ++++--- DataStructures/Trees/TrieMapNode.cs | 190 ++- DataStructures/Trees/TrieNode.cs | 185 ++- .../BinarySearchTreeSorterTest.cs | 19 +- .../AlgorithmsTests/BinarySearcherTest.cs | 123 +- .../BinaryTreeRecursiveWalkerTests.cs | 293 ++-- UnitTest/AlgorithmsTests/BubbleSorterTest.cs | 23 +- .../AlgorithmsTests/CatalanNumbersTest.cs | 109 +- UnitTest/AlgorithmsTests/CountingSortTest.cs | 19 +- .../GraphsBipartiteColoringTest.cs | 231 ++- .../GraphsBreadthFirstPathsTest.cs | 89 +- .../GraphsBreadthFirstSearchTest.cs | 95 +- .../GraphsConnectedComponents.cs | 102 +- .../GraphsCyclesDetectorTests.cs | 138 +- .../GraphsDepthFirstSearchTest.cs | 98 +- .../GraphsDijkstraShortestPathsTest.cs | 485 +++--- .../GraphsTopologicalSorterTest.cs | 99 +- .../GreatestCommonDivisorTests.cs | 141 +- UnitTest/AlgorithmsTests/HeapSorterTest.cs | 31 +- UnitTest/AlgorithmsTests/InsertionSortTest.cs | 94 +- .../AlgorithmsTests/LSDRadixSorterTest.cs | 58 +- UnitTest/AlgorithmsTests/MergeSorterTest.cs | 22 +- UnitTest/AlgorithmsTests/QuickSortTest.cs | 22 +- UnitTest/AlgorithmsTests/SieveOfAtkinTest.cs | 23 +- .../SieveOfEratosthenesTests.cs | 49 +- .../AlgorithmsTests/StringEditDistanceTest.cs | 60 +- .../AlgorithmsTests/StringPermutationTests.cs | 69 +- UnitTest/DataStructuresTests/AVLTreeTest.cs | 520 ++++--- UnitTest/DataStructuresTests/ArrayListTest.cs | 115 +- UnitTest/DataStructuresTests/BTreeTest.cs | 407 +++--- .../DataStructuresTests/BinaryHeapsTest.cs | 302 ++-- .../BinarySearchTreeMapTests.cs | 212 ++- .../BinarySearchTreeTest.cs | 223 ++- .../DataStructuresTests/BinomialHeapsTest.cs | 53 +- .../DataStructuresTests/CircularBufferTest.cs | 437 +++--- .../DataStructuresTests/CliqueGraphTest.cs | 156 +- .../CuckooHashTableTest.cs | 59 +- .../DataStructuresTests/DLinkedListTest.cs | 230 ++- .../GraphsDirectedDenseGraphTest.cs | 219 ++- .../GraphsDirectedSparseGraphTest.cs | 268 ++-- .../GraphsDirectedWeightedDenseGraphTest.cs | 309 ++-- .../GraphsDirectedWeightedSparseGraphTest.cs | 300 ++-- .../GraphsUndirectedDenseGraphTest.cs | 211 ++- .../GraphsUndirectedSparseGraphTest.cs | 168 ++- ...GraphsUndirectedWeightedSparseGraphTest.cs | 333 +++-- .../HashTableSeparateChainingTest.cs | 265 ++-- UnitTest/DataStructuresTests/PrimeListTest.cs | 31 +- .../DataStructuresTests/PriorityQueuesTest.cs | 176 ++- UnitTest/DataStructuresTests/QueueTest.cs | 60 +- .../RedBlackTreeMapTests.cs | 357 +++-- .../DataStructuresTests/RedBlackTreeTest.cs | 715 +++++---- .../DataStructuresTests/SLinkedListTest.cs | 116 +- UnitTest/DataStructuresTests/SkipListTest.cs | 41 +- .../SortedDictionaryTests.cs | 235 ++- .../DataStructuresTests/SortedListTests.cs | 230 ++- UnitTest/DataStructuresTests/StackTest.cs | 60 +- .../TernarySearchTreeTest.cs | 45 +- UnitTest/DataStructuresTests/TrieMapTest.cs | 257 ++-- UnitTest/DataStructuresTests/TrieTest.cs | 261 ++-- .../UndirectedWeightedDenseGraphTests.cs | 387 +++-- 157 files changed, 21900 insertions(+), 22168 deletions(-) diff --git a/Algorithms/Common/Comparers.cs b/Algorithms/Common/Comparers.cs index bb6e6418..34e4ab63 100644 --- a/Algorithms/Common/Comparers.cs +++ b/Algorithms/Common/Comparers.cs @@ -1,70 +1,68 @@ using System; -namespace Algorithms.Common +namespace Algorithms.Common; + +public static class Comparers { - public static class Comparers + /// + /// Determines if a specific value is a number. + /// + /// true if the value is a number; otherwise, false. + /// Value. + /// The Type of value. + public static bool IsNumber(this T value) { - /// - /// Determines if a specific value is a number. - /// - /// true if the value is a number; otherwise, false. - /// Value. - /// The Type of value. - public static bool IsNumber(this T value) - { - if (value is sbyte) return true; - if (value is byte) return true; - if (value is short) return true; - if (value is ushort) return true; - if (value is int) return true; - if (value is uint) return true; - if (value is long) return true; - if (value is ulong) return true; - if (value is float) return true; - if (value is double) return true; - if (value is decimal) return true; - return false; - } - + if (value is sbyte) return true; + if (value is byte) return true; + if (value is short) return true; + if (value is ushort) return true; + if (value is int) return true; + if (value is uint) return true; + if (value is long) return true; + if (value is ulong) return true; + if (value is float) return true; + if (value is double) return true; + if (value is decimal) return true; + return false; + } - /// - /// Determines if firstValue is equals to the specified secondValue. - /// - /// true if firstValue is equals to the specified secondValue; otherwise, false. - /// The first value. - /// The second value. - /// The Type of values. - public static bool IsEqualTo(this T firstValue, T secondValue) where T : IComparable - { - return firstValue.Equals(secondValue); - } + /// + /// Determines if firstValue is equals to the specified secondValue. + /// + /// true if firstValue is equals to the specified secondValue; otherwise, false. + /// The first value. + /// The second value. + /// The Type of values. + public static bool IsEqualTo(this T firstValue, T secondValue) where T : IComparable + { + return firstValue.Equals(secondValue); + } - /// - /// Determines if thisValue is greater than the specified otherValue. - /// - /// true if thisValue is greater than the specified otherValue; otherwise, false. - /// The first value. - /// The second value. - /// The Type of values. - public static bool IsGreaterThan(this T firstValue, T secondValue) where T : IComparable - { - return firstValue.CompareTo(secondValue) > 0; - } + /// + /// Determines if thisValue is greater than the specified otherValue. + /// + /// true if thisValue is greater than the specified otherValue; otherwise, false. + /// The first value. + /// The second value. + /// The Type of values. + public static bool IsGreaterThan(this T firstValue, T secondValue) where T : IComparable + { + return firstValue.CompareTo(secondValue) > 0; + } - /// - /// Determines if thisValue is less than the specified otherValue. - /// - /// true if thisValue is less than the specified otherValue; otherwise, false. - /// The first value. - /// The second value. - /// The Type of values. - public static bool IsLessThan(this T firstValue, T secondValue) where T : IComparable - { - return firstValue.CompareTo(secondValue) < 0; - } + /// + /// Determines if thisValue is less than the specified otherValue. + /// + /// true if thisValue is less than the specified otherValue; otherwise, false. + /// The first value. + /// The second value. + /// The Type of values. + public static bool IsLessThan(this T firstValue, T secondValue) where T : IComparable + { + return firstValue.CompareTo(secondValue) < 0; } -} +} \ No newline at end of file diff --git a/Algorithms/Common/Helpers.cs b/Algorithms/Common/Helpers.cs index 8d78384f..88b0a280 100644 --- a/Algorithms/Common/Helpers.cs +++ b/Algorithms/Common/Helpers.cs @@ -1,49 +1,47 @@ using System.Collections.Generic; using DataStructures.Lists; -namespace Algorithms.Common +namespace Algorithms.Common; + +public static class Helpers { - public static class Helpers + /// + /// Swaps two values in an IList collection given their indexes. + /// + public static void Swap(this IList list, int firstIndex, int secondIndex) { - /// - /// Swaps two values in an IList collection given their indexes. - /// - public static void Swap(this IList list, int firstIndex, int secondIndex) - { - if (list.Count < 2 || firstIndex == secondIndex) //This check is not required but Partition function may make many calls so its for perf reason - return; + if (list.Count < 2 || firstIndex == secondIndex) //This check is not required but Partition function may make many calls so its for perf reason + return; - var temp = list[firstIndex]; - list[firstIndex] = list[secondIndex]; - list[secondIndex] = temp; - } + var temp = list[firstIndex]; + list[firstIndex] = list[secondIndex]; + list[secondIndex] = temp; + } - /// - /// Swaps two values in an ArrayList collection given their indexes. - /// - public static void Swap(this ArrayList list, int firstIndex, int secondIndex) - { - if (list.Count < 2 || firstIndex == secondIndex) //This check is not required but Partition function may make many calls so its for perf reason - return; + /// + /// Swaps two values in an ArrayList collection given their indexes. + /// + public static void Swap(this ArrayList list, int firstIndex, int secondIndex) + { + if (list.Count < 2 || firstIndex == secondIndex) //This check is not required but Partition function may make many calls so its for perf reason + return; - var temp = list[firstIndex]; - list[firstIndex] = list[secondIndex]; - list[secondIndex] = temp; - } + var temp = list[firstIndex]; + list[firstIndex] = list[secondIndex]; + list[secondIndex] = temp; + } - /// - /// Populates a collection with a specific value. - /// - public static void Populate(this IList collection, T value) - { - if (collection == null) - return; + /// + /// Populates a collection with a specific value. + /// + public static void Populate(this IList collection, T value) + { + if (collection == null) + return; - for (int i = 0; i < collection.Count; i++) - { - collection[i] = value; - } + for (int i = 0; i < collection.Count; i++) + { + collection[i] = value; } } -} - +} \ No newline at end of file diff --git a/Algorithms/Graphs/BellmanFordShortestPaths.cs b/Algorithms/Graphs/BellmanFordShortestPaths.cs index 96771291..ffef9c5a 100644 --- a/Algorithms/Graphs/BellmanFordShortestPaths.cs +++ b/Algorithms/Graphs/BellmanFordShortestPaths.cs @@ -4,98 +4,75 @@ using Algorithms.Common; using DataStructures.Graphs; -namespace Algorithms.Graphs +namespace Algorithms.Graphs; + +public class BellmanFordShortestPaths + where TGraph : IGraph, IWeightedGraph + where TVertex : IComparable { - public class BellmanFordShortestPaths - where TGraph : IGraph, IWeightedGraph - where TVertex : IComparable + /// + /// INSTANCE VARIABLES + /// + private int _edgesCount; + private int _verticesCount; + private long[] _distances; + private int[] _predecessors; + private WeightedEdge[] _edgeTo; + + // A dictionary that maps node-values to integer indeces + private Dictionary _nodesToIndices; + + // A dictionary that maps integer index to node-value + private Dictionary _indicesToNodes; + + // A const that represent an infinite distance + private const Int64 Infinity = Int64.MaxValue; + private const int NilPredecessor = -1; + + + /// + /// CONSTRUCTOR + /// + public BellmanFordShortestPaths(TGraph Graph, TVertex Source) { - /// - /// INSTANCE VARIABLES - /// - private int _edgesCount; - private int _verticesCount; - private long[] _distances; - private int[] _predecessors; - private WeightedEdge[] _edgeTo; - - // A dictionary that maps node-values to integer indeces - private Dictionary _nodesToIndices; - - // A dictionary that maps integer index to node-value - private Dictionary _indicesToNodes; - - // A const that represent an infinite distance - private const Int64 Infinity = Int64.MaxValue; - private const int NilPredecessor = -1; - - - /// - /// CONSTRUCTOR - /// - public BellmanFordShortestPaths(TGraph Graph, TVertex Source) - { - if (Graph == null) { - throw new ArgumentNullException (); - } else { - if (!Graph.HasVertex (Source)) - throw new ArgumentException ("The source vertex doesn't belong to graph."); + if (Graph == null) { + throw new ArgumentNullException (); + } else { + if (!Graph.HasVertex (Source)) + throw new ArgumentException ("The source vertex doesn't belong to graph."); - // Init - _initializeDataMembers (Graph); + // Init + _initializeDataMembers (Graph); - // Traverse the graph - var status = _bellmanFord (Graph, Source); + // Traverse the graph + var status = _bellmanFord (Graph, Source); - if (status == false) - throw new Exception ("Negative-weight cycle detected."); + if (status == false) + throw new Exception ("Negative-weight cycle detected."); - Debug.Assert (_checkOptimalityConditions (Graph, Source)); - } + Debug.Assert (_checkOptimalityConditions (Graph, Source)); } + } - /************************************************************************************************************/ + /************************************************************************************************************/ - /// - /// The Bellman-Ford Algorithm. - /// - /// True if shortest-path computation is finished with no negative-weight cycles detected; otehrwise, false. - private bool _bellmanFord(TGraph graph, TVertex source) - { - int srcIndex = _nodesToIndices[source]; - _distances[srcIndex] = 0; + /// + /// The Bellman-Ford Algorithm. + /// + /// True if shortest-path computation is finished with no negative-weight cycles detected; otehrwise, false. + private bool _bellmanFord(TGraph graph, TVertex source) + { + int srcIndex = _nodesToIndices[source]; + _distances[srcIndex] = 0; - var edges = graph.Edges as IEnumerable>; + var edges = graph.Edges as IEnumerable>; - // First pass - // Calculate shortest paths and relax all edges. - for (int i = 1; i < graph.VerticesCount - 1; ++i) - { - foreach (var edge in edges) - { - int fromIndex = _nodesToIndices[edge.Source]; - int toIndex = _nodesToIndices[edge.Destination]; - - // calculate a new possible weighted path if the edge weight is less than infinity - var delta = Infinity; - if (edge.Weight < Infinity && Infinity - edge.Weight > _distances[fromIndex]) // Handles overflow - delta = _distances[fromIndex] + edge.Weight; - - // Relax the edge - // if check is true, a shorter path is found from current to adjacent - if (delta < _distances[toIndex]) - { - _edgeTo[toIndex] = edge; - _distances[toIndex] = delta; - _predecessors[toIndex] = fromIndex; - } - } - } - - // Second pass - // Check for negative-weight cycles. + // First pass + // Calculate shortest paths and relax all edges. + for (int i = 1; i < graph.VerticesCount - 1; ++i) + { foreach (var edge in edges) { int fromIndex = _nodesToIndices[edge.Source]; @@ -106,170 +83,191 @@ private bool _bellmanFord(TGraph graph, TVertex source) if (edge.Weight < Infinity && Infinity - edge.Weight > _distances[fromIndex]) // Handles overflow delta = _distances[fromIndex] + edge.Weight; - // if check is true a negative-weight cycle is detected - // return false; + // Relax the edge + // if check is true, a shorter path is found from current to adjacent if (delta < _distances[toIndex]) - return false; + { + _edgeTo[toIndex] = edge; + _distances[toIndex] = delta; + _predecessors[toIndex] = fromIndex; + } } - - // Completed shortest paths computation. - // No negative edges were detected. - return true; } - /// - /// Constructors helper function. Initializes some of the data memebers. - /// - private void _initializeDataMembers(TGraph Graph) + // Second pass + // Check for negative-weight cycles. + foreach (var edge in edges) { - _edgesCount = Graph.EdgesCount; - _verticesCount = Graph.VerticesCount; + int fromIndex = _nodesToIndices[edge.Source]; + int toIndex = _nodesToIndices[edge.Destination]; - _distances = new Int64[_verticesCount]; - _predecessors = new int[_verticesCount]; - _edgeTo = new WeightedEdge[_edgesCount]; + // calculate a new possible weighted path if the edge weight is less than infinity + var delta = Infinity; + if (edge.Weight < Infinity && Infinity - edge.Weight > _distances[fromIndex]) // Handles overflow + delta = _distances[fromIndex] + edge.Weight; - _nodesToIndices = new Dictionary(); - _indicesToNodes = new Dictionary(); + // if check is true a negative-weight cycle is detected + // return false; + if (delta < _distances[toIndex]) + return false; + } - // Reset the information arrays - int i = 0; - foreach (var node in Graph.Vertices) - { - if (i >= _verticesCount) - break; + // Completed shortest paths computation. + // No negative edges were detected. + return true; + } + + /// + /// Constructors helper function. Initializes some of the data memebers. + /// + private void _initializeDataMembers(TGraph Graph) + { + _edgesCount = Graph.EdgesCount; + _verticesCount = Graph.VerticesCount; - _edgeTo[i] = null; - _distances[i] = Infinity; - _predecessors[i] = NilPredecessor; + _distances = new Int64[_verticesCount]; + _predecessors = new int[_verticesCount]; + _edgeTo = new WeightedEdge[_edgesCount]; - _nodesToIndices.Add(node, i); - _indicesToNodes.Add(i, node); + _nodesToIndices = new Dictionary(); + _indicesToNodes = new Dictionary(); - ++i; - } + // Reset the information arrays + int i = 0; + foreach (var node in Graph.Vertices) + { + if (i >= _verticesCount) + break; + + _edgeTo[i] = null; + _distances[i] = Infinity; + _predecessors[i] = NilPredecessor; + + _nodesToIndices.Add(node, i); + _indicesToNodes.Add(i, node); + + ++i; + } + } + + /// + /// Constructors helper function. Checks Optimality Conditions: + /// (i) for all edges e: distTo[e.to()] <= distTo[e.from()] + e.weight() + /// (ii) for all edge e on the SPT: distTo[e.to()] == distTo[e.from()] + e.weight() + /// + private bool _checkOptimalityConditions(TGraph graph, TVertex source) + { + // Get the source index (to be used with the information arrays). + int s = _nodesToIndices[source]; + + // check that distTo[v] and edgeTo[v] are consistent + if (_distances[s] != 0 || _predecessors[s] != NilPredecessor) + { + Console.WriteLine("distanceTo[s] and edgeTo[s] are inconsistent"); + return false; } - /// - /// Constructors helper function. Checks Optimality Conditions: - /// (i) for all edges e: distTo[e.to()] <= distTo[e.from()] + e.weight() - /// (ii) for all edge e on the SPT: distTo[e.to()] == distTo[e.from()] + e.weight() - /// - private bool _checkOptimalityConditions(TGraph graph, TVertex source) + for (int v = 0; v < graph.VerticesCount; v++) { - // Get the source index (to be used with the information arrays). - int s = _nodesToIndices[source]; + if (v == s) continue; - // check that distTo[v] and edgeTo[v] are consistent - if (_distances[s] != 0 || _predecessors[s] != NilPredecessor) + if (_predecessors[v] == NilPredecessor && _distances[v] != Infinity) { - Console.WriteLine("distanceTo[s] and edgeTo[s] are inconsistent"); + Console.WriteLine("distanceTo[] and edgeTo[] are inconsistent for at least one vertex."); return false; } + } - for (int v = 0; v < graph.VerticesCount; v++) - { - if (v == s) continue; - - if (_predecessors[v] == NilPredecessor && _distances[v] != Infinity) - { - Console.WriteLine("distanceTo[] and edgeTo[] are inconsistent for at least one vertex."); - return false; - } - } + // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight() + foreach (var vertex in graph.Vertices) + { + int v = _nodesToIndices[vertex]; - // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight() - foreach (var vertex in graph.Vertices) + foreach (var edge in graph.NeighboursMap(vertex)) { - int v = _nodesToIndices[vertex]; + int w = _nodesToIndices[edge.Key]; - foreach (var edge in graph.NeighboursMap(vertex)) + if (_distances[v] + edge.Value < _distances[w]) { - int w = _nodesToIndices[edge.Key]; - - if (_distances[v] + edge.Value < _distances[w]) - { - Console.WriteLine("edge " + vertex + "-" + edge.Key + " is not relaxed"); - return false; - } + Console.WriteLine("edge " + vertex + "-" + edge.Key + " is not relaxed"); + return false; } } + } - // check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight() - foreach (var vertex in graph.Vertices) - { - int w = _nodesToIndices[vertex]; + // check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight() + foreach (var vertex in graph.Vertices) + { + int w = _nodesToIndices[vertex]; - if (_edgeTo[w] == null) - continue; + if (_edgeTo[w] == null) + continue; - var edge = _edgeTo[w]; - int v = _nodesToIndices[edge.Source]; + var edge = _edgeTo[w]; + int v = _nodesToIndices[edge.Source]; - if (!vertex.IsEqualTo(edge.Destination)) - return false; + if (!vertex.IsEqualTo(edge.Destination)) + return false; - if (_distances[v] + edge.Weight != _distances[w]) - { - Console.WriteLine("edge " + edge.Source + "-" + edge.Destination + " on shortest path not tight"); - return false; - } + if (_distances[v] + edge.Weight != _distances[w]) + { + Console.WriteLine("edge " + edge.Source + "-" + edge.Destination + " on shortest path not tight"); + return false; } - - return true; } + return true; + } - /************************************************************************************************************/ + /************************************************************************************************************/ - /// - /// Determines whether there is a path from the source vertex to this specified vertex. - /// - public bool HasPathTo(TVertex destination) - { - if (!_nodesToIndices.ContainsKey(destination)) - throw new Exception("Graph doesn't have the specified vertex."); - int index = _nodesToIndices[destination]; - return _distances[index] != Infinity; - } + /// + /// Determines whether there is a path from the source vertex to this specified vertex. + /// + public bool HasPathTo(TVertex destination) + { + if (!_nodesToIndices.ContainsKey(destination)) + throw new Exception("Graph doesn't have the specified vertex."); - /// - /// Returns the distance between the source vertex and the specified vertex. - /// - public long DistanceTo(TVertex destination) - { - if (!_nodesToIndices.ContainsKey(destination)) - throw new Exception("Graph doesn't have the specified vertex."); + int index = _nodesToIndices[destination]; + return _distances[index] != Infinity; + } - int index = _nodesToIndices[destination]; - return _distances[index]; - } + /// + /// Returns the distance between the source vertex and the specified vertex. + /// + public long DistanceTo(TVertex destination) + { + if (!_nodesToIndices.ContainsKey(destination)) + throw new Exception("Graph doesn't have the specified vertex."); - /// - /// Returns an enumerable collection of nodes that specify the shortest path from the source vertex to the destination vertex. - /// - public IEnumerable ShortestPathTo(TVertex destination) - { - if (!_nodesToIndices.ContainsKey(destination)) - throw new Exception("Graph doesn't have the specified vertex."); - if (!HasPathTo(destination)) - return null; + int index = _nodesToIndices[destination]; + return _distances[index]; + } - int dstIndex = _nodesToIndices[destination]; - var stack = new DataStructures.Lists.Stack(); + /// + /// Returns an enumerable collection of nodes that specify the shortest path from the source vertex to the destination vertex. + /// + public IEnumerable ShortestPathTo(TVertex destination) + { + if (!_nodesToIndices.ContainsKey(destination)) + throw new Exception("Graph doesn't have the specified vertex."); + if (!HasPathTo(destination)) + return null; - int index; - for (index = dstIndex; _distances[index] != 0; index = _predecessors[index]) - stack.Push(_indicesToNodes[index]); + int dstIndex = _nodesToIndices[destination]; + var stack = new DataStructures.Lists.Stack(); - // Push the source vertex + int index; + for (index = dstIndex; _distances[index] != 0; index = _predecessors[index]) stack.Push(_indicesToNodes[index]); - return stack; - } + // Push the source vertex + stack.Push(_indicesToNodes[index]); + return stack; } -} +} \ No newline at end of file diff --git a/Algorithms/Graphs/BipartiteColoring.cs b/Algorithms/Graphs/BipartiteColoring.cs index 8b041178..1ae5e5f6 100644 --- a/Algorithms/Graphs/BipartiteColoring.cs +++ b/Algorithms/Graphs/BipartiteColoring.cs @@ -16,183 +16,180 @@ using DataStructures.Graphs; -namespace Algorithms.Graphs +namespace Algorithms.Graphs; + +/// +/// The Bipartite Colors type. +/// +public enum BipartiteColor { - /// - /// The Bipartite Colors type. - /// - public enum BipartiteColor - { - Red = 0, - Blue = 1 - }; + Red = 0, + Blue = 1 +}; + + +/// +/// Bipartite Graph Coloring/Labeling. +/// +public class BipartiteColoring + where TGraph : IGraph + where TVertex : IComparable +{ + private bool _isBipartite { get; set; } + private int _edgesCount { get; set; } + private int _verticesCount { get; set; } + private bool[] _visited { get; set; } + private BipartiteColor[] _nodesColors { get; set; } + private Stack _cycle { get; set; } + + // A dictionary that maps node-values to integer indeces + private Dictionary _nodesToIndices { get; set; } + + // A dictionary that maps integer index to node-value + private Dictionary _indicesToNodes { get; set; } /// - /// Bipartite Graph Coloring/Labeling. + /// CONTRUSTOR /// - public class BipartiteColoring - where TGraph : IGraph - where TVertex : IComparable + public BipartiteColoring(IGraph Graph) { - private bool _isBipartite { get; set; } - private int _edgesCount { get; set; } - private int _verticesCount { get; set; } - private bool[] _visited { get; set; } - private BipartiteColor[] _nodesColors { get; set; } - private Stack _cycle { get; set; } + // Validate Graph parameter + if (Graph == null) + throw new ArgumentNullException(); + if (Graph.VerticesCount < 2) + throw new InvalidOperationException("Graph contains less elements than required."); - // A dictionary that maps node-values to integer indeces - private Dictionary _nodesToIndices { get; set; } + // Init data members + _initializeDataMembers(Graph); - // A dictionary that maps integer index to node-value - private Dictionary _indicesToNodes { get; set; } + // Set bipartite flag to true + _isBipartite = true; - - /// - /// CONTRUSTOR - /// - public BipartiteColoring(IGraph Graph) + // Compute bipartiteness + foreach (var vertex in Graph.Vertices) { - // Validate Graph parameter - if (Graph == null) - throw new ArgumentNullException(); - if (Graph.VerticesCount < 2) - throw new InvalidOperationException("Graph contains less elements than required."); - - // Init data members - _initializeDataMembers(Graph); + var vertexIndex = _nodesToIndices[vertex]; - // Set bipartite flag to true - _isBipartite = true; - - // Compute bipartiteness - foreach (var vertex in Graph.Vertices) + // Check the bipartite from this vertex, if it was not visited + if (!_visited[vertexIndex]) { - var vertexIndex = _nodesToIndices[vertex]; - - // Check the bipartite from this vertex, if it was not visited - if (!_visited[vertexIndex]) - { - _isBipartite = _isBipartiteHelper(Graph, vertex); + _isBipartite = _isBipartiteHelper(Graph, vertex); - // Stop discovery of graph when bipartiteness doesn't hold - if (!_isBipartite) - throw new InvalidOperationException("Graph contains an odd cycle."); - } + // Stop discovery of graph when bipartiteness doesn't hold + if (!_isBipartite) + throw new InvalidOperationException("Graph contains an odd cycle."); } } + } - /// - /// Constructors helper function. Initializes some of the data memebers. - /// - private void _initializeDataMembers(IGraph Graph) - { - _isBipartite = false; - _cycle = null; - - _edgesCount = Graph.EdgesCount; - _verticesCount = Graph.VerticesCount; + /// + /// Constructors helper function. Initializes some of the data memebers. + /// + private void _initializeDataMembers(IGraph Graph) + { + _isBipartite = false; + _cycle = null; - _visited = new bool[_verticesCount]; - _nodesColors = new BipartiteColor[_verticesCount]; + _edgesCount = Graph.EdgesCount; + _verticesCount = Graph.VerticesCount; - _nodesToIndices = new Dictionary(); - _indicesToNodes = new Dictionary(); + _visited = new bool[_verticesCount]; + _nodesColors = new BipartiteColor[_verticesCount]; - // Reset the visited, distances and predeccessors arrays - int i = 0; - foreach (var node in Graph.Vertices) - { - if (i >= _verticesCount) - break; + _nodesToIndices = new Dictionary(); + _indicesToNodes = new Dictionary(); - _visited[i] = false; - _nodesColors[i] = BipartiteColor.Red; + // Reset the visited, distances and predeccessors arrays + int i = 0; + foreach (var node in Graph.Vertices) + { + if (i >= _verticesCount) + break; - _nodesToIndices.Add(node, i); - _indicesToNodes.Add(i, node); + _visited[i] = false; + _nodesColors[i] = BipartiteColor.Red; - ++i; - } + _nodesToIndices.Add(node, i); + _indicesToNodes.Add(i, node); + ++i; } - /// - /// Constructors helper function. Computes the bipartite of graph from a source vertex. - /// - private bool _isBipartiteHelper(IGraph Graph, TVertex Source) + } + + /// + /// Constructors helper function. Computes the bipartite of graph from a source vertex. + /// + private bool _isBipartiteHelper(IGraph Graph, TVertex Source) + { + var queue = new Queue(); + queue.Enqueue(Source); + + while (queue.Count > 0) { - var queue = new Queue(); - queue.Enqueue(Source); + var current = queue.Dequeue(); + var currIndex = _nodesToIndices[current]; - while (queue.Count > 0) + // Visit node + if (!_visited[currIndex]) { - var current = queue.Dequeue(); - var currIndex = _nodesToIndices[current]; + _visited[currIndex] = true; + _nodesColors[currIndex] = BipartiteColor.Red; + } - // Visit node - if (!_visited[currIndex]) - { - _visited[currIndex] = true; - _nodesColors[currIndex] = BipartiteColor.Red; - } + // Discover bfs-level neighbors + foreach(var adjacent in Graph.Neighbours(current)) + { + var adjIndex = _nodesToIndices[adjacent]; - // Discover bfs-level neighbors - foreach(var adjacent in Graph.Neighbours(current)) + if (!_visited[adjIndex]) { - var adjIndex = _nodesToIndices[adjacent]; - - if (!_visited[adjIndex]) - { - _visited[adjIndex] = true; - _nodesColors[adjIndex] = _nodesColors[currIndex] == BipartiteColor.Red ? BipartiteColor.Blue : BipartiteColor.Red; - - queue.Enqueue(adjacent); - } - else if (_nodesColors[currIndex] == _nodesColors[adjIndex]) - { - return false; - } - }//end-foreach - }//end-while - - return true; - } + _visited[adjIndex] = true; + _nodesColors[adjIndex] = _nodesColors[currIndex] == BipartiteColor.Red ? BipartiteColor.Blue : BipartiteColor.Red; + queue.Enqueue(adjacent); + } + else if (_nodesColors[currIndex] == _nodesColors[adjIndex]) + { + return false; + } + }//end-foreach + }//end-while - /// - /// Determines the graph is bipartite. - /// - public bool IsBipartite() - { - return _isBipartite; - } + return true; + } - /// - /// Returns the color of a vertex. - /// - public BipartiteColor ColorOf(TVertex vertex) - { - if (!_isBipartite) - throw new InvalidOperationException("Graph is not bipartite."); - if (!_nodesToIndices.ContainsKey(vertex)) - throw new InvalidOperationException("Vertex doesn't belong to graph."); - return _nodesColors[_nodesToIndices[vertex]]; - } + /// + /// Determines the graph is bipartite. + /// + public bool IsBipartite() + { + return _isBipartite; + } - /// - /// Returns the odd-cycle in graoh, if any. - /// - /// The cycle. - public IEnumerable OddCycle() - { - throw new NotImplementedException(); - } + /// + /// Returns the color of a vertex. + /// + public BipartiteColor ColorOf(TVertex vertex) + { + if (!_isBipartite) + throw new InvalidOperationException("Graph is not bipartite."); + if (!_nodesToIndices.ContainsKey(vertex)) + throw new InvalidOperationException("Vertex doesn't belong to graph."); + return _nodesColors[_nodesToIndices[vertex]]; } -} + /// + /// Returns the odd-cycle in graoh, if any. + /// + /// The cycle. + public IEnumerable OddCycle() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/Algorithms/Graphs/BreadthFirstSearcher.cs b/Algorithms/Graphs/BreadthFirstSearcher.cs index 56a2c55a..3d8f3198 100644 --- a/Algorithms/Graphs/BreadthFirstSearcher.cs +++ b/Algorithms/Graphs/BreadthFirstSearcher.cs @@ -14,154 +14,151 @@ using DataStructures.Graphs; -namespace Algorithms.Graphs +namespace Algorithms.Graphs; + +public static class BreadthFirstSearcher { - public static class BreadthFirstSearcher + /// + /// Iterative BFS implementation. + /// Traverses nodes in graph starting from a specific node, printing them as they get visited. + /// + public static void PrintAll(IGraph Graph, T StartVertex) where T : IComparable { - /// - /// Iterative BFS implementation. - /// Traverses nodes in graph starting from a specific node, printing them as they get visited. - /// - public static void PrintAll(IGraph Graph, T StartVertex) where T : IComparable - { - // Check if graph is empty - if (Graph.VerticesCount == 0) - throw new Exception("Graph is empty!"); + // Check if graph is empty + if (Graph.VerticesCount == 0) + throw new Exception("Graph is empty!"); - // Check if graph has the starting vertex - if (!Graph.HasVertex(StartVertex)) - throw new Exception("Starting vertex doesn't belong to graph."); + // Check if graph has the starting vertex + if (!Graph.HasVertex(StartVertex)) + throw new Exception("Starting vertex doesn't belong to graph."); - var visited = new HashSet(); - var queue = new Queue(Graph.VerticesCount); + var visited = new HashSet(); + var queue = new Queue(Graph.VerticesCount); - queue.Enqueue (StartVertex); + queue.Enqueue (StartVertex); - while (queue.Count > 0) - { - var current = queue.Dequeue(); - Console.Write(String.Format("({0}) ", current)); + while (queue.Count > 0) + { + var current = queue.Dequeue(); + Console.Write(String.Format("({0}) ", current)); - foreach (var adjacent in Graph.Neighbours(current)) + foreach (var adjacent in Graph.Neighbours(current)) + { + if (!visited.Contains(adjacent)) { - if (!visited.Contains(adjacent)) - { - visited.Add(adjacent); - queue.Enqueue(adjacent); - } + visited.Add(adjacent); + queue.Enqueue(adjacent); } } } + } - /// - /// Iterative BFS implementation. - /// Traverses all the nodes in a graph starting from a specific node, applying the passed action to every node. - /// - public static void VisitAll(ref IGraph Graph, T StartVertex, Action Action) where T : IComparable - { - // Check if graph is empty - if (Graph.VerticesCount == 0) - throw new Exception("Graph is empty!"); + /// + /// Iterative BFS implementation. + /// Traverses all the nodes in a graph starting from a specific node, applying the passed action to every node. + /// + public static void VisitAll(ref IGraph Graph, T StartVertex, Action Action) where T : IComparable + { + // Check if graph is empty + if (Graph.VerticesCount == 0) + throw new Exception("Graph is empty!"); - // Check if graph has the starting vertex - if (!Graph.HasVertex(StartVertex)) - throw new Exception("Starting vertex doesn't belong to graph."); + // Check if graph has the starting vertex + if (!Graph.HasVertex(StartVertex)) + throw new Exception("Starting vertex doesn't belong to graph."); - int level = 0; // keeps track of level - var frontiers = new List(); // keeps track of previous levels, i - 1 - var levels = new Dictionary(Graph.VerticesCount); // keeps track of visited nodes and their distances - var parents = new Dictionary(Graph.VerticesCount); // keeps track of tree-nodes + int level = 0; // keeps track of level + var frontiers = new List(); // keeps track of previous levels, i - 1 + var levels = new Dictionary(Graph.VerticesCount); // keeps track of visited nodes and their distances + var parents = new Dictionary(Graph.VerticesCount); // keeps track of tree-nodes - frontiers.Add(StartVertex); - levels.Add(StartVertex, 0); - parents.Add(StartVertex, null); + frontiers.Add(StartVertex); + levels.Add(StartVertex, 0); + parents.Add(StartVertex, null); - // BFS VISIT CURRENT NODE - Action(StartVertex); + // BFS VISIT CURRENT NODE + Action(StartVertex); - // TRAVERSE GRAPH - while (frontiers.Count > 0) - { - var next = new List(); // keeps track of the current level, i + // TRAVERSE GRAPH + while (frontiers.Count > 0) + { + var next = new List(); // keeps track of the current level, i - foreach (var node in frontiers) + foreach (var node in frontiers) + { + foreach (var adjacent in Graph.Neighbours(node)) { - foreach (var adjacent in Graph.Neighbours(node)) + if (!levels.ContainsKey(adjacent)) // not visited yet { - if (!levels.ContainsKey(adjacent)) // not visited yet - { - // BFS VISIT NODE STEP - Action(adjacent); - - levels.Add(adjacent, level); // level[node] + 1 - parents.Add(adjacent, node); - next.Add(adjacent); - } + // BFS VISIT NODE STEP + Action(adjacent); + + levels.Add(adjacent, level); // level[node] + 1 + parents.Add(adjacent, node); + next.Add(adjacent); } } - - frontiers = next; - level = level + 1; } + + frontiers = next; + level = level + 1; } + } - /// - /// Iterative BFS Implementation. - /// Given a predicate function and a starting node, this function searches the nodes of the graph for a first match. - /// - public static T FindFirstMatch(IGraph Graph, T StartVertex, Predicate Match) where T : IComparable - { - // Check if graph is empty - if (Graph.VerticesCount == 0) - throw new Exception("Graph is empty!"); + /// + /// Iterative BFS Implementation. + /// Given a predicate function and a starting node, this function searches the nodes of the graph for a first match. + /// + public static T FindFirstMatch(IGraph Graph, T StartVertex, Predicate Match) where T : IComparable + { + // Check if graph is empty + if (Graph.VerticesCount == 0) + throw new Exception("Graph is empty!"); - // Check if graph has the starting vertex - if (!Graph.HasVertex(StartVertex)) - throw new Exception("Starting vertex doesn't belong to graph."); + // Check if graph has the starting vertex + if (!Graph.HasVertex(StartVertex)) + throw new Exception("Starting vertex doesn't belong to graph."); - int level = 0; // keeps track of levels - var frontiers = new List(); // keeps track of previous levels, i - 1 - var levels = new Dictionary(Graph.VerticesCount); // keeps track of visited nodes and their distances - var parents = new Dictionary(Graph.VerticesCount); // keeps track of tree-nodes + int level = 0; // keeps track of levels + var frontiers = new List(); // keeps track of previous levels, i - 1 + var levels = new Dictionary(Graph.VerticesCount); // keeps track of visited nodes and their distances + var parents = new Dictionary(Graph.VerticesCount); // keeps track of tree-nodes - frontiers.Add(StartVertex); - levels.Add(StartVertex, 0); - parents.Add(StartVertex, null); + frontiers.Add(StartVertex); + levels.Add(StartVertex, 0); + parents.Add(StartVertex, null); - // BFS VISIT CURRENT NODE - if (Match(StartVertex)) - return StartVertex; + // BFS VISIT CURRENT NODE + if (Match(StartVertex)) + return StartVertex; - // TRAVERSE GRAPH - while (frontiers.Count > 0) - { - var next = new List(); // keeps track of the current level, i + // TRAVERSE GRAPH + while (frontiers.Count > 0) + { + var next = new List(); // keeps track of the current level, i - foreach (var node in frontiers) + foreach (var node in frontiers) + { + foreach (var adjacent in Graph.Neighbours(node)) { - foreach (var adjacent in Graph.Neighbours(node)) + if (!levels.ContainsKey(adjacent)) // not visited yet { - if (!levels.ContainsKey(adjacent)) // not visited yet - { - // BFS VISIT NODE STEP - if (Match(adjacent)) - return adjacent; - - levels.Add(adjacent, level); // level[node] + 1 - parents.Add(adjacent, node); - next.Add(adjacent); - } + // BFS VISIT NODE STEP + if (Match(adjacent)) + return adjacent; + + levels.Add(adjacent, level); // level[node] + 1 + parents.Add(adjacent, node); + next.Add(adjacent); } } - - frontiers = next; - level = level + 1; } - throw new Exception("Item was not found!"); + frontiers = next; + level = level + 1; } + throw new Exception("Item was not found!"); } -} - +} \ No newline at end of file diff --git a/Algorithms/Graphs/BreadthFirstShortestPaths.cs b/Algorithms/Graphs/BreadthFirstShortestPaths.cs index d53e6a92..fd91321a 100644 --- a/Algorithms/Graphs/BreadthFirstShortestPaths.cs +++ b/Algorithms/Graphs/BreadthFirstShortestPaths.cs @@ -10,294 +10,291 @@ using Algorithms.Common; using DataStructures.Graphs; -namespace Algorithms.Graphs +namespace Algorithms.Graphs; + +public class BreadthFirstShortestPaths where T : IComparable { - public class BreadthFirstShortestPaths where T : IComparable - { - private int _edgesCount { get; set; } - private int _verticesCount { get; set; } - private bool[] _visited { get; set; } - private Int64[] _distances { get; set; } - private int[] _predecessors { get; set; } + private int _edgesCount { get; set; } + private int _verticesCount { get; set; } + private bool[] _visited { get; set; } + private Int64[] _distances { get; set; } + private int[] _predecessors { get; set; } - // A dictionary that maps node-values to integer indeces - private Dictionary _nodesToIndices { get; set; } + // A dictionary that maps node-values to integer indeces + private Dictionary _nodesToIndices { get; set; } - // A dictionary that maps integer index to node-value - private Dictionary _indicesToNodes { get; set; } + // A dictionary that maps integer index to node-value + private Dictionary _indicesToNodes { get; set; } - // A const that represent an infinite distance - private const Int64 INFINITY = Int64.MaxValue; + // A const that represent an infinite distance + private const Int64 INFINITY = Int64.MaxValue; - /// - /// CONSTRUCTOR. - /// Breadth First Searcher from Single Source. - /// - public BreadthFirstShortestPaths(IGraph Graph, T Source) - { - if (Graph == null) - throw new ArgumentNullException(); - if (!Graph.HasVertex(Source)) - throw new ArgumentException("The source vertex doesn't belong to graph."); + /// + /// CONSTRUCTOR. + /// Breadth First Searcher from Single Source. + /// + public BreadthFirstShortestPaths(IGraph Graph, T Source) + { + if (Graph == null) + throw new ArgumentNullException(); + if (!Graph.HasVertex(Source)) + throw new ArgumentException("The source vertex doesn't belong to graph."); - // Init - _initializeDataMembers(Graph); + // Init + _initializeDataMembers(Graph); - // Single source BFS - _breadthFirstSearch(Graph, Source); + // Single source BFS + _breadthFirstSearch(Graph, Source); - //bool optimalityConditionsSatisfied = checkOptimalityConditions (Graph, Source); - Debug.Assert(checkOptimalityConditions(Graph, Source)); - } + //bool optimalityConditionsSatisfied = checkOptimalityConditions (Graph, Source); + Debug.Assert(checkOptimalityConditions(Graph, Source)); + } - /// - /// CONSTRUCTOR. - /// Breadth First Searcher from Multiple Sources. - /// - public BreadthFirstShortestPaths(IGraph Graph, IList Sources) - { - if (Graph == null) - throw new ArgumentNullException(); - if (Sources == null || Sources.Count == 0) - throw new ArgumentException("Sources list is either null or empty."); + /// + /// CONSTRUCTOR. + /// Breadth First Searcher from Multiple Sources. + /// + public BreadthFirstShortestPaths(IGraph Graph, IList Sources) + { + if (Graph == null) + throw new ArgumentNullException(); + if (Sources == null || Sources.Count == 0) + throw new ArgumentException("Sources list is either null or empty."); - // Init - _initializeDataMembers(Graph); + // Init + _initializeDataMembers(Graph); - // Multiple sources BFS - _breadthFirstSearch(Graph, Sources); - } + // Multiple sources BFS + _breadthFirstSearch(Graph, Sources); + } - /************************************************************************************************************/ + /************************************************************************************************************/ - /// - /// Constructors helper function. Initializes some of the data memebers. - /// - private void _initializeDataMembers(IGraph Graph) - { - _edgesCount = Graph.EdgesCount; - _verticesCount = Graph.VerticesCount; + /// + /// Constructors helper function. Initializes some of the data memebers. + /// + private void _initializeDataMembers(IGraph Graph) + { + _edgesCount = Graph.EdgesCount; + _verticesCount = Graph.VerticesCount; - _visited = new bool[_verticesCount]; - _distances = new Int64[_verticesCount]; - _predecessors = new int[_verticesCount]; + _visited = new bool[_verticesCount]; + _distances = new Int64[_verticesCount]; + _predecessors = new int[_verticesCount]; - _nodesToIndices = new Dictionary(); - _indicesToNodes = new Dictionary(); + _nodesToIndices = new Dictionary(); + _indicesToNodes = new Dictionary(); - // Reset the visited, distances and predeccessors arrays - int i = 0; - foreach (var node in Graph.Vertices) - { - if (i >= _verticesCount) - break; + // Reset the visited, distances and predeccessors arrays + int i = 0; + foreach (var node in Graph.Vertices) + { + if (i >= _verticesCount) + break; - _visited[i] = false; - _distances[i] = INFINITY; - _predecessors[i] = -1; + _visited[i] = false; + _distances[i] = INFINITY; + _predecessors[i] = -1; - _nodesToIndices.Add(node, i); - _indicesToNodes.Add(i, node); + _nodesToIndices.Add(node, i); + _indicesToNodes.Add(i, node); - ++i; - } + ++i; } + } - /// - /// Privat helper. Breadth First Search from Single Source. - /// - private void _breadthFirstSearch(IGraph graph, T source) - { - // Set distance to current to zero - _distances[_nodesToIndices[source]] = 0; + /// + /// Privat helper. Breadth First Search from Single Source. + /// + private void _breadthFirstSearch(IGraph graph, T source) + { + // Set distance to current to zero + _distances[_nodesToIndices[source]] = 0; - // Set current to visited: true. - _visited[_nodesToIndices[source]] = true; + // Set current to visited: true. + _visited[_nodesToIndices[source]] = true; - var queue = new Queue(_verticesCount); - queue.Enqueue(source); + var queue = new Queue(_verticesCount); + queue.Enqueue(source); + + while (queue.Count > 0) + { + var current = queue.Dequeue(); + int indexOfCurrent = _nodesToIndices[current]; - while (queue.Count > 0) + foreach (var adjacent in graph.Neighbours(current)) { - var current = queue.Dequeue(); - int indexOfCurrent = _nodesToIndices[current]; + int indexOfAdjacent = _nodesToIndices[adjacent]; - foreach (var adjacent in graph.Neighbours(current)) + if (!_visited[indexOfAdjacent]) { - int indexOfAdjacent = _nodesToIndices[adjacent]; - - if (!_visited[indexOfAdjacent]) - { - _predecessors[indexOfAdjacent] = indexOfCurrent; - _distances[indexOfAdjacent] = _distances[indexOfCurrent] + 1; - _visited[indexOfAdjacent] = true; - - queue.Enqueue(adjacent); - } - }//end-foreach - }//end-while - } + _predecessors[indexOfAdjacent] = indexOfCurrent; + _distances[indexOfAdjacent] = _distances[indexOfCurrent] + 1; + _visited[indexOfAdjacent] = true; + + queue.Enqueue(adjacent); + } + }//end-foreach + }//end-while + } + + /// + /// Privat helper. Breadth First Search from Multiple Sources. + /// + private void _breadthFirstSearch(IGraph graph, IList sources) + { + // Define helper variables. + var queue = new Queue(_verticesCount); - /// - /// Privat helper. Breadth First Search from Multiple Sources. - /// - private void _breadthFirstSearch(IGraph graph, IList sources) + foreach (var source in sources) { - // Define helper variables. - var queue = new Queue(_verticesCount); + if (!graph.HasVertex(source)) + throw new Exception("Graph doesn't has a vertex '" + source + "'"); - foreach (var source in sources) - { - if (!graph.HasVertex(source)) - throw new Exception("Graph doesn't has a vertex '" + source + "'"); + int index = _nodesToIndices[source]; + _distances[index] = 0; + _visited[index] = true; + queue.Enqueue(source); + } - int index = _nodesToIndices[source]; - _distances[index] = 0; - _visited[index] = true; - queue.Enqueue(source); - } + while (queue.Count > 0) + { + var current = queue.Dequeue(); + int indexOfCurrent = _nodesToIndices[current]; - while (queue.Count > 0) + foreach (var adjacent in graph.Neighbours(current)) { - var current = queue.Dequeue(); - int indexOfCurrent = _nodesToIndices[current]; + int indexOfAdjacent = _nodesToIndices[adjacent]; - foreach (var adjacent in graph.Neighbours(current)) + if (!_visited[indexOfAdjacent]) { - int indexOfAdjacent = _nodesToIndices[adjacent]; - - if (!_visited[indexOfAdjacent]) - { - _predecessors[indexOfAdjacent] = indexOfCurrent; - _distances[indexOfAdjacent] = _distances[indexOfCurrent] + 1; - _visited[indexOfAdjacent] = true; - - queue.Enqueue(adjacent); - } - }//end-foreach - }//end-while - } + _predecessors[indexOfAdjacent] = indexOfCurrent; + _distances[indexOfAdjacent] = _distances[indexOfCurrent] + 1; + _visited[indexOfAdjacent] = true; - /// - /// Private helper. Checks optimality conditions for single source - /// - private bool checkOptimalityConditions(IGraph graph, T source) + queue.Enqueue(adjacent); + } + }//end-foreach + }//end-while + } + + /// + /// Private helper. Checks optimality conditions for single source + /// + private bool checkOptimalityConditions(IGraph graph, T source) + { + int indexOfSource = _nodesToIndices[source]; + + // check that the distance of s = 0 + if (_distances[indexOfSource] != 0) { - int indexOfSource = _nodesToIndices[source]; + Console.WriteLine("Distance of source '" + source + "' to itself = " + _distances[indexOfSource]); + return false; + } - // check that the distance of s = 0 - if (_distances[indexOfSource] != 0) - { - Console.WriteLine("Distance of source '" + source + "' to itself = " + _distances[indexOfSource]); - return false; - } + // check that for each edge v-w dist[w] <= dist[v] + 1 + // provided v is reachable from s + foreach (var node in graph.Vertices) + { + int v = _nodesToIndices[node]; - // check that for each edge v-w dist[w] <= dist[v] + 1 - // provided v is reachable from s - foreach (var node in graph.Vertices) + foreach (var adjacent in graph.Neighbours(node)) { - int v = _nodesToIndices[node]; + int w = _nodesToIndices[adjacent]; - foreach (var adjacent in graph.Neighbours(node)) + if (HasPathTo(node) != HasPathTo(adjacent)) { - int w = _nodesToIndices[adjacent]; - - if (HasPathTo(node) != HasPathTo(adjacent)) - { - Console.WriteLine("edge " + node + "-" + adjacent); - Console.WriteLine("hasPathTo(" + node + ") = " + HasPathTo(node)); - Console.WriteLine("hasPathTo(" + adjacent + ") = " + HasPathTo(adjacent)); - return false; - } - if (HasPathTo(node) && _distances[w] > _distances[v] + 1) - { - Console.WriteLine("edge " + node + "-" + adjacent); - Console.WriteLine("distanceTo[" + node + "] = " + _distances[v]); - Console.WriteLine("distanceTo[" + adjacent + "] = " + _distances[w]); - return false; - } + Console.WriteLine("edge " + node + "-" + adjacent); + Console.WriteLine("hasPathTo(" + node + ") = " + HasPathTo(node)); + Console.WriteLine("hasPathTo(" + adjacent + ") = " + HasPathTo(adjacent)); + return false; + } + if (HasPathTo(node) && _distances[w] > _distances[v] + 1) + { + Console.WriteLine("edge " + node + "-" + adjacent); + Console.WriteLine("distanceTo[" + node + "] = " + _distances[v]); + Console.WriteLine("distanceTo[" + adjacent + "] = " + _distances[w]); + return false; } } + } - // check that v = edgeTo[w] satisfies distTo[w] + distTo[v] + 1 - // provided v is reachable from source - foreach (var node in graph.Vertices) - { - int w = _nodesToIndices[node]; + // check that v = edgeTo[w] satisfies distTo[w] + distTo[v] + 1 + // provided v is reachable from source + foreach (var node in graph.Vertices) + { + int w = _nodesToIndices[node]; - if (!HasPathTo(node) || node.IsEqualTo(source)) - continue; + if (!HasPathTo(node) || node.IsEqualTo(source)) + continue; - int v = _predecessors[w]; + int v = _predecessors[w]; - if (_distances[w] != _distances[v] + 1) - { - Console.WriteLine("shortest path edge " + v + "-" + w); - Console.WriteLine("distanceTo[" + v + "] = " + _distances[v]); - Console.WriteLine("distanceTo[" + w + "] = " + _distances[w]); - return false; - } + if (_distances[w] != _distances[v] + 1) + { + Console.WriteLine("shortest path edge " + v + "-" + w); + Console.WriteLine("distanceTo[" + v + "] = " + _distances[v]); + Console.WriteLine("distanceTo[" + w + "] = " + _distances[w]); + return false; } - - return true; } + return true; + } - /************************************************************************************************************/ + /************************************************************************************************************/ - /// - /// Determines whether there is a path from the source vertex to this specified vertex. - /// - public bool HasPathTo(T destination) - { - if (!_nodesToIndices.ContainsKey(destination)) - throw new Exception("Graph doesn't have the specified vertex."); - int dstIndex = _nodesToIndices[destination]; - return _visited[dstIndex]; - } + /// + /// Determines whether there is a path from the source vertex to this specified vertex. + /// + public bool HasPathTo(T destination) + { + if (!_nodesToIndices.ContainsKey(destination)) + throw new Exception("Graph doesn't have the specified vertex."); - /// - /// Returns the distance between the source vertex and the specified vertex. - /// - public long DistanceTo(T destination) - { - if (!_nodesToIndices.ContainsKey(destination)) - throw new Exception("Graph doesn't have the specified vertex."); + int dstIndex = _nodesToIndices[destination]; + return _visited[dstIndex]; + } - int dstIndex = _nodesToIndices[destination]; - return _distances[dstIndex]; - } + /// + /// Returns the distance between the source vertex and the specified vertex. + /// + public long DistanceTo(T destination) + { + if (!_nodesToIndices.ContainsKey(destination)) + throw new Exception("Graph doesn't have the specified vertex."); - /// - /// Returns an enumerable collection of nodes that specify the shortest path from the source vertex to the destination vertex. - /// - public IEnumerable ShortestPathTo(T destination) - { - if (!_nodesToIndices.ContainsKey(destination)) - throw new Exception("Graph doesn't have the specified vertex."); - if (!HasPathTo(destination)) - return null; + int dstIndex = _nodesToIndices[destination]; + return _distances[dstIndex]; + } - int dstIndex = _nodesToIndices[destination]; - var stack = new DataStructures.Lists.Stack(); + /// + /// Returns an enumerable collection of nodes that specify the shortest path from the source vertex to the destination vertex. + /// + public IEnumerable ShortestPathTo(T destination) + { + if (!_nodesToIndices.ContainsKey(destination)) + throw new Exception("Graph doesn't have the specified vertex."); + if (!HasPathTo(destination)) + return null; - int index; - for (index = dstIndex; _distances[index] != 0; index = _predecessors[index]) - stack.Push(_indicesToNodes[index]); + int dstIndex = _nodesToIndices[destination]; + var stack = new DataStructures.Lists.Stack(); - // Push the source vertex + int index; + for (index = dstIndex; _distances[index] != 0; index = _predecessors[index]) stack.Push(_indicesToNodes[index]); - return stack; - } + // Push the source vertex + stack.Push(_indicesToNodes[index]); + return stack; } -} - +} \ No newline at end of file diff --git a/Algorithms/Graphs/ConnectedComponents.cs b/Algorithms/Graphs/ConnectedComponents.cs index 3c755cc3..01d4f02b 100644 --- a/Algorithms/Graphs/ConnectedComponents.cs +++ b/Algorithms/Graphs/ConnectedComponents.cs @@ -12,62 +12,60 @@ using DataStructures.Graphs; -namespace Algorithms.Graphs +namespace Algorithms.Graphs; + +public static class ConnectedComponents { - public static class ConnectedComponents + /// + /// Private helper. Discovers a connected component and return from a source vertex in a graph. + /// + private static List _bfsConnectedComponent(IGraph graph, TVertex source, ref HashSet visited) where TVertex : IComparable { - /// - /// Private helper. Discovers a connected component and return from a source vertex in a graph. - /// - private static List _bfsConnectedComponent(IGraph graph, TVertex source, ref HashSet visited) where TVertex : IComparable - { - var component = new List(); - var queue = new Queue(); + var component = new List(); + var queue = new Queue(); - queue.Enqueue(source); + queue.Enqueue(source); - while (queue.Count > 0) - { - var current = queue.Dequeue(); + while (queue.Count > 0) + { + var current = queue.Dequeue(); - if (!visited.Contains(current)) - { - component.Add(current); - visited.Add(current); + if (!visited.Contains(current)) + { + component.Add(current); + visited.Add(current); - foreach (var adjacent in graph.Neighbours(current)) - if (!visited.Contains(adjacent)) - queue.Enqueue(adjacent); - } + foreach (var adjacent in graph.Neighbours(current)) + if (!visited.Contains(adjacent)) + queue.Enqueue(adjacent); } - - return component; } + return component; + } - /// - /// Return the the connected components in graph as list of lists of nodes. Each list represents a connected component. - /// - public static List> Compute(IGraph Graph) where TVertex : IComparable - { - var components = new List>(); - var visited = new HashSet(); - - // Validate the graph parameter - if (Graph == null) - throw new ArgumentNullException(); - if (Graph.IsDirected == true) - throw new NotSupportedException("Directed Graphs are not supported."); - if(Graph.VerticesCount == 0) - return components; - // Get connected components using BFS - foreach(var vertex in Graph.Vertices) - if(!visited.Contains(vertex)) - components.Add(_bfsConnectedComponent(Graph, vertex, ref visited)); + /// + /// Return the the connected components in graph as list of lists of nodes. Each list represents a connected component. + /// + public static List> Compute(IGraph Graph) where TVertex : IComparable + { + var components = new List>(); + var visited = new HashSet(); + // Validate the graph parameter + if (Graph == null) + throw new ArgumentNullException(); + if (Graph.IsDirected == true) + throw new NotSupportedException("Directed Graphs are not supported."); + if(Graph.VerticesCount == 0) return components; - } - } -} + // Get connected components using BFS + foreach(var vertex in Graph.Vertices) + if(!visited.Contains(vertex)) + components.Add(_bfsConnectedComponent(Graph, vertex, ref visited)); + + return components; + } +} \ No newline at end of file diff --git a/Algorithms/Graphs/CyclesDetector.cs b/Algorithms/Graphs/CyclesDetector.cs index 3e99fba1..4ae53557 100644 --- a/Algorithms/Graphs/CyclesDetector.cs +++ b/Algorithms/Graphs/CyclesDetector.cs @@ -7,109 +7,107 @@ using Algorithms.Common; using DataStructures.Graphs; -namespace Algorithms.Graphs +namespace Algorithms.Graphs; + +/// +/// Implements Cycles Detection in Graphs +/// +public static class CyclesDetector { /// - /// Implements Cycles Detection in Graphs + /// [Undirected DFS Forest]. + /// Helper function used to decide whether the graph explored from a specific vertex contains a cycle. /// - public static class CyclesDetector + /// The graph to explore. + /// The vertex to explore graph from. + /// The predecessor node to the vertex we are exploring the graph from. + /// A hash set of the explored nodes so far. + /// True if there is a cycle; otherwise, false. + private static bool _isUndirectedCyclic(IGraph graph, T source, object parent, ref HashSet visited) where T : IComparable { - /// - /// [Undirected DFS Forest]. - /// Helper function used to decide whether the graph explored from a specific vertex contains a cycle. - /// - /// The graph to explore. - /// The vertex to explore graph from. - /// The predecessor node to the vertex we are exploring the graph from. - /// A hash set of the explored nodes so far. - /// True if there is a cycle; otherwise, false. - private static bool _isUndirectedCyclic(IGraph graph, T source, object parent, ref HashSet visited) where T : IComparable + if (!visited.Contains(source)) { - if (!visited.Contains(source)) + // Mark the current node as visited + visited.Add(source); + + // Recur for all the vertices adjacent to this vertex + foreach (var adjacent in graph.Neighbours(source)) { - // Mark the current node as visited - visited.Add(source); - - // Recur for all the vertices adjacent to this vertex - foreach (var adjacent in graph.Neighbours(source)) - { - // If an adjacent node was not visited, then check the DFS forest of the adjacent for UNdirected cycles. - if (!visited.Contains(adjacent) && _isUndirectedCyclic(graph, adjacent, source, ref visited)) - return true; - - // If an adjacent is visited and NOT parent of current vertex, then there is a cycle. - if (parent != (object)null && !adjacent.IsEqualTo((T)parent)) - return true; - } - } + // If an adjacent node was not visited, then check the DFS forest of the adjacent for UNdirected cycles. + if (!visited.Contains(adjacent) && _isUndirectedCyclic(graph, adjacent, source, ref visited)) + return true; - return false; + // If an adjacent is visited and NOT parent of current vertex, then there is a cycle. + if (parent != (object)null && !adjacent.IsEqualTo((T)parent)) + return true; + } } - /// - /// [Directed DFS Forest] - /// Helper function used to decide whether the graph explored from a specific vertex contains a cycle. - /// - /// The graph to explore. - /// The vertex to explore graph from. - /// The predecessor node to the vertex we are exploring the graph from. - /// A hash set of the explored nodes so far. - /// A set of element that are currently being processed. - /// True if there is a cycle; otherwise, false. - private static bool _isDirectedCyclic(IGraph graph, T source, ref HashSet visited, ref HashSet recursionStack) where T : IComparable + return false; + } + + /// + /// [Directed DFS Forest] + /// Helper function used to decide whether the graph explored from a specific vertex contains a cycle. + /// + /// The graph to explore. + /// The vertex to explore graph from. + /// The predecessor node to the vertex we are exploring the graph from. + /// A hash set of the explored nodes so far. + /// A set of element that are currently being processed. + /// True if there is a cycle; otherwise, false. + private static bool _isDirectedCyclic(IGraph graph, T source, ref HashSet visited, ref HashSet recursionStack) where T : IComparable + { + if (!visited.Contains(source)) { - if (!visited.Contains(source)) + // Mark the current node as visited and add it to the recursion stack + visited.Add(source); + recursionStack.Add(source); + + // Recur for all the vertices adjacent to this vertex + foreach (var adjacent in graph.Neighbours(source)) { - // Mark the current node as visited and add it to the recursion stack - visited.Add(source); - recursionStack.Add(source); - - // Recur for all the vertices adjacent to this vertex - foreach (var adjacent in graph.Neighbours(source)) - { - // If an adjacent node was not visited, then check the DFS forest of the adjacent for directed cycles. - if (!visited.Contains(adjacent) && _isDirectedCyclic(graph, adjacent, ref visited, ref recursionStack)) - return true; - - // If an adjacent is visited and is on the recursion stack then there is a cycle. - if (recursionStack.Contains(adjacent)) - return true; - } - } + // If an adjacent node was not visited, then check the DFS forest of the adjacent for directed cycles. + if (!visited.Contains(adjacent) && _isDirectedCyclic(graph, adjacent, ref visited, ref recursionStack)) + return true; - // Remove the source vertex from the recursion stack - recursionStack.Remove(source); - return false; + // If an adjacent is visited and is on the recursion stack then there is a cycle. + if (recursionStack.Contains(adjacent)) + return true; + } } + // Remove the source vertex from the recursion stack + recursionStack.Remove(source); + return false; + } - /// - /// Returns true if Graph has cycle. - /// - public static bool IsCyclic(IGraph Graph) where T : IComparable - { - if (Graph == null) - throw new ArgumentNullException(); - var visited = new HashSet(); - var recursionStack = new HashSet(); + /// + /// Returns true if Graph has cycle. + /// + public static bool IsCyclic(IGraph Graph) where T : IComparable + { + if (Graph == null) + throw new ArgumentNullException(); - if (Graph.IsDirected) - { - foreach (var vertex in Graph.Vertices) - if (_isDirectedCyclic(Graph, vertex, ref visited, ref recursionStack)) - return true; - } - else - { - foreach (var vertex in Graph.Vertices) - if (_isUndirectedCyclic(Graph, vertex, null, ref visited)) - return true; - } + var visited = new HashSet(); + var recursionStack = new HashSet(); - return false; + if (Graph.IsDirected) + { + foreach (var vertex in Graph.Vertices) + if (_isDirectedCyclic(Graph, vertex, ref visited, ref recursionStack)) + return true; + } + else + { + foreach (var vertex in Graph.Vertices) + if (_isUndirectedCyclic(Graph, vertex, null, ref visited)) + return true; } + return false; } -} +} \ No newline at end of file diff --git a/Algorithms/Graphs/DepthFirstSearcher.cs b/Algorithms/Graphs/DepthFirstSearcher.cs index b0129117..018ea6c9 100644 --- a/Algorithms/Graphs/DepthFirstSearcher.cs +++ b/Algorithms/Graphs/DepthFirstSearcher.cs @@ -14,151 +14,148 @@ using DataStructures.Graphs; -namespace Algorithms.Graphs +namespace Algorithms.Graphs; + +public static class DepthFirstSearcher { - public static class DepthFirstSearcher + /// + /// DFS Recursive Helper function. + /// Visits the neighbors of a given vertex recusively, and applies the given Action to each one of them. + /// + private static void _visitNeighbors(T Vertex, ref IGraph Graph, ref Dictionary Parents, Action Action) where T : IComparable { - /// - /// DFS Recursive Helper function. - /// Visits the neighbors of a given vertex recusively, and applies the given Action to each one of them. - /// - private static void _visitNeighbors(T Vertex, ref IGraph Graph, ref Dictionary Parents, Action Action) where T : IComparable + foreach (var adjacent in Graph.Neighbours(Vertex)) { - foreach (var adjacent in Graph.Neighbours(Vertex)) + if (!Parents.ContainsKey(adjacent)) { - if (!Parents.ContainsKey(adjacent)) - { - // DFS VISIT NODE - Action(adjacent); + // DFS VISIT NODE + Action(adjacent); - // Save adjacents parent into dictionary - Parents.Add(adjacent, Vertex); + // Save adjacents parent into dictionary + Parents.Add(adjacent, Vertex); - // Recusively visit adjacent nodes - _visitNeighbors(adjacent, ref Graph, ref Parents, Action); - } + // Recusively visit adjacent nodes + _visitNeighbors(adjacent, ref Graph, ref Parents, Action); } } + } - /// - /// Recursive DFS Implementation with helper. - /// Traverses all the nodes in a graph starting from a specific node, applying the passed action to every node. - /// - public static void VisitAll(ref IGraph Graph, T StartVertex, Action Action) where T : IComparable - { - // Check if graph is empty - if (Graph.VerticesCount == 0) - throw new Exception("Graph is empty!"); + /// + /// Recursive DFS Implementation with helper. + /// Traverses all the nodes in a graph starting from a specific node, applying the passed action to every node. + /// + public static void VisitAll(ref IGraph Graph, T StartVertex, Action Action) where T : IComparable + { + // Check if graph is empty + if (Graph.VerticesCount == 0) + throw new Exception("Graph is empty!"); - // Check if graph has the starting vertex - if (!Graph.HasVertex(StartVertex)) - throw new Exception("Starting vertex doesn't belong to graph."); + // Check if graph has the starting vertex + if (!Graph.HasVertex(StartVertex)) + throw new Exception("Starting vertex doesn't belong to graph."); - var parents = new Dictionary(Graph.VerticesCount); // keeps track of visited nodes and tree-edges + var parents = new Dictionary(Graph.VerticesCount); // keeps track of visited nodes and tree-edges - foreach (var vertex in Graph.Neighbours(StartVertex)) + foreach (var vertex in Graph.Neighbours(StartVertex)) + { + if (!parents.ContainsKey(vertex)) { - if (!parents.ContainsKey(vertex)) - { - // DFS VISIT NODE - Action(vertex); + // DFS VISIT NODE + Action(vertex); - // Add to parents dictionary - parents.Add(vertex, null); + // Add to parents dictionary + parents.Add(vertex, null); - // Visit neighbors using recusrive helper - _visitNeighbors(vertex, ref Graph, ref parents, Action); - } + // Visit neighbors using recusrive helper + _visitNeighbors(vertex, ref Graph, ref parents, Action); } } + } - /// - /// Iterative DFS Implementation. - /// Given a starting node, dfs the graph and print the nodes as they get visited. - /// - public static void PrintAll(IGraph Graph, T StartVertex) where T : IComparable - { - // Check if graph is empty - if (Graph.VerticesCount == 0) - throw new Exception("Graph is empty!"); + /// + /// Iterative DFS Implementation. + /// Given a starting node, dfs the graph and print the nodes as they get visited. + /// + public static void PrintAll(IGraph Graph, T StartVertex) where T : IComparable + { + // Check if graph is empty + if (Graph.VerticesCount == 0) + throw new Exception("Graph is empty!"); + + // Check if graph has the starting vertex + if (!Graph.HasVertex(StartVertex)) + throw new Exception("Starting vertex doesn't belong to graph."); - // Check if graph has the starting vertex - if (!Graph.HasVertex(StartVertex)) - throw new Exception("Starting vertex doesn't belong to graph."); + var visited = new HashSet(); + var stack = new Stack(Graph.VerticesCount); - var visited = new HashSet(); - var stack = new Stack(Graph.VerticesCount); + stack.Push(StartVertex); - stack.Push(StartVertex); + while (stack.Count > 0) + { + var current = stack.Pop(); - while (stack.Count > 0) + if (!visited.Contains(current)) { - var current = stack.Pop(); - - if (!visited.Contains(current)) - { - // DFS VISIT NODE STEP - Console.Write(String.Format("({0}) ", current)); - visited.Add(current); - - // Get the adjacent nodes of current - foreach (var adjacent in Graph.Neighbours(current)) - if (!visited.Contains(adjacent)) - stack.Push(adjacent); - } + // DFS VISIT NODE STEP + Console.Write(String.Format("({0}) ", current)); + visited.Add(current); + + // Get the adjacent nodes of current + foreach (var adjacent in Graph.Neighbours(current)) + if (!visited.Contains(adjacent)) + stack.Push(adjacent); } - } - /// - /// Iterative DFS Implementation. - /// Given a predicate function and a starting node, this function searches the nodes of the graph for a first match. - /// - public static T FindFirstMatch(IGraph Graph, T StartVertex, Predicate Match) where T : IComparable - { - // Check if graph is empty - if (Graph.VerticesCount == 0) - throw new Exception("Graph is empty!"); + } + + /// + /// Iterative DFS Implementation. + /// Given a predicate function and a starting node, this function searches the nodes of the graph for a first match. + /// + public static T FindFirstMatch(IGraph Graph, T StartVertex, Predicate Match) where T : IComparable + { + // Check if graph is empty + if (Graph.VerticesCount == 0) + throw new Exception("Graph is empty!"); - // Check if graph has the starting vertex - if (!Graph.HasVertex(StartVertex)) - throw new Exception("Starting vertex doesn't belong to graph."); + // Check if graph has the starting vertex + if (!Graph.HasVertex(StartVertex)) + throw new Exception("Starting vertex doesn't belong to graph."); - var stack = new Stack(); - var parents = new Dictionary(Graph.VerticesCount); // keeps track of visited nodes and tree-edges + var stack = new Stack(); + var parents = new Dictionary(Graph.VerticesCount); // keeps track of visited nodes and tree-edges - object currentParent = null; - stack.Push(StartVertex); + object currentParent = null; + stack.Push(StartVertex); - while (stack.Count > 0) + while (stack.Count > 0) + { + var current = stack.Pop(); + + // Skip loop if node was already visited + if (!parents.ContainsKey(current)) { - var current = stack.Pop(); - - // Skip loop if node was already visited - if (!parents.ContainsKey(current)) - { - // Save its parent into the dictionary - // Mark it as visited - parents.Add(current, currentParent); - - // DFS VISIT NODE STEP - if (Match(current)) - return current; - - // Get currents adjacent nodes (might add already visited nodes). - foreach (var adjacent in Graph.Neighbours(current)) - if (!parents.ContainsKey(adjacent)) - stack.Push(adjacent); - - // Mark current as the father of its adjacents. This helps keep track of tree-nodes. - currentParent = current; - } - }//end-while - - throw new Exception("Item was not found!"); - } + // Save its parent into the dictionary + // Mark it as visited + parents.Add(current, currentParent); - } + // DFS VISIT NODE STEP + if (Match(current)) + return current; + + // Get currents adjacent nodes (might add already visited nodes). + foreach (var adjacent in Graph.Neighbours(current)) + if (!parents.ContainsKey(adjacent)) + stack.Push(adjacent); -} + // Mark current as the father of its adjacents. This helps keep track of tree-nodes. + currentParent = current; + } + }//end-while + + throw new Exception("Item was not found!"); + } +} \ No newline at end of file diff --git a/Algorithms/Graphs/DijkstraAllPairsShortestPaths.cs b/Algorithms/Graphs/DijkstraAllPairsShortestPaths.cs index 11d80c7e..0a722744 100644 --- a/Algorithms/Graphs/DijkstraAllPairsShortestPaths.cs +++ b/Algorithms/Graphs/DijkstraAllPairsShortestPaths.cs @@ -8,72 +8,70 @@ using System.Collections.Generic; using DataStructures.Graphs; -namespace Algorithms.Graphs +namespace Algorithms.Graphs; + +public class DijkstraAllPairsShortestPaths + where TGraph : IGraph, IWeightedGraph + where TVertex : IComparable { - public class DijkstraAllPairsShortestPaths - where TGraph : IGraph, IWeightedGraph - where TVertex : IComparable - { - /// - /// INSTANCE VARIABLES - /// - Dictionary> _allPairsDjkstra; + /// + /// INSTANCE VARIABLES + /// + Dictionary> _allPairsDjkstra; - /// - /// CONSTRUCTOR - /// - public DijkstraAllPairsShortestPaths(TGraph Graph) - { - if (Graph == null) - throw new ArgumentNullException(); + /// + /// CONSTRUCTOR + /// + public DijkstraAllPairsShortestPaths(TGraph Graph) + { + if (Graph == null) + throw new ArgumentNullException(); - // Initialize the all pairs dictionary - _allPairsDjkstra = new Dictionary>(); + // Initialize the all pairs dictionary + _allPairsDjkstra = new Dictionary>(); - var vertices = Graph.Vertices; + var vertices = Graph.Vertices; - foreach (var vertex in vertices) - { - var dijkstra = new DijkstraShortestPaths(Graph, vertex); - _allPairsDjkstra.Add(vertex, dijkstra); - } + foreach (var vertex in vertices) + { + var dijkstra = new DijkstraShortestPaths(Graph, vertex); + _allPairsDjkstra.Add(vertex, dijkstra); } + } - /// - /// Determines whether there is a path from source vertex to destination vertex. - /// - public bool HasPath(TVertex source, TVertex destination) - { - if (!_allPairsDjkstra.ContainsKey(source) || !_allPairsDjkstra.ContainsKey(destination)) - throw new Exception("Either one of the vertices or both of them don't belong to Graph."); - - return _allPairsDjkstra[source].HasPathTo(destination); - } + /// + /// Determines whether there is a path from source vertex to destination vertex. + /// + public bool HasPath(TVertex source, TVertex destination) + { + if (!_allPairsDjkstra.ContainsKey(source) || !_allPairsDjkstra.ContainsKey(destination)) + throw new Exception("Either one of the vertices or both of them don't belong to Graph."); - /// - /// Returns the distance between source vertex and destination vertex. - /// - public long PathDistance(TVertex source, TVertex destination) - { - if (!_allPairsDjkstra.ContainsKey(source) || !_allPairsDjkstra.ContainsKey(destination)) - throw new Exception("Either one of the vertices or both of them don't belong to Graph."); + return _allPairsDjkstra[source].HasPathTo(destination); + } - return _allPairsDjkstra[source].DistanceTo(destination); - } + /// + /// Returns the distance between source vertex and destination vertex. + /// + public long PathDistance(TVertex source, TVertex destination) + { + if (!_allPairsDjkstra.ContainsKey(source) || !_allPairsDjkstra.ContainsKey(destination)) + throw new Exception("Either one of the vertices or both of them don't belong to Graph."); - /// - /// Returns an enumerable collection of nodes that specify the shortest path from source vertex to destination vertex. - /// - public IEnumerable ShortestPath(TVertex source, TVertex destination) - { - if (!_allPairsDjkstra.ContainsKey(source) || !_allPairsDjkstra.ContainsKey(destination)) - throw new Exception("Either one of the vertices or both of them don't belong to Graph."); + return _allPairsDjkstra[source].DistanceTo(destination); + } - return _allPairsDjkstra[source].ShortestPathTo(destination); - } + /// + /// Returns an enumerable collection of nodes that specify the shortest path from source vertex to destination vertex. + /// + public IEnumerable ShortestPath(TVertex source, TVertex destination) + { + if (!_allPairsDjkstra.ContainsKey(source) || !_allPairsDjkstra.ContainsKey(destination)) + throw new Exception("Either one of the vertices or both of them don't belong to Graph."); + return _allPairsDjkstra[source].ShortestPathTo(destination); } -} +} \ No newline at end of file diff --git a/Algorithms/Graphs/DijkstraShortestPaths.cs b/Algorithms/Graphs/DijkstraShortestPaths.cs index c72f7719..c8a16994 100644 --- a/Algorithms/Graphs/DijkstraShortestPaths.cs +++ b/Algorithms/Graphs/DijkstraShortestPaths.cs @@ -4,164 +4,163 @@ using System.Collections.Generic; using System.Linq; -namespace Algorithms.Graphs +namespace Algorithms.Graphs; + +/// +/// Computes Dijkstra's Shortest-Paths for Directed Weighted Graphs from a single-source to all destinations. +/// +public class DijkstraShortestPaths + where TGraph : IGraph, IWeightedGraph + where TVertex : IComparable { - /// - /// Computes Dijkstra's Shortest-Paths for Directed Weighted Graphs from a single-source to all destinations. - /// - public class DijkstraShortestPaths - where TGraph : IGraph, IWeightedGraph - where TVertex : IComparable - { - private const long Infinity = long.MaxValue; - private const int NilPredecessor = -1; + private const long Infinity = long.MaxValue; + private const int NilPredecessor = -1; - private long[] _distances; - private int[] _predecessors; + private long[] _distances; + private int[] _predecessors; - private Dictionary _nodesToIndices; - private Dictionary _indicesToNodes; + private Dictionary _nodesToIndices; + private Dictionary _indicesToNodes; - private MinPriorityQueue _minPriorityQueue; + private MinPriorityQueue _minPriorityQueue; - private readonly TGraph _graph; - private readonly TVertex _source; + private readonly TGraph _graph; + private readonly TVertex _source; - public DijkstraShortestPaths(TGraph graph, TVertex source) - { - if (graph == null) - throw new ArgumentNullException(nameof(graph)); + public DijkstraShortestPaths(TGraph graph, TVertex source) + { + if (graph == null) + throw new ArgumentNullException(nameof(graph)); - if (source == null) - throw new ArgumentNullException(nameof(source)); + if (source == null) + throw new ArgumentNullException(nameof(source)); - if (!graph.HasVertex(source)) - throw new ArgumentException("The source vertex doesn't belong to graph."); + if (!graph.HasVertex(source)) + throw new ArgumentException("The source vertex doesn't belong to graph."); - if (graph.Edges.Any(edge => edge.Weight < 0)) - throw new ArgumentException("Negative edge weight detected."); + if (graph.Edges.Any(edge => edge.Weight < 0)) + throw new ArgumentException("Negative edge weight detected."); - _graph = graph; - _source = source; + _graph = graph; + _source = source; - _initialize(); - _dijkstra(); - } + _initialize(); + _dijkstra(); + } - /// - /// The Dijkstra's algorithm. - /// - private void _dijkstra() + /// + /// The Dijkstra's algorithm. + /// + private void _dijkstra() + { + while (!_minPriorityQueue.IsEmpty) { - while (!_minPriorityQueue.IsEmpty) + var currentVertex = _minPriorityQueue.DequeueMin(); + var currentVertexIndex = _nodesToIndices[currentVertex]; + + var outgoingEdges = _graph.OutgoingEdges(currentVertex); + foreach (var outgoingEdge in outgoingEdges) { - var currentVertex = _minPriorityQueue.DequeueMin(); - var currentVertexIndex = _nodesToIndices[currentVertex]; + var adjacentIndex = _nodesToIndices[outgoingEdge.Destination]; + var delta = _distances[currentVertexIndex] != Infinity ? _distances[currentVertexIndex] + outgoingEdge.Weight : Infinity; - var outgoingEdges = _graph.OutgoingEdges(currentVertex); - foreach (var outgoingEdge in outgoingEdges) + if (delta < _distances[adjacentIndex]) { - var adjacentIndex = _nodesToIndices[outgoingEdge.Destination]; - var delta = _distances[currentVertexIndex] != Infinity ? _distances[currentVertexIndex] + outgoingEdge.Weight : Infinity; + _distances[adjacentIndex] = delta; + _predecessors[adjacentIndex] = currentVertexIndex; - if (delta < _distances[adjacentIndex]) + if (_minPriorityQueue.Contains(outgoingEdge.Destination)) + { + _minPriorityQueue.UpdatePriority(outgoingEdge.Destination, delta); + } + else { - _distances[adjacentIndex] = delta; - _predecessors[adjacentIndex] = currentVertexIndex; - - if (_minPriorityQueue.Contains(outgoingEdge.Destination)) - { - _minPriorityQueue.UpdatePriority(outgoingEdge.Destination, delta); - } - else - { - _minPriorityQueue.Enqueue(outgoingEdge.Destination, delta); - } + _minPriorityQueue.Enqueue(outgoingEdge.Destination, delta); } } } } + } - private void _initialize() - { - var verticesCount = _graph.VerticesCount; + private void _initialize() + { + var verticesCount = _graph.VerticesCount; - _distances = new long[verticesCount]; - _predecessors = new int[verticesCount]; + _distances = new long[verticesCount]; + _predecessors = new int[verticesCount]; - _nodesToIndices = new Dictionary(); - _indicesToNodes = new Dictionary(); - _minPriorityQueue = new MinPriorityQueue((uint)verticesCount); + _nodesToIndices = new Dictionary(); + _indicesToNodes = new Dictionary(); + _minPriorityQueue = new MinPriorityQueue((uint)verticesCount); - var vertices = _graph.Vertices.ToList(); - for (int i = 0; i < verticesCount; i++) + var vertices = _graph.Vertices.ToList(); + for (int i = 0; i < verticesCount; i++) + { + if (_source.Equals(vertices[i])) { - if (_source.Equals(vertices[i])) - { - _distances[i] = 0; - _predecessors[i] = 0; - } - else - { - _distances[i] = Infinity; - _predecessors[i] = NilPredecessor; - } + _distances[i] = 0; + _predecessors[i] = 0; + } + else + { + _distances[i] = Infinity; + _predecessors[i] = NilPredecessor; + } - _minPriorityQueue.Enqueue(vertices[i], _distances[i]); + _minPriorityQueue.Enqueue(vertices[i], _distances[i]); - _nodesToIndices.Add(vertices[i], i); - _indicesToNodes.Add(i, vertices[i]); - } + _nodesToIndices.Add(vertices[i], i); + _indicesToNodes.Add(i, vertices[i]); } + } - /// - /// Determines whether there is a path from the source vertex to this specified vertex. - /// - public bool HasPathTo(TVertex destination) - { - if (!_nodesToIndices.ContainsKey(destination)) - throw new ArgumentException("Graph doesn't have the specified vertex."); + /// + /// Determines whether there is a path from the source vertex to this specified vertex. + /// + public bool HasPathTo(TVertex destination) + { + if (!_nodesToIndices.ContainsKey(destination)) + throw new ArgumentException("Graph doesn't have the specified vertex."); - var index = _nodesToIndices[destination]; - return _distances[index] != Infinity; - } + var index = _nodesToIndices[destination]; + return _distances[index] != Infinity; + } - /// - /// Returns the distance between the source vertex and the specified vertex. - /// - public long DistanceTo(TVertex destination) - { - if (!_nodesToIndices.ContainsKey(destination)) - throw new ArgumentException("Graph doesn't have the specified vertex."); + /// + /// Returns the distance between the source vertex and the specified vertex. + /// + public long DistanceTo(TVertex destination) + { + if (!_nodesToIndices.ContainsKey(destination)) + throw new ArgumentException("Graph doesn't have the specified vertex."); - var index = _nodesToIndices[destination]; - return _distances[index]; - } + var index = _nodesToIndices[destination]; + return _distances[index]; + } - /// - /// Returns an enumerable collection of nodes that specify the shortest path from the source vertex to the destination vertex. - /// - public IEnumerable ShortestPathTo(TVertex destination) - { - if (!_nodesToIndices.ContainsKey(destination)) - throw new ArgumentException("Graph doesn't have the specified vertex."); + /// + /// Returns an enumerable collection of nodes that specify the shortest path from the source vertex to the destination vertex. + /// + public IEnumerable ShortestPathTo(TVertex destination) + { + if (!_nodesToIndices.ContainsKey(destination)) + throw new ArgumentException("Graph doesn't have the specified vertex."); - if (!HasPathTo(destination)) - { - return null; - } + if (!HasPathTo(destination)) + { + return null; + } - var dstIndex = _nodesToIndices[destination]; - var stack = new Stack(); + var dstIndex = _nodesToIndices[destination]; + var stack = new Stack(); - int index; - for (index = dstIndex; _distances[index] != 0; index = _predecessors[index]) - { - stack.Push(_indicesToNodes[index]); - } + int index; + for (index = dstIndex; _distances[index] != 0; index = _predecessors[index]) + { stack.Push(_indicesToNodes[index]); - - return stack; } + stack.Push(_indicesToNodes[index]); + + return stack; } -} +} \ No newline at end of file diff --git a/Algorithms/Graphs/TopologicalSorter.cs b/Algorithms/Graphs/TopologicalSorter.cs index 25eebb68..6c1d0ad6 100644 --- a/Algorithms/Graphs/TopologicalSorter.cs +++ b/Algorithms/Graphs/TopologicalSorter.cs @@ -7,44 +7,43 @@ using System.Collections.Generic; using DataStructures.Graphs; -namespace Algorithms.Graphs +namespace Algorithms.Graphs; + +public static class TopologicalSorter { - public static class TopologicalSorter + /// + /// Private recursive helper. + /// + private static void _topoSortHelper(IGraph graph, T source, ref DataStructures.Lists.Stack topoSortStack, ref HashSet visited) where T : IComparable + { + visited.Add(source); + + foreach (var adjacent in graph.Neighbours(source)) + if (!visited.Contains(adjacent)) + _topoSortHelper(graph, adjacent, ref topoSortStack, ref visited); + + topoSortStack.Push(source); + } + + + /// + /// The Topological Sorting algorithm + /// + public static IEnumerable Sort(IGraph Graph) where T : IComparable { - /// - /// Private recursive helper. - /// - private static void _topoSortHelper(IGraph graph, T source, ref DataStructures.Lists.Stack topoSortStack, ref HashSet visited) where T : IComparable - { - visited.Add(source); - - foreach (var adjacent in graph.Neighbours(source)) - if (!visited.Contains(adjacent)) - _topoSortHelper(graph, adjacent, ref topoSortStack, ref visited); - - topoSortStack.Push(source); - } - - - /// - /// The Topological Sorting algorithm - /// - public static IEnumerable Sort(IGraph Graph) where T : IComparable - { - // If the graph is either null or is not a DAG, throw exception. - if (Graph == null) - throw new ArgumentNullException(); - if (!Graph.IsDirected || CyclesDetector.IsCyclic(Graph)) - throw new Exception("The graph is not a DAG."); - - var visited = new HashSet(); - var topoSortStack = new DataStructures.Lists.Stack(); - - foreach (var vertex in Graph.Vertices) - if (!visited.Contains(vertex)) - _topoSortHelper(Graph, vertex, ref topoSortStack, ref visited); - - return topoSortStack; - } + // If the graph is either null or is not a DAG, throw exception. + if (Graph == null) + throw new ArgumentNullException(); + if (!Graph.IsDirected || CyclesDetector.IsCyclic(Graph)) + throw new Exception("The graph is not a DAG."); + + var visited = new HashSet(); + var topoSortStack = new DataStructures.Lists.Stack(); + + foreach (var vertex in Graph.Vertices) + if (!visited.Contains(vertex)) + _topoSortHelper(Graph, vertex, ref topoSortStack, ref visited); + + return topoSortStack; } -} +} \ No newline at end of file diff --git a/Algorithms/Numeric/BinomialCoefficients.cs b/Algorithms/Numeric/BinomialCoefficients.cs index 4affcc33..81d8f807 100644 --- a/Algorithms/Numeric/BinomialCoefficients.cs +++ b/Algorithms/Numeric/BinomialCoefficients.cs @@ -1,33 +1,32 @@ using System.Collections.Generic; using System.Numerics; -namespace Algorithms.Numeric +namespace Algorithms.Numeric; + +public static class BinomialCoefficients { - public static class BinomialCoefficients - { - private static readonly Dictionary Cache = new Dictionary(); + private static readonly Dictionary Cache = new Dictionary(); - /// - /// Calculate binomial coefficients, C(n, k). - /// - /// - /// - public static BigInteger Calculate(uint n) - { - return Factorial(2 * n) / (Factorial(n) * Factorial(n + 1)); - } + /// + /// Calculate binomial coefficients, C(n, k). + /// + /// + /// + public static BigInteger Calculate(uint n) + { + return Factorial(2 * n) / (Factorial(n) * Factorial(n + 1)); + } - private static BigInteger Factorial(uint n) + private static BigInteger Factorial(uint n) + { + if (n <= 1) + return 1; + if (Cache.ContainsKey(n)) { - if (n <= 1) - return 1; - if (Cache.ContainsKey(n)) - { - return Cache[n]; - } - var value = n * Factorial(n - 1); - Cache[n] = value; - return value; + return Cache[n]; } + var value = n * Factorial(n - 1); + Cache[n] = value; + return value; } } \ No newline at end of file diff --git a/Algorithms/Numeric/CatalanNumbers.cs b/Algorithms/Numeric/CatalanNumbers.cs index 3aa698c0..e805dd4d 100644 --- a/Algorithms/Numeric/CatalanNumbers.cs +++ b/Algorithms/Numeric/CatalanNumbers.cs @@ -8,84 +8,83 @@ using System.Collections.Generic; using System.Numerics; -namespace Algorithms.Numeric +namespace Algorithms.Numeric; + +public static class CatalanNumbers { - public static class CatalanNumbers - { - /// - /// Internal cache. - /// By default contains the first two catalan numbers for the ranks: 0, and 1. - /// - private static readonly Dictionary CachedCatalanNumbers = new Dictionary { { 0, 1 }, { 1, 1 } }; - - /// - /// Helper method. - /// - /// - /// - private static BigInteger _recursiveHelper(uint rank) - { - if (CachedCatalanNumbers.ContainsKey(rank)) - return CachedCatalanNumbers[rank]; + /// + /// Internal cache. + /// By default contains the first two catalan numbers for the ranks: 0, and 1. + /// + private static readonly Dictionary CachedCatalanNumbers = new Dictionary { { 0, 1 }, { 1, 1 } }; - BigInteger number = 0; - var lastRank = rank - 1; + /// + /// Helper method. + /// + /// + /// + private static BigInteger _recursiveHelper(uint rank) + { + if (CachedCatalanNumbers.ContainsKey(rank)) + return CachedCatalanNumbers[rank]; - for (uint i = 0; i <= lastRank; ++i) - { - var firstPart = _recursiveHelper(i); - var secondPart = _recursiveHelper(lastRank - i); + BigInteger number = 0; + var lastRank = rank - 1; - if (!CachedCatalanNumbers.ContainsKey(i)) CachedCatalanNumbers.Add(i, firstPart); - if (!CachedCatalanNumbers.ContainsKey(lastRank - i)) CachedCatalanNumbers.Add(lastRank - i, secondPart); + for (uint i = 0; i <= lastRank; ++i) + { + var firstPart = _recursiveHelper(i); + var secondPart = _recursiveHelper(lastRank - i); - number = number + firstPart * secondPart; - } + if (!CachedCatalanNumbers.ContainsKey(i)) CachedCatalanNumbers.Add(i, firstPart); + if (!CachedCatalanNumbers.ContainsKey(lastRank - i)) CachedCatalanNumbers.Add(lastRank - i, secondPart); - return number; + number = number + firstPart * secondPart; } - /// - /// Public API. - /// - /// - /// - public static BigInteger GetNumber(uint rank) - { - // Assert the cache is not empty. - Debug.Assert(CachedCatalanNumbers.Count >= 2); + return number; + } - return _recursiveHelper(rank); - } + /// + /// Public API. + /// + /// + /// + public static BigInteger GetNumber(uint rank) + { + // Assert the cache is not empty. + Debug.Assert(CachedCatalanNumbers.Count >= 2); - /// - /// Calculate the number using the Binomial Coefficients algorithm - /// - /// - /// - public static BigInteger GetNumberByBinomialCoefficients(uint rank) - { - // Calculate by binomial coefficient. - return BinomialCoefficients.Calculate(rank); - } + return _recursiveHelper(rank); + } - /// - /// Return the list of catalan numbers between two ranks, inclusive - /// - /// - /// - /// - public static List GetRange(uint fromRank, uint toRank) - { - var numbers = new List(); + /// + /// Calculate the number using the Binomial Coefficients algorithm + /// + /// + /// + public static BigInteger GetNumberByBinomialCoefficients(uint rank) + { + // Calculate by binomial coefficient. + return BinomialCoefficients.Calculate(rank); + } + + /// + /// Return the list of catalan numbers between two ranks, inclusive + /// + /// + /// + /// + public static List GetRange(uint fromRank, uint toRank) + { + var numbers = new List(); - if (fromRank > toRank) - return null; + if (fromRank > toRank) + return null; - for (var i = fromRank; i <= toRank; ++i) - numbers.Add(GetNumber(i)); + for (var i = fromRank; i <= toRank; ++i) + numbers.Add(GetNumber(i)); - return numbers; - } + return numbers; } } \ No newline at end of file diff --git a/Algorithms/Numeric/GreatestCommonDivisor.cs b/Algorithms/Numeric/GreatestCommonDivisor.cs index 839c1d72..be708a24 100644 --- a/Algorithms/Numeric/GreatestCommonDivisor.cs +++ b/Algorithms/Numeric/GreatestCommonDivisor.cs @@ -1,70 +1,69 @@ using System; -namespace Algorithms.Numeric +namespace Algorithms.Numeric; + +public static class GreatestCommonDivisor { - public static class GreatestCommonDivisor + /// + /// Returns the greatest common divisor of two numbers using Euclidean Algorithm. + /// + public static int FindGCDEuclidean(int a, int b) { - /// - /// Returns the greatest common divisor of two numbers using Euclidean Algorithm. - /// - public static int FindGCDEuclidean(int a, int b) - { - int t = 0; - - a = Math.Abs(a); - b = Math.Abs(b); + int t = 0; - if (a == 0) - return b; - if (b == 0) - return a; + a = Math.Abs(a); + b = Math.Abs(b); - while (a % b != 0) { - t = b; - b = a % b; - a = t; - } + if (a == 0) return b; + if (b == 0) + return a; + + while (a % b != 0) { + t = b; + b = a % b; + a = t; } + return b; + } - /// - /// Returns the greatest common divisor of two numbers using Stein Algorithm. - /// - public static int FindGCDStein(int a, int b) - { - a = Math.Abs(a); - b = Math.Abs(b); + /// + /// Returns the greatest common divisor of two numbers using Stein Algorithm. + /// + public static int FindGCDStein(int a, int b) + { + a = Math.Abs(a); + b = Math.Abs(b); - return Stein(a, b); - } + return Stein(a, b); + } - private static int Stein(int a, int b) - { - if (a == 0) - return b; - if (b == 0) - return a; - if (a == b) - return a; + private static int Stein(int a, int b) + { + if (a == 0) + return b; + if (b == 0) + return a; + if (a == b) + return a; - if ((~a & 1) == 1) + if ((~a & 1) == 1) + { + if ((b & 1) == 1) { - if ((b & 1) == 1) - { - return Stein(a >> 1, b); - } - else - { - return Stein(a >> 1, b >> 1) << 1; - } + return Stein(a >> 1, b); } - - if ((~b & 1) == 1) + else { - return Stein(a, b >> 1); + return Stein(a >> 1, b >> 1) << 1; } + } - return a > b ? Stein((a - b) >> 1, b) : Stein(a, (b - a) >> 1); + if ((~b & 1) == 1) + { + return Stein(a, b >> 1); } + + return a > b ? Stein((a - b) >> 1, b) : Stein(a, (b - a) >> 1); } -} +} \ No newline at end of file diff --git a/Algorithms/Numeric/SieveOfAtkin.cs b/Algorithms/Numeric/SieveOfAtkin.cs index 3c679505..1070364a 100644 --- a/Algorithms/Numeric/SieveOfAtkin.cs +++ b/Algorithms/Numeric/SieveOfAtkin.cs @@ -8,66 +8,65 @@ */ -namespace Algorithms.Numeric +namespace Algorithms.Numeric; + +public static class SieveOfAtkin { - public static class SieveOfAtkin + /// + /// Calculate primes up to a given number + /// + public static List GeneratePrimesUpTo(int max) { - /// - /// Calculate primes up to a given number - /// - public static List GeneratePrimesUpTo(int max) + if (max == 2) { - if (max == 2) - { - return new List() { 2 }; - } + return new List() { 2 }; + } - if (max < 2) - { - return new List(); - } + if (max < 2) + { + return new List(); + } - var isPrime = new bool[max + 1]; - var sqrt = (int)System.Math.Sqrt(max); + var isPrime = new bool[max + 1]; + var sqrt = (int)System.Math.Sqrt(max); - Parallel.For(1, sqrt, x => + Parallel.For(1, sqrt, x => + { + var xx = x * x; + for (var y = 1; y <= sqrt; y++) { - var xx = x * x; - for (var y = 1; y <= sqrt; y++) - { - var yy = y * y; - var n = 4 * xx + yy; - if (n <= max && (n % 12 == 1 || n % 12 == 5)) - isPrime[n] ^= true; + var yy = y * y; + var n = 4 * xx + yy; + if (n <= max && (n % 12 == 1 || n % 12 == 5)) + isPrime[n] ^= true; - n = 3 * xx + yy; - if (n <= max && n % 12 == 7) - isPrime[n] ^= true; + n = 3 * xx + yy; + if (n <= max && n % 12 == 7) + isPrime[n] ^= true; - n = 3 * xx - yy; - if (x > y && n <= max && n % 12 == 11) - isPrime[n] ^= true; - } - }); + n = 3 * xx - yy; + if (x > y && n <= max && n % 12 == 11) + isPrime[n] ^= true; + } + }); - var primes = new List() { 2, 3 }; - for (var n = 5; n <= sqrt; n++) + var primes = new List() { 2, 3 }; + for (var n = 5; n <= sqrt; n++) + { + if (isPrime[n]) { - if (isPrime[n]) - { - primes.Add(n); - var nn = n * n; - for (var k = nn; k <= max; k += nn) - isPrime[k] = false; - } + primes.Add(n); + var nn = n * n; + for (var k = nn; k <= max; k += nn) + isPrime[k] = false; } - - for (var n = sqrt + 1; n <= max; n++) - if (isPrime[n]) - primes.Add(n); - - return primes; } + for (var n = sqrt + 1; n <= max; n++) + if (isPrime[n]) + primes.Add(n); + + return primes; } -} + +} \ No newline at end of file diff --git a/Algorithms/Numeric/SieveOfEratosthenes.cs b/Algorithms/Numeric/SieveOfEratosthenes.cs index 39505e94..c8a8664e 100644 --- a/Algorithms/Numeric/SieveOfEratosthenes.cs +++ b/Algorithms/Numeric/SieveOfEratosthenes.cs @@ -8,51 +8,50 @@ */ -namespace Algorithms.Numeric +namespace Algorithms.Numeric; + +public static class SieveOfEratosthenes { - public static class SieveOfEratosthenes + /// + /// Calculate primes up to a given number + /// + public static IEnumerable GeneratePrimesUpTo(int x) { - /// - /// Calculate primes up to a given number - /// - public static IEnumerable GeneratePrimesUpTo(int x) - { - //The hash of primes that will be returned - var primes = new HashSet(); + //The hash of primes that will be returned + var primes = new HashSet(); - //Returns an empty list if x is a value under 2 - if (x < 2) - { - return primes.ToList(); - } + //Returns an empty list if x is a value under 2 + if (x < 2) + { + return primes.ToList(); + } - //Adds every number between 2 and x to the hashset - for (int i = 2; i <= x; i++) - { - primes.Add(i); - } + //Adds every number between 2 and x to the hashset + for (int i = 2; i <= x; i++) + { + primes.Add(i); + } - //integer that all multiples of will be removed from the hashset - int removeMultiplesOf; + //integer that all multiples of will be removed from the hashset + int removeMultiplesOf; - //Finds the next number that hasn't been removed and removes all multiples of that number - //from the hashset - for (int i = 2; i <= Math.Sqrt(x); i++) + //Finds the next number that hasn't been removed and removes all multiples of that number + //from the hashset + for (int i = 2; i <= Math.Sqrt(x); i++) + { + if (primes.Contains(i)) { - if (primes.Contains(i)) + removeMultiplesOf = i; + for (int j = removeMultiplesOf * removeMultiplesOf; j <= x; j += removeMultiplesOf) { - removeMultiplesOf = i; - for (int j = removeMultiplesOf * removeMultiplesOf; j <= x; j += removeMultiplesOf) - { - primes.Remove(j); - } + primes.Remove(j); } } - - //The list of primes is returned - return primes.ToList(); } + //The list of primes is returned + return primes.ToList(); } -} + +} \ No newline at end of file diff --git a/Algorithms/Search/BinarySearcher.cs b/Algorithms/Search/BinarySearcher.cs index e4940680..c5c4e672 100644 --- a/Algorithms/Search/BinarySearcher.cs +++ b/Algorithms/Search/BinarySearcher.cs @@ -3,101 +3,100 @@ using System.Collections.Generic; using Algorithms.Sorting; -namespace Algorithms.Search +namespace Algorithms.Search; + +public class BinarySearcher : IEnumerator { - public class BinarySearcher : IEnumerator - { - private readonly IList _collection; - private readonly Comparer _comparer; - private T _item; - private int _currentItemIndex; - private int _leftIndex; - private int _rightIndex; + private readonly IList _collection; + private readonly Comparer _comparer; + private T _item; + private int _currentItemIndex; + private int _leftIndex; + private int _rightIndex; + + /// + /// The value of the current item + /// + public T Current => _collection[_currentItemIndex]; - /// - /// The value of the current item - /// - public T Current => _collection[_currentItemIndex]; + object IEnumerator.Current => Current; + + /// + /// Class constructor + /// + /// A list + /// A comparer + public BinarySearcher(IList collection, Comparer comparer) + { + if (collection == null) + { + throw new NullReferenceException("List is null"); + } + _collection = collection; + _comparer = comparer; + HeapSorter.HeapSort(_collection); + } - object IEnumerator.Current => Current; + /// + /// Apply Binary Search in a list. + /// + /// The item we search + /// If item found, its' index, -1 otherwise + public int BinarySearch(T item) + { + bool notFound = true; - /// - /// Class constructor - /// - /// A list - /// A comparer - public BinarySearcher(IList collection, Comparer comparer) + if (item == null) { - if (collection == null) - { - throw new NullReferenceException("List is null"); - } - _collection = collection; - _comparer = comparer; - HeapSorter.HeapSort(_collection); + throw new NullReferenceException("Item to search for is not set"); } + Reset(); + _item = item; - /// - /// Apply Binary Search in a list. - /// - /// The item we search - /// If item found, its' index, -1 otherwise - public int BinarySearch(T item) + while (_leftIndex <= _rightIndex && notFound) { - bool notFound = true; + notFound = MoveNext(); + } - if (item == null) - { - throw new NullReferenceException("Item to search for is not set"); - } + if (notFound) + { Reset(); - _item = item; + } + return _currentItemIndex; + } - while (_leftIndex <= _rightIndex && notFound) - { - notFound = MoveNext(); - } + /// + /// An implementation of IEnumerator's MoveNext method. + /// + /// true if iteration can proceed to the next item, false otherwise + public bool MoveNext() + { + _currentItemIndex = _leftIndex + (_rightIndex - _leftIndex) / 2; - if (notFound) - { - Reset(); - } - return _currentItemIndex; + if (_comparer.Compare(_item, Current) < 0) + { + _rightIndex = _currentItemIndex - 1; } - - /// - /// An implementation of IEnumerator's MoveNext method. - /// - /// true if iteration can proceed to the next item, false otherwise - public bool MoveNext() + else if (_comparer.Compare(_item, Current) > 0) { - _currentItemIndex = _leftIndex + (_rightIndex - _leftIndex) / 2; - - if (_comparer.Compare(_item, Current) < 0) - { - _rightIndex = _currentItemIndex - 1; - } - else if (_comparer.Compare(_item, Current) > 0) - { - _leftIndex = _currentItemIndex + 1; - } - else - { - return false; - } - return true; + _leftIndex = _currentItemIndex + 1; } - - public void Reset() - { - _currentItemIndex = -1; - _leftIndex = 0; - _rightIndex = _collection.Count - 1; + else + { + return false; } + return true; + } - public void Dispose() - { - //not implementing this, since there are no managed resources to release - } + public void Reset() + { + _currentItemIndex = -1; + _leftIndex = 0; + _rightIndex = _collection.Count - 1; + } + + public void Dispose() + { + //not implementing this, since there are no managed resources to release } } \ No newline at end of file diff --git a/Algorithms/Sorting/BinarySearchTreeSorter.cs b/Algorithms/Sorting/BinarySearchTreeSorter.cs index 2c1ac437..9a8a7d3e 100644 --- a/Algorithms/Sorting/BinarySearchTreeSorter.cs +++ b/Algorithms/Sorting/BinarySearchTreeSorter.cs @@ -3,107 +3,106 @@ using Algorithms.Common; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +public static class BinarySearchTreeSorter { - public static class BinarySearchTreeSorter + /// + /// Unbalanced Binary Search Tree sort. + /// + /// + /// + public static void UnbalancedBSTSort(this List collection) where T : IComparable { - /// - /// Unbalanced Binary Search Tree sort. - /// - /// - /// - public static void UnbalancedBSTSort(this List collection) where T : IComparable - { - if (collection.Count == 0) - return; + if (collection.Count == 0) + return; - Node treeRoot = new Node() { Value = collection[0] }; + Node treeRoot = new Node() { Value = collection[0] }; - // Get a handle on root. - for (int i = 1; i < collection.Count; ++i) - { - var currentNode = treeRoot; - var newNode = new Node() { Value = collection[i] }; + // Get a handle on root. + for (int i = 1; i < collection.Count; ++i) + { + var currentNode = treeRoot; + var newNode = new Node() { Value = collection[i] }; - while (true) + while (true) + { + // Go left + if (newNode.Value.IsLessThan(currentNode.Value)) { - // Go left - if (newNode.Value.IsLessThan(currentNode.Value)) + if (currentNode.Left == null) { - if (currentNode.Left == null) - { - newNode.Parent = currentNode; - currentNode.Left = newNode; - break; - } - - currentNode = currentNode.Left; + newNode.Parent = currentNode; + currentNode.Left = newNode; + break; } - // Go right - else + + currentNode = currentNode.Left; + } + // Go right + else + { + if (currentNode.Right == null) { - if (currentNode.Right == null) - { - newNode.Parent = currentNode; - currentNode.Right = newNode; - break; - } - - currentNode = currentNode.Right; + newNode.Parent = currentNode; + currentNode.Right = newNode; + break; } - }//end-while - }//end-for - // Reference handle to root again. - collection.Clear(); - var treeRootReference = treeRoot; - _inOrderTravelAndAdd(treeRootReference, ref collection); + currentNode = currentNode.Right; + } + }//end-while + }//end-for - treeRootReference = treeRoot = null; - } + // Reference handle to root again. + collection.Clear(); + var treeRootReference = treeRoot; + _inOrderTravelAndAdd(treeRootReference, ref collection); + treeRootReference = treeRoot = null; + } - /// - /// Used to travel a node's subtrees and add the elements to the collection. - /// - /// Type of tree elements. - /// Node to start from. - /// Collection to add elements to. - private static void _inOrderTravelAndAdd(Node currentNode, ref List collection) where T : IComparable - { - if (currentNode == null) - return; - _inOrderTravelAndAdd(currentNode.Left, ref collection); - collection.Add(currentNode.Value); - _inOrderTravelAndAdd(currentNode.Right, ref collection); - } + /// + /// Used to travel a node's subtrees and add the elements to the collection. + /// + /// Type of tree elements. + /// Node to start from. + /// Collection to add elements to. + private static void _inOrderTravelAndAdd(Node currentNode, ref List collection) where T : IComparable + { + if (currentNode == null) + return; + _inOrderTravelAndAdd(currentNode.Left, ref collection); + collection.Add(currentNode.Value); + _inOrderTravelAndAdd(currentNode.Right, ref collection); + } - /// - /// Minimal BST Node class, used only for unbalanced binary search tree sort. - /// - /// - private class Node : IComparable> where T : IComparable - { - public T Value { get; set; } - public Node Parent { get; set; } - public Node Left { get; set; } - public Node Right { get; set; } - public Node() - { - Value = default; - Parent = null; - Left = null; - Right = null; - } + /// + /// Minimal BST Node class, used only for unbalanced binary search tree sort. + /// + /// + private class Node : IComparable> where T : IComparable + { + public T Value { get; set; } + public Node Parent { get; set; } + public Node Left { get; set; } + public Node Right { get; set; } - public int CompareTo(Node other) - { - if (other == null) return -1; - return Value.CompareTo(other.Value); - } + public Node() + { + Value = default; + Parent = null; + Left = null; + Right = null; + } + + public int CompareTo(Node other) + { + if (other == null) return -1; + return Value.CompareTo(other.Value); } } -} +} \ No newline at end of file diff --git a/Algorithms/Sorting/BubbleSorter.cs b/Algorithms/Sorting/BubbleSorter.cs index 83981475..e1b4d718 100644 --- a/Algorithms/Sorting/BubbleSorter.cs +++ b/Algorithms/Sorting/BubbleSorter.cs @@ -1,48 +1,47 @@ using System.Collections.Generic; using Algorithms.Common; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +public static class BubbleSorter { - public static class BubbleSorter + public static void BubbleSort(this IList collection, Comparer comparer = null) { - public static void BubbleSort(this IList collection, Comparer comparer = null) - { - comparer = comparer ?? Comparer.Default; - collection.BubbleSortAscending(comparer); - } + comparer = comparer ?? Comparer.Default; + collection.BubbleSortAscending(comparer); + } - /// - /// Public API: Sorts ascending - /// - public static void BubbleSortAscending(this IList collection, Comparer comparer) + /// + /// Public API: Sorts ascending + /// + public static void BubbleSortAscending(this IList collection, Comparer comparer) + { + for (int i = 0; i < collection.Count; i++) { - for (int i = 0; i < collection.Count; i++) + for (int index = 0; index < collection.Count - i - 1; index++) { - for (int index = 0; index < collection.Count - i - 1; index++) + if (comparer.Compare(collection[index], collection[index + 1]) > 0) { - if (comparer.Compare(collection[index], collection[index + 1]) > 0) - { - collection.Swap(index, index + 1); - } + collection.Swap(index, index + 1); } } } + } - /// - /// Public API: Sorts descending - /// - public static void BubbleSortDescending(this IList collection, Comparer comparer) + /// + /// Public API: Sorts descending + /// + public static void BubbleSortDescending(this IList collection, Comparer comparer) + { + for (int i = 0; i < collection.Count - 1; i++) { - for (int i = 0; i < collection.Count - 1; i++) + for (int index = 1; index < collection.Count - i; index++) { - for (int index = 1; index < collection.Count - i; index++) + if (comparer.Compare(collection[index], collection[index - 1]) > 0) { - if (comparer.Compare(collection[index], collection[index - 1]) > 0) - { - collection.Swap(index - 1, index); - } + collection.Swap(index - 1, index); } } } } -} +} \ No newline at end of file diff --git a/Algorithms/Sorting/BucketSorter.cs b/Algorithms/Sorting/BucketSorter.cs index 65fa1af1..9087c697 100644 --- a/Algorithms/Sorting/BucketSorter.cs +++ b/Algorithms/Sorting/BucketSorter.cs @@ -1,89 +1,88 @@ using System.Collections.Generic; using System.Linq; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +/// +/// Only support IList Sort +/// +public static class BucketSorter { + public static void BucketSort(this IList collection) + { + collection.BucketSortAscending(); + } + /// - /// Only support IList Sort + /// Public API: Sorts ascending /// - public static class BucketSorter + public static void BucketSortAscending(this IList collection) { - public static void BucketSort(this IList collection) + int maxValue = collection.Max(); + int minValue = collection.Min(); + + List[] bucket = new List[maxValue - minValue + 1]; + + for (int i = 0; i < bucket.Length; i++) { - collection.BucketSortAscending(); + bucket[i] = new List(); } - /// - /// Public API: Sorts ascending - /// - public static void BucketSortAscending(this IList collection) - { - int maxValue = collection.Max(); - int minValue = collection.Min(); - - List[] bucket = new List[maxValue - minValue + 1]; + foreach (int i in collection) { + bucket[i - minValue].Add(i); + } - for (int i = 0; i < bucket.Length; i++) + int k = 0; + foreach (List i in bucket) { + if (i.Count > 0) { - bucket[i] = new List(); - } - - foreach (int i in collection) { - bucket[i - minValue].Add(i); - } - - int k = 0; - foreach (List i in bucket) { - if (i.Count > 0) + foreach (int j in i) { - foreach (int j in i) - { - collection[k] = j; - k++; - } + collection[k] = j; + k++; } } } + } - /// - /// Public API: Sorts descending - /// - public static void BucketSortDescending(this IList collection) + /// + /// Public API: Sorts descending + /// + public static void BucketSortDescending(this IList collection) + { + int maxValue = collection[0]; + int minValue = collection[0]; + for (int i = 1; i < collection.Count; i++) { - int maxValue = collection[0]; - int minValue = collection[0]; - for (int i = 1; i < collection.Count; i++) - { - if (collection[i] > maxValue) - maxValue = collection[i]; + if (collection[i] > maxValue) + maxValue = collection[i]; - if (collection[i] < minValue) - minValue = collection[i]; - } - List[] bucket = new List[maxValue - minValue + 1]; + if (collection[i] < minValue) + minValue = collection[i]; + } + List[] bucket = new List[maxValue - minValue + 1]; - for (int i = 0; i < bucket.Length; i++) - { - bucket[i] = new List(); - } + for (int i = 0; i < bucket.Length; i++) + { + bucket[i] = new List(); + } - foreach (int i in collection) - { - bucket[i - minValue].Add(i); - } + foreach (int i in collection) + { + bucket[i - minValue].Add(i); + } - int k = collection.Count-1; - foreach (List i in bucket) + int k = collection.Count-1; + foreach (List i in bucket) + { + if (i.Count > 0) { - if (i.Count > 0) + foreach (int j in i) { - foreach (int j in i) - { - collection[k] = j; - k--; - } + collection[k] = j; + k--; } } } } -} +} \ No newline at end of file diff --git a/Algorithms/Sorting/CombSorter.cs b/Algorithms/Sorting/CombSorter.cs index 22dcc106..cbe6a9c5 100644 --- a/Algorithms/Sorting/CombSorter.cs +++ b/Algorithms/Sorting/CombSorter.cs @@ -1,66 +1,65 @@ using System.Collections.Generic; using Algorithms.Common; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +public static class CombSorter { - public static class CombSorter + public static void CombSort(this IList collection, Comparer comparer = null) { - public static void CombSort(this IList collection, Comparer comparer = null) - { - comparer = comparer ?? Comparer.Default; - collection.ShellSortAscending(comparer); - } + comparer = comparer ?? Comparer.Default; + collection.ShellSortAscending(comparer); + } - /// - /// Public API: Sorts ascending - /// - public static void CombSortAscending(this IList collection, Comparer comparer) + /// + /// Public API: Sorts ascending + /// + public static void CombSortAscending(this IList collection, Comparer comparer) + { + double gap = collection.Count; + bool swaps = true; + while (gap > 1 || swaps) { - double gap = collection.Count; - bool swaps = true; - while (gap > 1 || swaps) + gap /= 1.247330950103979; + if (gap < 1) { gap = 1; } + int i = 0; + swaps = false; + while (i + gap < collection.Count) { - gap /= 1.247330950103979; - if (gap < 1) { gap = 1; } - int i = 0; - swaps = false; - while (i + gap < collection.Count) + int igap = i + (int)gap; + if (comparer.Compare(collection[i], collection[igap])>0) { - int igap = i + (int)gap; - if (comparer.Compare(collection[i], collection[igap])>0) - { - collection.Swap(i,igap); - swaps = true; - } - i++; + collection.Swap(i,igap); + swaps = true; } + i++; } } + } - /// - /// Public API: Sorts descending - /// - public static void CombSortDescending(this IList collection, Comparer comparer) + /// + /// Public API: Sorts descending + /// + public static void CombSortDescending(this IList collection, Comparer comparer) + { + double gap = collection.Count; + bool swaps = true; + while (gap > 1 || swaps) { - double gap = collection.Count; - bool swaps = true; - while (gap > 1 || swaps) + gap /= 1.247330950103979; + if (gap < 1) { gap = 1; } + int i = 0; + swaps = false; + while (i + gap < collection.Count) { - gap /= 1.247330950103979; - if (gap < 1) { gap = 1; } - int i = 0; - swaps = false; - while (i + gap < collection.Count) + int igap = i + (int)gap; + if (comparer.Compare(collection[i], collection[igap]) < 0) { - int igap = i + (int)gap; - if (comparer.Compare(collection[i], collection[igap]) < 0) - { - collection.Swap(i, igap); - swaps = true; - } - i++; + collection.Swap(i, igap); + swaps = true; } + i++; } } } -} +} \ No newline at end of file diff --git a/Algorithms/Sorting/CountingSorter.cs b/Algorithms/Sorting/CountingSorter.cs index 10673b59..3b920a54 100644 --- a/Algorithms/Sorting/CountingSorter.cs +++ b/Algorithms/Sorting/CountingSorter.cs @@ -3,54 +3,53 @@ using Algorithms.Common; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +public static class CountingSorter { - public static class CountingSorter + public static void CountingSort(this IList collection) { - public static void CountingSort(this IList collection) + if (collection == null || collection.Count == 0) + return; + + // Get the maximum number in array. + int maxK = 0; + int index = 0; + while (true) { - if (collection == null || collection.Count == 0) - return; + if (index >= collection.Count) + break; - // Get the maximum number in array. - int maxK = 0; - int index = 0; - while (true) - { - if (index >= collection.Count) - break; + maxK = Math.Max(maxK, collection[index] + 1); + index++; + } - maxK = Math.Max(maxK, collection[index] + 1); - index++; - } + // The array of keys, used to sort the original array. + int[] keys = new int[maxK]; + keys.Populate(0); // populate it with zeros - // The array of keys, used to sort the original array. - int[] keys = new int[maxK]; - keys.Populate(0); // populate it with zeros + // Assign the keys + for (int i = 0; i < collection.Count; ++i) + { + keys[collection[i]] += 1; + } - // Assign the keys - for (int i = 0; i < collection.Count; ++i) - { - keys[collection[i]] += 1; - } + // Reset index. + index = 0; - // Reset index. - index = 0; + // Sort the elements + for (int j = 0; j < keys.Length; ++j) + { + var val = keys[j]; - // Sort the elements - for (int j = 0; j < keys.Length; ++j) + if (val > 0) { - var val = keys[j]; - - if (val > 0) + while (val-- > 0) { - while (val-- > 0) - { - collection[index] = j; - index++; - } + collection[index] = j; + index++; } } } } -} +} \ No newline at end of file diff --git a/Algorithms/Sorting/CycleSorter.cs b/Algorithms/Sorting/CycleSorter.cs index 21974cb8..e2bba26d 100644 --- a/Algorithms/Sorting/CycleSorter.cs +++ b/Algorithms/Sorting/CycleSorter.cs @@ -1,80 +1,79 @@ using System.Collections.Generic; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +public static class CycleSorter { - public static class CycleSorter - { - public static void CycleSort(this IList collection, Comparer comparer = null) - { - comparer = comparer ?? Comparer.Default; - collection.CycleSortAscending(comparer); - } + public static void CycleSort(this IList collection, Comparer comparer = null) + { + comparer = comparer ?? Comparer.Default; + collection.CycleSortAscending(comparer); + } - public static void CycleSortDescending(this IList collection, Comparer comparer) + public static void CycleSortDescending(this IList collection, Comparer comparer) + { + for (int cycleStart = 0; cycleStart < collection.Count; cycleStart++) { - for (int cycleStart = 0; cycleStart < collection.Count; cycleStart++) - { - T item = collection[cycleStart]; - int position = cycleStart; + T item = collection[cycleStart]; + int position = cycleStart; - do + do + { + int to = 0; + for (int i = 0; i < collection.Count; i++) { - int to = 0; - for (int i = 0; i < collection.Count; i++) + if (i != cycleStart && comparer.Compare(collection[i], item) > 0) { - if (i != cycleStart && comparer.Compare(collection[i], item) > 0) - { - to++; - } + to++; } - if (position != to) + } + if (position != to) + { + while (position != to && comparer.Compare(item, collection[to]) == 0) { - while (position != to && comparer.Compare(item, collection[to]) == 0) - { - to++; - } - - T temp = collection[to]; - collection[to] = item; - item = temp; - position = to; + to++; } - } while (position != cycleStart); - } + + T temp = collection[to]; + collection[to] = item; + item = temp; + position = to; + } + } while (position != cycleStart); } + } - public static void CycleSortAscending(this IList collection, Comparer comparer) + public static void CycleSortAscending(this IList collection, Comparer comparer) + { + for (int cycleStart = 0; cycleStart < collection.Count; cycleStart++) { - for (int cycleStart = 0; cycleStart < collection.Count; cycleStart++) - { - T item = collection[cycleStart]; - int position = cycleStart; + T item = collection[cycleStart]; + int position = cycleStart; - do + do + { + int to = 0; + for (int i = 0; i < collection.Count; i++) { - int to = 0; - for (int i = 0; i < collection.Count; i++) + if (i != cycleStart && comparer.Compare(collection[i], item) < 0) { - if (i != cycleStart && comparer.Compare(collection[i], item) < 0) - { - to++; - } + to++; } - if (position != to) + } + if (position != to) + { + while (position != to && comparer.Compare(item,collection[to]) == 0) { - while (position != to && comparer.Compare(item,collection[to]) == 0) - { - to++; - } - - T temp = collection[to]; - collection[to] = item; - item = temp; - position = to; + to++; } - } while (position != cycleStart); - } + + T temp = collection[to]; + collection[to] = item; + item = temp; + position = to; + } + } while (position != cycleStart); } } -} +} \ No newline at end of file diff --git a/Algorithms/Sorting/GnomeSorter.cs b/Algorithms/Sorting/GnomeSorter.cs index 4f44b7c4..e69abdb9 100644 --- a/Algorithms/Sorting/GnomeSorter.cs +++ b/Algorithms/Sorting/GnomeSorter.cs @@ -1,63 +1,62 @@ using System.Collections.Generic; using Algorithms.Common; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +/// +/// Also called Stupid Sort +/// +public static class GnomeSorter { + public static void GnomeSort(this IList collection, Comparer comparer = null) + { + comparer = comparer ?? Comparer.Default; + collection.GnomeSortAscending(comparer); + } + /// - /// Also called Stupid Sort + /// Public API: Sorts ascending /// - public static class GnomeSorter + public static void GnomeSortAscending(this IList collection, Comparer comparer) { - public static void GnomeSort(this IList collection, Comparer comparer = null) - { - comparer = comparer ?? Comparer.Default; - collection.GnomeSortAscending(comparer); - } - - /// - /// Public API: Sorts ascending - /// - public static void GnomeSortAscending(this IList collection, Comparer comparer) + int pos = 1; + while (pos < collection.Count) { - int pos = 1; - while (pos < collection.Count) + if (comparer.Compare(collection[pos],collection[pos-1]) >= 0) { - if (comparer.Compare(collection[pos],collection[pos-1]) >= 0) - { - pos++; - } - else + pos++; + } + else + { + collection.Swap(pos,pos-1); + if (pos > 1) { - collection.Swap(pos,pos-1); - if (pos > 1) - { - pos--; - } + pos--; } } } + } - /// - /// Public API: Sorts descending - /// - public static void GnomeSortDescending(this IList collection, Comparer comparer) + /// + /// Public API: Sorts descending + /// + public static void GnomeSortDescending(this IList collection, Comparer comparer) + { + int pos = 1; + while (pos < collection.Count) { - int pos = 1; - while (pos < collection.Count) + if (comparer.Compare(collection[pos], collection[pos - 1]) <= 0) { - if (comparer.Compare(collection[pos], collection[pos - 1]) <= 0) - { - pos++; - } - else + pos++; + } + else + { + collection.Swap(pos, pos - 1); + if (pos > 1) { - collection.Swap(pos, pos - 1); - if (pos > 1) - { - pos--; - } + pos--; } } } } -} +} \ No newline at end of file diff --git a/Algorithms/Sorting/HeapSorter.cs b/Algorithms/Sorting/HeapSorter.cs index 7be00c7a..e91db83b 100644 --- a/Algorithms/Sorting/HeapSorter.cs +++ b/Algorithms/Sorting/HeapSorter.cs @@ -1,143 +1,142 @@ using System.Collections.Generic; using Algorithms.Common; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +public static class HeapSorter { - public static class HeapSorter + /// + /// Public API: Default functionality. + /// Sorts in ascending order. Uses Max-Heaps. + /// + public static void HeapSort(this IList collection, Comparer comparer = null) + { + collection.HeapSortAscending(comparer); + } + + /// + /// Public API: Sorts ascending + /// Uses Max-Heaps + /// + public static void HeapSortAscending(this IList collection, Comparer comparer = null) { - /// - /// Public API: Default functionality. - /// Sorts in ascending order. Uses Max-Heaps. - /// - public static void HeapSort(this IList collection, Comparer comparer = null) + // Handle the comparer's default null value + comparer = comparer ?? Comparer.Default; + + int lastIndex = collection.Count - 1; + collection.BuildMaxHeap(0, lastIndex, comparer); + + while (lastIndex >= 0) { - collection.HeapSortAscending(comparer); + collection.Swap(0, lastIndex); + lastIndex--; + collection.MaxHeapify(0, lastIndex, comparer); } + } - /// - /// Public API: Sorts ascending - /// Uses Max-Heaps - /// - public static void HeapSortAscending(this IList collection, Comparer comparer = null) + /// + /// Public API: Sorts ascending + /// Uses Min-Heaps + /// + public static void HeapSortDescending(this IList collection, Comparer comparer = null) + { + // Handle the comparer's default null value + comparer = comparer ?? Comparer.Default; + + int lastIndex = collection.Count - 1; + collection.BuildMinHeap(0, lastIndex, comparer); + + while (lastIndex >= 0) { - // Handle the comparer's default null value - comparer = comparer ?? Comparer.Default; - - int lastIndex = collection.Count - 1; - collection.BuildMaxHeap(0, lastIndex, comparer); - - while (lastIndex >= 0) - { - collection.Swap(0, lastIndex); - lastIndex--; - collection.MaxHeapify(0, lastIndex, comparer); - } + collection.Swap(0, lastIndex); + lastIndex--; + collection.MinHeapify(0, lastIndex, comparer); } + } + + + /****************************************************************************/ + - /// - /// Public API: Sorts ascending - /// Uses Min-Heaps - /// - public static void HeapSortDescending(this IList collection, Comparer comparer = null) + /// + /// Private Max-Heap Builder. + /// Builds a max heap from an IList collection. + /// + private static void BuildMaxHeap(this IList collection, int firstIndex, int lastIndex, Comparer comparer) + { + int lastNodeWithChildren = lastIndex / 2; + + for (int node = lastNodeWithChildren; node >= 0; --node) { - // Handle the comparer's default null value - comparer = comparer ?? Comparer.Default; - - int lastIndex = collection.Count - 1; - collection.BuildMinHeap(0, lastIndex, comparer); - - while (lastIndex >= 0) - { - collection.Swap(0, lastIndex); - lastIndex--; - collection.MinHeapify(0, lastIndex, comparer); - } + collection.MaxHeapify(node, lastIndex, comparer); } + } + /// + /// Private Max-Heapifier. Used in BuildMaxHeap. + /// Heapfies the elements between two indexes (inclusive), maintaining the maximum at the top. + /// + private static void MaxHeapify(this IList collection, int nodeIndex, int lastIndex, Comparer comparer) + { + // assume left(i) and right(i) are max-heaps + int left = nodeIndex * 2 + 1; + int right = left + 1; + int largest = nodeIndex; - /****************************************************************************/ + // If collection[left] > collection[nodeIndex] + if (left <= lastIndex && comparer.Compare(collection[left], collection[nodeIndex]) > 0) + largest = left; + // If collection[right] > collection[largest] + if (right <= lastIndex && comparer.Compare(collection[right], collection[largest]) > 0) + largest = right; - /// - /// Private Max-Heap Builder. - /// Builds a max heap from an IList collection. - /// - private static void BuildMaxHeap(this IList collection, int firstIndex, int lastIndex, Comparer comparer) + // Swap and heapify + if (largest != nodeIndex) { - int lastNodeWithChildren = lastIndex / 2; - - for (int node = lastNodeWithChildren; node >= 0; --node) - { - collection.MaxHeapify(node, lastIndex, comparer); - } + collection.Swap(nodeIndex, largest); + collection.MaxHeapify(largest, lastIndex, comparer); } + } - /// - /// Private Max-Heapifier. Used in BuildMaxHeap. - /// Heapfies the elements between two indexes (inclusive), maintaining the maximum at the top. - /// - private static void MaxHeapify(this IList collection, int nodeIndex, int lastIndex, Comparer comparer) + /// + /// Private Min-Heap Builder. + /// Builds a min heap from an IList collection. + /// + private static void BuildMinHeap(this IList collection, int firstIndex, int lastIndex, Comparer comparer) + { + int lastNodeWithChildren = lastIndex / 2; + + for (int node = lastNodeWithChildren; node >= 0; --node) { - // assume left(i) and right(i) are max-heaps - int left = nodeIndex * 2 + 1; - int right = left + 1; - int largest = nodeIndex; - - // If collection[left] > collection[nodeIndex] - if (left <= lastIndex && comparer.Compare(collection[left], collection[nodeIndex]) > 0) - largest = left; - - // If collection[right] > collection[largest] - if (right <= lastIndex && comparer.Compare(collection[right], collection[largest]) > 0) - largest = right; - - // Swap and heapify - if (largest != nodeIndex) - { - collection.Swap(nodeIndex, largest); - collection.MaxHeapify(largest, lastIndex, comparer); - } + collection.MinHeapify(node, lastIndex, comparer); } + } - /// - /// Private Min-Heap Builder. - /// Builds a min heap from an IList collection. - /// - private static void BuildMinHeap(this IList collection, int firstIndex, int lastIndex, Comparer comparer) - { - int lastNodeWithChildren = lastIndex / 2; + /// + /// Private Min-Heapifier. Used in BuildMinHeap. + /// Heapfies the elements between two indexes (inclusive), maintaining the minimum at the top. + /// + private static void MinHeapify(this IList collection, int nodeIndex, int lastIndex, Comparer comparer) + { + // assume left(i) and right(i) are max-heaps + int left = nodeIndex * 2 + 1; + int right = left + 1; + int smallest = nodeIndex; - for (int node = lastNodeWithChildren; node >= 0; --node) - { - collection.MinHeapify(node, lastIndex, comparer); - } - } + // If collection[left] > collection[nodeIndex] + if (left <= lastIndex && comparer.Compare(collection[left], collection[nodeIndex]) < 0) + smallest = left; + + // If collection[right] > collection[largest] + if (right <= lastIndex && comparer.Compare(collection[right], collection[smallest]) < 0) + smallest = right; - /// - /// Private Min-Heapifier. Used in BuildMinHeap. - /// Heapfies the elements between two indexes (inclusive), maintaining the minimum at the top. - /// - private static void MinHeapify(this IList collection, int nodeIndex, int lastIndex, Comparer comparer) + // Swap and heapify + if (smallest != nodeIndex) { - // assume left(i) and right(i) are max-heaps - int left = nodeIndex * 2 + 1; - int right = left + 1; - int smallest = nodeIndex; - - // If collection[left] > collection[nodeIndex] - if (left <= lastIndex && comparer.Compare(collection[left], collection[nodeIndex]) < 0) - smallest = left; - - // If collection[right] > collection[largest] - if (right <= lastIndex && comparer.Compare(collection[right], collection[smallest]) < 0) - smallest = right; - - // Swap and heapify - if (smallest != nodeIndex) - { - collection.Swap(nodeIndex, smallest); - collection.MinHeapify(smallest, lastIndex, comparer); - } + collection.Swap(nodeIndex, smallest); + collection.MinHeapify(smallest, lastIndex, comparer); } } -} +} \ No newline at end of file diff --git a/Algorithms/Sorting/InsertionSorter.cs b/Algorithms/Sorting/InsertionSorter.cs index b74bc986..f0441e2a 100644 --- a/Algorithms/Sorting/InsertionSorter.cs +++ b/Algorithms/Sorting/InsertionSorter.cs @@ -1,64 +1,61 @@ using System.Collections.Generic; using DataStructures.Lists; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +/// +/// Implements this Insertion Sort algorithm over ArrayLists. +/// +public static class InsertionSorter { - /// - /// Implements this Insertion Sort algorithm over ArrayLists. - /// - public static class InsertionSorter + // + // The quick insertion sort algorithm. + // For any collection that implements the IList interface. + public static void InsertionSort(this IList list, Comparer comparer = null) { // - // The quick insertion sort algorithm. - // For any collection that implements the IList interface. - public static void InsertionSort(this IList list, Comparer comparer = null) + // If the comparer is Null, then initialize it using a default typed comparer + comparer = comparer ?? Comparer.Default; + + // Do sorting if list is not empty. + int i, j; + for (i = 1; i < list.Count; i++) { - // - // If the comparer is Null, then initialize it using a default typed comparer - comparer = comparer ?? Comparer.Default; + T value = list[i]; + j = i - 1; - // Do sorting if list is not empty. - int i, j; - for (i = 1; i < list.Count; i++) + while (j >= 0 && comparer.Compare(list[j], value) > 0) { - T value = list[i]; - j = i - 1; - - while (j >= 0 && comparer.Compare(list[j], value) > 0) - { - list[j + 1] = list[j]; - j--; - } - - list[j + 1] = value; + list[j + 1] = list[j]; + j--; } + + list[j + 1] = value; } + } + // + // The quick insertion sort algorithm. + // For the internal ArrayList. Check the DataStructures.ArrayList.cs. + public static void InsertionSort(this ArrayList list, Comparer comparer = null) + { // - // The quick insertion sort algorithm. - // For the internal ArrayList. Check the DataStructures.ArrayList.cs. - public static void InsertionSort(this ArrayList list, Comparer comparer = null) - { - // - // If the comparer is Null, then initialize it using a default typed comparer - comparer = comparer ?? Comparer.Default; + // If the comparer is Null, then initialize it using a default typed comparer + comparer = comparer ?? Comparer.Default; - for (int i = 1; i < list.Count; i++) + for (int i = 1; i < list.Count; i++) + { + for (int j = i; j > 0; j--) { - for (int j = i; j > 0; j--) + if (comparer.Compare(list[j], list[j - 1]) < 0) //(j)th is less than (j-1)th { - if (comparer.Compare(list[j], list[j - 1]) < 0) //(j)th is less than (j-1)th - { - var temp = list[j - 1]; - list[j - 1] = list[j]; - list[j] = temp; - } + var temp = list[j - 1]; + list[j - 1] = list[j]; + list[j] = temp; } } } - } -} - +} \ No newline at end of file diff --git a/Algorithms/Sorting/LSDRadixSorter.cs b/Algorithms/Sorting/LSDRadixSorter.cs index abe475bd..cb44ef9d 100644 --- a/Algorithms/Sorting/LSDRadixSorter.cs +++ b/Algorithms/Sorting/LSDRadixSorter.cs @@ -1,104 +1,103 @@ using System; using System.Collections.Generic; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +/// +/// LSD (Least Significat Digit) Radix Sort. +/// +/// Sorts ASCII-encoded strings. +/// Implemented as a static class of extension methods. +/// +public static class LSDRadixSorter { /// - /// LSD (Least Significat Digit) Radix Sort. - /// - /// Sorts ASCII-encoded strings. - /// Implemented as a static class of extension methods. + /// Extension method for sorting strings. /// - public static class LSDRadixSorter + public static string LSDRadixSort(this string source) { - /// - /// Extension method for sorting strings. - /// - public static string LSDRadixSort(this string source) - { - if (string.IsNullOrEmpty(source) || source.Length <= 1) - return source; + if (string.IsNullOrEmpty(source) || source.Length <= 1) + return source; - // LSD Radix Sort the character arrapy representation of the string - var charArray = source.ToCharArray(); - charArray.LSDRadixSort(); + // LSD Radix Sort the character arrapy representation of the string + var charArray = source.ToCharArray(); + charArray.LSDRadixSort(); - return new String(charArray); - } + return new String(charArray); + } - /// - /// Extension method for sorting character arrays, in place. - /// - public static void LSDRadixSort(this char[] source) - { - if (source == null || source.Length <= 1) - return; + /// + /// Extension method for sorting character arrays, in place. + /// + public static void LSDRadixSort(this char[] source) + { + if (source == null || source.Length <= 1) + return; - // extend ASCII alphabet size - int asciiSize = 256; + // extend ASCII alphabet size + int asciiSize = 256; - int length = source.Length; - char[] auxiliary = new char[length]; + int length = source.Length; + char[] auxiliary = new char[length]; + + // compute frequency counts + int[] count = new int[asciiSize + 1]; + + for (int i = 0; i < length; i++) + count[source[i] + 1]++; + + // compute cumulates + for (int r = 0; r < asciiSize; r++) + count[r + 1] += count[r]; + + // move data + for (int i = 0; i < length; i++) + auxiliary[count[source[i]]++] = source[i]; + + // copy back + for (int i = 0; i < length; i++) + source[i] = auxiliary[i]; + } + + /// + /// Extension method for sorting collections of strings of the same width, in place. + /// + public static void LSDRadixSort(this IList collection, int stringFixedWidth) + { + // Validate input + if (collection == null || collection.Count <= 1) + return; + for (int i = 0; i < collection.Count; ++i) + if (collection[i] == null || collection[i].Length != stringFixedWidth) + throw new InvalidOperationException("Not all strings have the same width"); + + // extend ASCII alphabet size + int asciiSize = 256; + + int stringsCount = collection.Count; + string[] auxiliary = new string[stringsCount]; + + for (int d = stringFixedWidth - 1; d >= 0; d--) + { // compute frequency counts int[] count = new int[asciiSize + 1]; - for (int i = 0; i < length; i++) - count[source[i] + 1]++; + for (int i = 0; i < stringsCount; i++) + count[collection[i][d] + 1]++; // compute cumulates for (int r = 0; r < asciiSize; r++) count[r + 1] += count[r]; // move data - for (int i = 0; i < length; i++) - auxiliary[count[source[i]]++] = source[i]; + for (int i = 0; i < stringsCount; i++) + auxiliary[count[collection[i][d]]++] = collection[i]; // copy back - for (int i = 0; i < length; i++) - source[i] = auxiliary[i]; - } - - - /// - /// Extension method for sorting collections of strings of the same width, in place. - /// - public static void LSDRadixSort(this IList collection, int stringFixedWidth) - { - // Validate input - if (collection == null || collection.Count <= 1) - return; - for (int i = 0; i < collection.Count; ++i) - if (collection[i] == null || collection[i].Length != stringFixedWidth) - throw new InvalidOperationException("Not all strings have the same width"); - - // extend ASCII alphabet size - int asciiSize = 256; - - int stringsCount = collection.Count; - string[] auxiliary = new string[stringsCount]; - - for (int d = stringFixedWidth - 1; d >= 0; d--) - { - // compute frequency counts - int[] count = new int[asciiSize + 1]; - - for (int i = 0; i < stringsCount; i++) - count[collection[i][d] + 1]++; - - // compute cumulates - for (int r = 0; r < asciiSize; r++) - count[r + 1] += count[r]; - - // move data - for (int i = 0; i < stringsCount; i++) - auxiliary[count[collection[i][d]]++] = collection[i]; - - // copy back - for (int i = 0; i < stringsCount; i++) - collection[i] = auxiliary[i]; - } + for (int i = 0; i < stringsCount; i++) + collection[i] = auxiliary[i]; } } -} +} \ No newline at end of file diff --git a/Algorithms/Sorting/MergeSorter.cs b/Algorithms/Sorting/MergeSorter.cs index 6f1a2038..0ffff857 100644 --- a/Algorithms/Sorting/MergeSorter.cs +++ b/Algorithms/Sorting/MergeSorter.cs @@ -1,83 +1,81 @@ using System.Collections.Generic; using Algorithms.Common; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +public static class MergeSorter { - public static class MergeSorter + // + // Public merge-sort API + public static List MergeSort(this List collection, Comparer comparer = null) { - // - // Public merge-sort API - public static List MergeSort(this List collection, Comparer comparer = null) - { - comparer = comparer ?? Comparer.Default; + comparer = comparer ?? Comparer.Default; - return InternalMergeSort(collection, comparer); - } + return InternalMergeSort(collection, comparer); + } - // - // Private static method - // Implements the recursive merge-sort algorithm - private static List InternalMergeSort(List collection, Comparer comparer) + // + // Private static method + // Implements the recursive merge-sort algorithm + private static List InternalMergeSort(List collection, Comparer comparer) + { + if (collection.Count < 2) { - if (collection.Count < 2) - { - return collection; - } + return collection; + } - int midIndex = collection.Count / 2; + int midIndex = collection.Count / 2; - var leftCollection = collection.GetRange(0, midIndex); - var rightCollection = collection.GetRange(midIndex, collection.Count - midIndex); + var leftCollection = collection.GetRange(0, midIndex); + var rightCollection = collection.GetRange(midIndex, collection.Count - midIndex); - leftCollection = InternalMergeSort(leftCollection, comparer); - rightCollection = InternalMergeSort(rightCollection, comparer); + leftCollection = InternalMergeSort(leftCollection, comparer); + rightCollection = InternalMergeSort(rightCollection, comparer); - return InternalMerge(leftCollection, rightCollection, comparer); - } + return InternalMerge(leftCollection, rightCollection, comparer); + } - // - // Private static method - // Implements the merge function inside the merge-sort - private static List InternalMerge(List leftCollection, List rightCollection, Comparer comparer) - { - int left = 0; - int right = 0; - int index; - int length = leftCollection.Count + rightCollection.Count; + // + // Private static method + // Implements the merge function inside the merge-sort + private static List InternalMerge(List leftCollection, List rightCollection, Comparer comparer) + { + int left = 0; + int right = 0; + int index; + int length = leftCollection.Count + rightCollection.Count; - List result = new List(length); + List result = new List(length); - for (index = 0; right < rightCollection.Count && left < leftCollection.Count; ++index) + for (index = 0; right < rightCollection.Count && left < leftCollection.Count; ++index) + { + if (comparer.Compare(rightCollection[right], leftCollection[left]) <= 0) // rightElement <= leftElement { - if (comparer.Compare(rightCollection[right], leftCollection[left]) <= 0) // rightElement <= leftElement - { - //resultArray.Add(rightCollection[right]); - result.Insert(index, rightCollection[right++]); - } - else - { - //result.Add(leftCollection[left]); - result.Insert(index, leftCollection[left++]); - } + //resultArray.Add(rightCollection[right]); + result.Insert(index, rightCollection[right++]); } - - // - // At most one of left and right might still have elements left - - while (right < rightCollection.Count) + else { - result.Insert(index++, rightCollection[right++]); + //result.Add(leftCollection[left]); + result.Insert(index, leftCollection[left++]); } + } - while (left < leftCollection.Count) - { - result.Insert(index++, leftCollection[left++]); - } + // + // At most one of left and right might still have elements left + + while (right < rightCollection.Count) + { + result.Insert(index++, rightCollection[right++]); + } - return result; + while (left < leftCollection.Count) + { + result.Insert(index++, leftCollection[left++]); } - } -} + return result; + } +} \ No newline at end of file diff --git a/Algorithms/Sorting/OddEvenSorter.cs b/Algorithms/Sorting/OddEvenSorter.cs index 4b936b0c..d917e9b4 100644 --- a/Algorithms/Sorting/OddEvenSorter.cs +++ b/Algorithms/Sorting/OddEvenSorter.cs @@ -1,75 +1,74 @@ using System.Collections.Generic; using Algorithms.Common; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +/// +/// Based on bubble sort +/// +public static class OddEvenSorter { + public static void OddEvenSort(this IList collection, Comparer comparer = null) + { + comparer = comparer ?? Comparer.Default; + collection.OddEvenSortAscending(comparer); + } + /// - /// Based on bubble sort + /// Public API: Sorts ascending /// - public static class OddEvenSorter + public static void OddEvenSortAscending(this IList collection, Comparer comparer) { - public static void OddEvenSort(this IList collection, Comparer comparer = null) + bool sorted = false; + while (!sorted) { - comparer = comparer ?? Comparer.Default; - collection.OddEvenSortAscending(comparer); - } - - /// - /// Public API: Sorts ascending - /// - public static void OddEvenSortAscending(this IList collection, Comparer comparer) - { - bool sorted = false; - while (!sorted) + sorted = true; + for (var i = 1; i < collection.Count - 1; i += 2) { - sorted = true; - for (var i = 1; i < collection.Count - 1; i += 2) + if (comparer.Compare(collection[i], collection[i + 1]) > 0) { - if (comparer.Compare(collection[i], collection[i + 1]) > 0) - { - collection.Swap(i, i + 1); - sorted = false; - } + collection.Swap(i, i + 1); + sorted = false; } + } - for (var i = 0; i < collection.Count - 1; i += 2) + for (var i = 0; i < collection.Count - 1; i += 2) + { + if (comparer.Compare(collection[i], collection[i + 1]) > 0) { - if (comparer.Compare(collection[i], collection[i + 1]) > 0) - { - collection.Swap(i, i + 1); - sorted = false; - } + collection.Swap(i, i + 1); + sorted = false; } } } + } - /// - /// Public API: Sorts descending - /// - public static void OddEvenSortDescending(this IList collection, Comparer comparer) + /// + /// Public API: Sorts descending + /// + public static void OddEvenSortDescending(this IList collection, Comparer comparer) + { + bool sorted = false; + while (!sorted) { - bool sorted = false; - while (!sorted) + sorted = true; + for (var i = 1; i < collection.Count - 1; i += 2) { - sorted = true; - for (var i = 1; i < collection.Count - 1; i += 2) + if (comparer.Compare(collection[i], collection[i + 1]) < 0) { - if (comparer.Compare(collection[i], collection[i + 1]) < 0) - { - collection.Swap(i, i + 1); - sorted = false; - } + collection.Swap(i, i + 1); + sorted = false; } + } - for (var i = 0; i < collection.Count - 1; i += 2) + for (var i = 0; i < collection.Count - 1; i += 2) + { + if (comparer.Compare(collection[i], collection[i + 1]) < 0) { - if (comparer.Compare(collection[i], collection[i + 1]) < 0) - { - collection.Swap(i, i + 1); - sorted = false; - } + collection.Swap(i, i + 1); + sorted = false; } } } } -} +} \ No newline at end of file diff --git a/Algorithms/Sorting/PigeonHoleSorter.cs b/Algorithms/Sorting/PigeonHoleSorter.cs index 1c922abd..d81959c2 100644 --- a/Algorithms/Sorting/PigeonHoleSorter.cs +++ b/Algorithms/Sorting/PigeonHoleSorter.cs @@ -1,61 +1,60 @@ using System.Collections.Generic; using System.Linq; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +/// +/// Only support IList Sort +/// Also called CountSort (not CountingSort) +/// +public static class PigeonHoleSorter { - /// - /// Only support IList Sort - /// Also called CountSort (not CountingSort) - /// - public static class PigeonHoleSorter + public static void PigeonHoleSort(this IList collection) + { + collection.PigeonHoleSortAscending(); + } + + public static void PigeonHoleSortAscending(this IList collection) { - public static void PigeonHoleSort(this IList collection) + int min = collection.Min(); + int max = collection.Max(); + int size = max - min + 1; + int[] holes = new int[size]; + foreach (int x in collection) { - collection.PigeonHoleSortAscending(); + holes[x - min]++; } - - public static void PigeonHoleSortAscending(this IList collection) + + int i = 0; + for (int count = 0; count < size; count++) { - int min = collection.Min(); - int max = collection.Max(); - int size = max - min + 1; - int[] holes = new int[size]; - foreach (int x in collection) + while (holes[count]-- > 0) { - holes[x - min]++; + collection[i] = count + min; + i++; } - - int i = 0; - for (int count = 0; count < size; count++) - { - while (holes[count]-- > 0) - { - collection[i] = count + min; - i++; - } - } - } + } + } - public static void PigeonHoleSortDescending(this IList collection) + public static void PigeonHoleSortDescending(this IList collection) + { + int min = collection.Min(); + int max = collection.Max(); + int size = max - min + 1; + int[] holes = new int[size]; + foreach (int x in collection) { - int min = collection.Min(); - int max = collection.Max(); - int size = max - min + 1; - int[] holes = new int[size]; - foreach (int x in collection) - { - holes[x - min]++; - } + holes[x - min]++; + } - int i = 0; - for (int count = size-1; count >= 0; count--) + int i = 0; + for (int count = size-1; count >= 0; count--) + { + while (holes[count]-- >0) { - while (holes[count]-- >0) - { - collection[i] = count + min; - i++; - } + collection[i] = count + min; + i++; } } } -} +} \ No newline at end of file diff --git a/Algorithms/Sorting/QuickSorter.cs b/Algorithms/Sorting/QuickSorter.cs index 291485be..d67ebee3 100644 --- a/Algorithms/Sorting/QuickSorter.cs +++ b/Algorithms/Sorting/QuickSorter.cs @@ -1,72 +1,69 @@ using System.Collections.Generic; using Algorithms.Common; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +public static class QuickSorter { - public static class QuickSorter + // + // The public APIs for the quick sort algorithm. + public static void QuickSort(this IList collection, Comparer comparer = null) { - // - // The public APIs for the quick sort algorithm. - public static void QuickSort(this IList collection, Comparer comparer = null) - { - int startIndex = 0; - int endIndex = collection.Count - 1; + int startIndex = 0; + int endIndex = collection.Count - 1; - // - // If the comparer is Null, then initialize it using a default typed comparer - comparer = comparer ?? Comparer.Default; + // + // If the comparer is Null, then initialize it using a default typed comparer + comparer = comparer ?? Comparer.Default; - collection.InternalQuickSort(startIndex, endIndex, comparer); - } + collection.InternalQuickSort(startIndex, endIndex, comparer); + } + // + // Private static method + // The recursive quick sort algorithm + private static void InternalQuickSort(this IList collection, int leftmostIndex, int rightmostIndex, Comparer comparer) + { // - // Private static method - // The recursive quick sort algorithm - private static void InternalQuickSort(this IList collection, int leftmostIndex, int rightmostIndex, Comparer comparer) + // Recursive call check + if (leftmostIndex < rightmostIndex) { - // - // Recursive call check - if (leftmostIndex < rightmostIndex) - { - int wallIndex = collection.InternalPartition(leftmostIndex, rightmostIndex, comparer); - collection.InternalQuickSort(leftmostIndex, wallIndex - 1, comparer); - collection.InternalQuickSort(wallIndex + 1, rightmostIndex, comparer); - } + int wallIndex = collection.InternalPartition(leftmostIndex, rightmostIndex, comparer); + collection.InternalQuickSort(leftmostIndex, wallIndex - 1, comparer); + collection.InternalQuickSort(wallIndex + 1, rightmostIndex, comparer); } + } - // - // Private static method - // The partition function, used in the quick sort algorithm - private static int InternalPartition(this IList collection, int leftmostIndex, int rightmostIndex, Comparer comparer) - { - int wallIndex, pivotIndex; + // + // Private static method + // The partition function, used in the quick sort algorithm + private static int InternalPartition(this IList collection, int leftmostIndex, int rightmostIndex, Comparer comparer) + { + int wallIndex, pivotIndex; - // Choose the pivot - pivotIndex = rightmostIndex; - T pivotValue = collection[pivotIndex]; + // Choose the pivot + pivotIndex = rightmostIndex; + T pivotValue = collection[pivotIndex]; - // Compare remaining array elements against pivotValue - wallIndex = leftmostIndex; + // Compare remaining array elements against pivotValue + wallIndex = leftmostIndex; - // Loop until pivot: exclusive! - for (int i = leftmostIndex; i <= rightmostIndex - 1; i++) + // Loop until pivot: exclusive! + for (int i = leftmostIndex; i <= rightmostIndex - 1; i++) + { + // check if collection[i] <= pivotValue + if (comparer.Compare(collection[i], pivotValue) <= 0) { - // check if collection[i] <= pivotValue - if (comparer.Compare(collection[i], pivotValue) <= 0) - { - collection.Swap(i, wallIndex); - wallIndex++; - } + collection.Swap(i, wallIndex); + wallIndex++; } - - collection.Swap(wallIndex, pivotIndex); - - return wallIndex; } - } + collection.Swap(wallIndex, pivotIndex); -} + return wallIndex; + } +} \ No newline at end of file diff --git a/Algorithms/Sorting/SelectionSorter.cs b/Algorithms/Sorting/SelectionSorter.cs index f770958f..7c4298ef 100644 --- a/Algorithms/Sorting/SelectionSorter.cs +++ b/Algorithms/Sorting/SelectionSorter.cs @@ -1,48 +1,47 @@ using System.Collections.Generic; using Algorithms.Common; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +public static class SelectionSorter { - public static class SelectionSorter + public static void SelectionSort(this IList collection, Comparer comparer = null) { - public static void SelectionSort(this IList collection, Comparer comparer = null) - { - comparer = comparer ?? Comparer.Default; - collection.SelectionSortAscending(comparer); - } + comparer = comparer ?? Comparer.Default; + collection.SelectionSortAscending(comparer); + } - /// - /// Public API: Sorts ascending - /// - public static void SelectionSortAscending(this IList collection, Comparer comparer) - { - int i; - for(i=0;i + /// Public API: Sorts ascending + /// + public static void SelectionSortAscending(this IList collection, Comparer comparer) + { + int i; + for(i=0;i - /// Public API: Sorts ascending - /// - public static void SelectionSortDescending(this IList collection, Comparer comparer) + /// + /// Public API: Sorts ascending + /// + public static void SelectionSortDescending(this IList collection, Comparer comparer) + { + int i; + for (i = collection.Count-1; i >0; i--) { - int i; - for (i = collection.Count-1; i >0; i--) + int max = i; + for (int j = 0; j <=i; j++) { - int max = i; - for (int j = 0; j <=i; j++) - { - if (comparer.Compare(collection[j], collection[max]) < 0) - max = j; - } - collection.Swap(i, max); + if (comparer.Compare(collection[j], collection[max]) < 0) + max = j; } + collection.Swap(i, max); } } -} +} \ No newline at end of file diff --git a/Algorithms/Sorting/ShellSorter.cs b/Algorithms/Sorting/ShellSorter.cs index 654f3588..42689a73 100644 --- a/Algorithms/Sorting/ShellSorter.cs +++ b/Algorithms/Sorting/ShellSorter.cs @@ -1,58 +1,57 @@ using System.Collections.Generic; using Algorithms.Common; -namespace Algorithms.Sorting +namespace Algorithms.Sorting; + +public static class ShellSorter { - public static class ShellSorter + public static void ShellSort(this IList collection, Comparer comparer = null) { - public static void ShellSort(this IList collection, Comparer comparer = null) - { - comparer = comparer ?? Comparer.Default; - collection.ShellSortAscending(comparer); - } + comparer = comparer ?? Comparer.Default; + collection.ShellSortAscending(comparer); + } - /// - /// Public API: Sorts ascending - /// - public static void ShellSortAscending(this IList collection, Comparer comparer) + /// + /// Public API: Sorts ascending + /// + public static void ShellSortAscending(this IList collection, Comparer comparer) + { + bool flag = true; + int d = collection.Count; + while (flag || d > 1) { - bool flag = true; - int d = collection.Count; - while (flag || d > 1) + flag = false; + d = (d + 1) / 2; + for (int i = 0; i < collection.Count - d; i++) { - flag = false; - d = (d + 1) / 2; - for (int i = 0; i < collection.Count - d; i++) + if (comparer.Compare(collection[i + d], collection[i]) < 0) { - if (comparer.Compare(collection[i + d], collection[i]) < 0) - { - collection.Swap(i + d, i); - flag = true; - } + collection.Swap(i + d, i); + flag = true; } } } + } - /// - /// Public API: Sorts descending - /// - public static void ShellSortDescending(this IList collection, Comparer comparer) + /// + /// Public API: Sorts descending + /// + public static void ShellSortDescending(this IList collection, Comparer comparer) + { + bool flag = true; + int d = collection.Count; + while (flag || d > 1) { - bool flag = true; - int d = collection.Count; - while (flag || d > 1) + flag = false; + d = (d + 1) / 2; + for (int i = 0; i < collection.Count - d; i++) { - flag = false; - d = (d + 1) / 2; - for (int i = 0; i < collection.Count - d; i++) + if (comparer.Compare(collection[i + d], collection[i])>0) { - if (comparer.Compare(collection[i + d], collection[i])>0) - { - collection.Swap(i+d,i); - flag = true; - } + collection.Swap(i+d,i); + flag = true; } } } } -} +} \ No newline at end of file diff --git a/Algorithms/Strings/EditDistance.cs b/Algorithms/Strings/EditDistance.cs index 9238c8fe..b7fe9d06 100644 --- a/Algorithms/Strings/EditDistance.cs +++ b/Algorithms/Strings/EditDistance.cs @@ -1,89 +1,87 @@ using System; -namespace Algorithms.Strings +namespace Algorithms.Strings; + +/// +/// The Edit Distance computation algorithm. +/// Uses a custom class for receiving the costs. +/// +public static class EditDistance { /// - /// The Edit Distance computation algorithm. - /// Uses a custom class for receiving the costs. + /// Computes the Minimum Edit Distance between two strings. /// - public static class EditDistance + public static Int64 GetMinDistance(string source, string destination, EditDistanceCostsMap distances) { - /// - /// Computes the Minimum Edit Distance between two strings. - /// - public static Int64 GetMinDistance(string source, string destination, EditDistanceCostsMap distances) - { - // Validate parameters and TCost. - if (source == null || destination == null || distances == null) - throw new ArgumentNullException("Some of the parameters are null."); - if (source == destination) - return 0; + // Validate parameters and TCost. + if (source == null || destination == null || distances == null) + throw new ArgumentNullException("Some of the parameters are null."); + if (source == destination) + return 0; - // Dynamic Programming 3D Table - long[,] dynamicTable = new long[source.Length + 1, destination.Length + 1]; + // Dynamic Programming 3D Table + long[,] dynamicTable = new long[source.Length + 1, destination.Length + 1]; - // Initialize table - for (int i = 0; i <= source.Length; ++i) - dynamicTable[i, 0] = i; + // Initialize table + for (int i = 0; i <= source.Length; ++i) + dynamicTable[i, 0] = i; - for (int i = 0; i <= destination.Length; ++i) - dynamicTable[0, i] = i; + for (int i = 0; i <= destination.Length; ++i) + dynamicTable[0, i] = i; - // Compute min edit distance cost - for (int i = 1; i <= source.Length; ++i) + // Compute min edit distance cost + for (int i = 1; i <= source.Length; ++i) + { + for (int j = 1; j <= destination.Length; ++j) { - for (int j = 1; j <= destination.Length; ++j) + if (source[i - 1] == destination[j - 1]) + { + dynamicTable[i, j] = dynamicTable[i - 1, j - 1]; + } + else { - if (source[i - 1] == destination[j - 1]) - { - dynamicTable[i, j] = dynamicTable[i - 1, j - 1]; - } - else - { - long insert = dynamicTable[i, j - 1] + distances.InsertionCost; - long delete = dynamicTable[i - 1, j] + distances.DeletionCost; - long substitute = dynamicTable[i - 1, j - 1] + distances.SubstitutionCost; + long insert = dynamicTable[i, j - 1] + distances.InsertionCost; + long delete = dynamicTable[i - 1, j] + distances.DeletionCost; + long substitute = dynamicTable[i - 1, j - 1] + distances.SubstitutionCost; - dynamicTable[i, j] = Math.Min(insert, Math.Min(delete, substitute)); - } + dynamicTable[i, j] = Math.Min(insert, Math.Min(delete, substitute)); } } - - // Get min edit distance cost - return dynamicTable[source.Length, destination.Length]; } - /// - /// Overloaded method for 32-bits Integer Distances - /// - public static Int32 GetMinDistance(string source, string destination, EditDistanceCostsMap distances) - { - // Validate parameters and TCost. - if (source == null || destination == null || distances == null) - throw new ArgumentNullException("Some of the parameters are null."); - var longDistance = new EditDistanceCostsMap( - insertionCost: Convert.ToInt64(distances.InsertionCost), - deletionCost: Convert.ToInt64(distances.DeletionCost), - substitutionCost: Convert.ToInt64(distances.InsertionCost)); - - return Convert.ToInt32(GetMinDistance(source, destination, longDistance)); - } + // Get min edit distance cost + return dynamicTable[source.Length, destination.Length]; + } - /// - /// Overloaded method for 16-bits Integer Distances - /// - public static Int16 GetMinDistance(string source, string destination, EditDistanceCostsMap distances) - { - // Validate parameters and TCost. - if (source == null || destination == null || distances == null) - throw new ArgumentNullException("Some of the parameters are null."); - var longDistance = new EditDistanceCostsMap( - insertionCost: Convert.ToInt64(distances.InsertionCost), - deletionCost: Convert.ToInt64(distances.DeletionCost), - substitutionCost: Convert.ToInt64(distances.InsertionCost)); + /// + /// Overloaded method for 32-bits Integer Distances + /// + public static Int32 GetMinDistance(string source, string destination, EditDistanceCostsMap distances) + { + // Validate parameters and TCost. + if (source == null || destination == null || distances == null) + throw new ArgumentNullException("Some of the parameters are null."); + var longDistance = new EditDistanceCostsMap( + insertionCost: Convert.ToInt64(distances.InsertionCost), + deletionCost: Convert.ToInt64(distances.DeletionCost), + substitutionCost: Convert.ToInt64(distances.InsertionCost)); - return Convert.ToInt16(GetMinDistance(source, destination, longDistance)); - } + return Convert.ToInt32(GetMinDistance(source, destination, longDistance)); } -} + /// + /// Overloaded method for 16-bits Integer Distances + /// + public static Int16 GetMinDistance(string source, string destination, EditDistanceCostsMap distances) + { + // Validate parameters and TCost. + if (source == null || destination == null || distances == null) + throw new ArgumentNullException("Some of the parameters are null."); + var longDistance = new EditDistanceCostsMap( + insertionCost: Convert.ToInt64(distances.InsertionCost), + deletionCost: Convert.ToInt64(distances.DeletionCost), + substitutionCost: Convert.ToInt64(distances.InsertionCost)); + + return Convert.ToInt16(GetMinDistance(source, destination, longDistance)); + } +} \ No newline at end of file diff --git a/Algorithms/Strings/EditDistanceCostsMap.cs b/Algorithms/Strings/EditDistanceCostsMap.cs index 62493472..9684a3bf 100644 --- a/Algorithms/Strings/EditDistanceCostsMap.cs +++ b/Algorithms/Strings/EditDistanceCostsMap.cs @@ -1,29 +1,28 @@ using System; using Algorithms.Common; -namespace Algorithms.Strings +namespace Algorithms.Strings; + +/// +/// Edit Distance Costs Map. +/// Helper class used with the EditDistance class. +/// +public class EditDistanceCostsMap where TCost : IComparable, IEquatable { + public TCost DeletionCost { get; set; } + public TCost InsertionCost { get; set; } + public TCost SubstitutionCost { get; set; } + /// - /// Edit Distance Costs Map. - /// Helper class used with the EditDistance class. + /// CONSTRUCTOR /// - public class EditDistanceCostsMap where TCost : IComparable, IEquatable + public EditDistanceCostsMap(TCost insertionCost, TCost deletionCost, TCost substitutionCost) { - public TCost DeletionCost { get; set; } - public TCost InsertionCost { get; set; } - public TCost SubstitutionCost { get; set; } - - /// - /// CONSTRUCTOR - /// - public EditDistanceCostsMap(TCost insertionCost, TCost deletionCost, TCost substitutionCost) - { - if (false == default(TCost).IsNumber()) - throw new InvalidOperationException("Invalid cost type TCost. Please choose TCost to be a number."); + if (false == default(TCost).IsNumber()) + throw new InvalidOperationException("Invalid cost type TCost. Please choose TCost to be a number."); - DeletionCost = deletionCost; - InsertionCost = insertionCost; - SubstitutionCost = substitutionCost; - } + DeletionCost = deletionCost; + InsertionCost = insertionCost; + SubstitutionCost = substitutionCost; } -} +} \ No newline at end of file diff --git a/Algorithms/Strings/Permutations.cs b/Algorithms/Strings/Permutations.cs index fe15d8a9..3f83eb00 100644 --- a/Algorithms/Strings/Permutations.cs +++ b/Algorithms/Strings/Permutations.cs @@ -5,90 +5,88 @@ using System; using System.Collections.Generic; -namespace Algorithms.Strings +namespace Algorithms.Strings; + +public static class Permutations { - public static class Permutations + /// + /// Private Helper. Computes permutations recursively for string source. + /// + private static HashSet _permutations(string source) { - /// - /// Private Helper. Computes permutations recursively for string source. - /// - private static HashSet _permutations(string source) + var perms = new HashSet(); + + if (source.Length == 1) + { + perms.Add(source); + } + else if (source.Length > 1) { - var perms = new HashSet(); + int lastIndex = source.Length - 1; + string lastChar = Convert.ToString(source[lastIndex]); + string substring = source.Substring(0, lastIndex); + perms = _mergePermutations(_permutations(substring), lastChar); + } - if (source.Length == 1) - { - perms.Add(source); - } - else if (source.Length > 1) - { - int lastIndex = source.Length - 1; - string lastChar = Convert.ToString(source[lastIndex]); - string substring = source.Substring(0, lastIndex); - perms = _mergePermutations(_permutations(substring), lastChar); - } + return perms; + } - return perms; - } + /// + /// Private helper. Merges a set of permutations with a character. + /// + private static HashSet _mergePermutations(HashSet permutations, string character) + { + var merges = new HashSet(); - /// - /// Private helper. Merges a set of permutations with a character. - /// - private static HashSet _mergePermutations(HashSet permutations, string character) + foreach (var perm in permutations) { - var merges = new HashSet(); - - foreach (var perm in permutations) + for (int i = 0; i < perm.Length; ++i) { - for (int i = 0; i < perm.Length; ++i) - { - var newMerge = perm.Insert(i, character); + var newMerge = perm.Insert(i, character); - if (!merges.Contains(newMerge)) - merges.Add(newMerge); - } + if (!merges.Contains(newMerge)) + merges.Add(newMerge); } - - return merges; } - /// - /// Computes the permutations of a string. - /// - public static HashSet ComputeDistinct(string source) - { - return _permutations(source); - } + return merges; + } - /// - /// Determines if the Other string is an anargram of the Source string. - /// - public static bool IsAnargram(string source, string other) - { - if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(other)) - return false; - if (source.Length != other.Length) - return false; - if (source.Equals(other, StringComparison.Ordinal)) - return true; + /// + /// Computes the permutations of a string. + /// + public static HashSet ComputeDistinct(string source) + { + return _permutations(source); + } - int len = source.Length; - // Hash set which will contains all the characters present in input source. - var hashSetSourceChars = new HashSet(); - var hashSetOtherChars = new HashSet(); - for (int i = 0; i < len; i++) - { - hashSetSourceChars.Add(source[i]); - hashSetOtherChars.Add(other[i]); - } - for (int i = 0; i < len; i++) - { - // Inputs are not Anargram if characers from *other are not present in *source. - if (!hashSetSourceChars.Contains(other[i])) return false; - if (!hashSetOtherChars.Contains(source[i])) return false; - } + /// + /// Determines if the Other string is an anargram of the Source string. + /// + public static bool IsAnargram(string source, string other) + { + if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(other)) + return false; + if (source.Length != other.Length) + return false; + if (source.Equals(other, StringComparison.Ordinal)) return true; + + int len = source.Length; + // Hash set which will contains all the characters present in input source. + var hashSetSourceChars = new HashSet(); + var hashSetOtherChars = new HashSet(); + for (int i = 0; i < len; i++) + { + hashSetSourceChars.Add(source[i]); + hashSetOtherChars.Add(other[i]); } + for (int i = 0; i < len; i++) + { + // Inputs are not Anargram if characers from *other are not present in *source. + if (!hashSetSourceChars.Contains(other[i])) return false; + if (!hashSetOtherChars.Contains(source[i])) return false; + } + return true; } -} - +} \ No newline at end of file diff --git a/Algorithms/Trees/BinaryTreeIterativeWalker.cs b/Algorithms/Trees/BinaryTreeIterativeWalker.cs index 7c793a8d..6d0317ed 100644 --- a/Algorithms/Trees/BinaryTreeIterativeWalker.cs +++ b/Algorithms/Trees/BinaryTreeIterativeWalker.cs @@ -1,25 +1,23 @@ -namespace Algorithms.Trees +namespace Algorithms.Trees; + +/// +/// Simple Iterative Tree Traversal and Search Algorithms. +/// +public static class BinaryTreeIterativeWalker { /// - /// Simple Iterative Tree Traversal and Search Algorithms. + /// Specifies the mode of travelling through the tree. /// - public static class BinaryTreeIterativeWalker + public enum TraversalMode { - /// - /// Specifies the mode of travelling through the tree. - /// - public enum TraversalMode - { - InOrder = 0, - PreOrder = 1, - PostOrder = 2 - } - - - /************************************************************************************ - * PRIVATE HELPERS SECTION - * - */ + InOrder = 0, + PreOrder = 1, + PostOrder = 2 } -} + + /************************************************************************************ + * PRIVATE HELPERS SECTION + * + */ +} \ No newline at end of file diff --git a/Algorithms/Trees/BinaryTreeRecursiveWalker.cs b/Algorithms/Trees/BinaryTreeRecursiveWalker.cs index e1f95c7d..df3bdab7 100644 --- a/Algorithms/Trees/BinaryTreeRecursiveWalker.cs +++ b/Algorithms/Trees/BinaryTreeRecursiveWalker.cs @@ -3,278 +3,277 @@ using DataStructures.Trees; using Algorithms.Common; -namespace Algorithms.Trees +namespace Algorithms.Trees; + +/// +/// Simple Recursive Tree Traversal and Search Algorithms. +/// +public static class BinaryTreeRecursiveWalker { /// - /// Simple Recursive Tree Traversal and Search Algorithms. + /// Specifies the mode of travelling through the tree. /// - public static class BinaryTreeRecursiveWalker + public enum TraversalMode { - /// - /// Specifies the mode of travelling through the tree. - /// - public enum TraversalMode - { - InOrder = 0, - PreOrder = 1, - PostOrder = 2 - } + InOrder = 0, + PreOrder = 1, + PostOrder = 2 + } - /************************************************************************************ - * PRIVATE HELPERS SECTION - * - */ + /************************************************************************************ + * PRIVATE HELPERS SECTION + * + */ - /// - /// Private helper method for Preorder Traversal. - /// - private static void PreOrderVisitor(BSTNode BinaryTreeRoot, Action Action) where T : IComparable - { - if (BinaryTreeRoot == null) - return; + /// + /// Private helper method for Preorder Traversal. + /// + private static void PreOrderVisitor(BSTNode BinaryTreeRoot, Action Action) where T : IComparable + { + if (BinaryTreeRoot == null) + return; - Action(BinaryTreeRoot.Value); - PreOrderVisitor(BinaryTreeRoot.LeftChild, Action); - PreOrderVisitor(BinaryTreeRoot.RightChild, Action); - } + Action(BinaryTreeRoot.Value); + PreOrderVisitor(BinaryTreeRoot.LeftChild, Action); + PreOrderVisitor(BinaryTreeRoot.RightChild, Action); + } + + /// + /// Private helper method for Inorder Traversal. + /// + private static void InOrderVisitor(BSTNode BinaryTreeRoot, Action Action) where T : IComparable + { + if (BinaryTreeRoot == null) + return; + + InOrderVisitor(BinaryTreeRoot.LeftChild, Action); + Action(BinaryTreeRoot.Value); + InOrderVisitor(BinaryTreeRoot.RightChild, Action); + } - /// - /// Private helper method for Inorder Traversal. - /// - private static void InOrderVisitor(BSTNode BinaryTreeRoot, Action Action) where T : IComparable + /// + /// Private helper method for Preorder Traversal. + /// + private static void PostOrderVisitor(BSTNode BinaryTreeRoot, Action Action) where T : IComparable + { + if (BinaryTreeRoot == null) + return; + + PostOrderVisitor(BinaryTreeRoot.LeftChild, Action); + PostOrderVisitor(BinaryTreeRoot.RightChild, Action); + Action(BinaryTreeRoot.Value); + } + + /// + /// Private helper method for Preorder Searcher. + /// + private static bool PreOrderSearcher(BSTNode BinaryTreeRoot, T Value, bool IsBinarySearchTree=false) where T : IComparable + { + var current = BinaryTreeRoot.Value; + var hasLeft = BinaryTreeRoot.HasLeftChild; + var hasRight = BinaryTreeRoot.HasRightChild; + + if (current.IsEqualTo(Value)) + return true; + + if (IsBinarySearchTree == true) { - if (BinaryTreeRoot == null) - return; + if (BinaryTreeRoot.HasLeftChild && current.IsGreaterThan(Value)) + return PreOrderSearcher(BinaryTreeRoot.LeftChild, Value); - InOrderVisitor(BinaryTreeRoot.LeftChild, Action); - Action(BinaryTreeRoot.Value); - InOrderVisitor(BinaryTreeRoot.RightChild, Action); + if (BinaryTreeRoot.HasRightChild && current.IsLessThan(Value)) + return PreOrderSearcher(BinaryTreeRoot.RightChild, Value); } - - /// - /// Private helper method for Preorder Traversal. - /// - private static void PostOrderVisitor(BSTNode BinaryTreeRoot, Action Action) where T : IComparable + else { - if (BinaryTreeRoot == null) - return; + if (hasLeft && PreOrderSearcher(BinaryTreeRoot.LeftChild, Value) == true) + return true; - PostOrderVisitor(BinaryTreeRoot.LeftChild, Action); - PostOrderVisitor(BinaryTreeRoot.RightChild, Action); - Action(BinaryTreeRoot.Value); + if (hasRight && PreOrderSearcher(BinaryTreeRoot.RightChild, Value) == true) + return true; } - /// - /// Private helper method for Preorder Searcher. - /// - private static bool PreOrderSearcher(BSTNode BinaryTreeRoot, T Value, bool IsBinarySearchTree=false) where T : IComparable + return false; + } + + /// + /// Private helper method for Inorder Searcher. + /// + private static bool InOrderSearcher(BSTNode BinaryTreeRoot, T Value, bool IsBinarySearchTree=false) where T : IComparable + { + var current = BinaryTreeRoot.Value; + var hasLeft = BinaryTreeRoot.HasLeftChild; + var hasRight = BinaryTreeRoot.HasRightChild; + + if (IsBinarySearchTree == true) { - var current = BinaryTreeRoot.Value; - var hasLeft = BinaryTreeRoot.HasLeftChild; - var hasRight = BinaryTreeRoot.HasRightChild; + if (hasLeft && current.IsGreaterThan(Value)) + return InOrderSearcher(BinaryTreeRoot.LeftChild, Value); if (current.IsEqualTo(Value)) return true; - if (IsBinarySearchTree == true) - { - if (BinaryTreeRoot.HasLeftChild && current.IsGreaterThan(Value)) - return PreOrderSearcher(BinaryTreeRoot.LeftChild, Value); - - if (BinaryTreeRoot.HasRightChild && current.IsLessThan(Value)) - return PreOrderSearcher(BinaryTreeRoot.RightChild, Value); - } - else - { - if (hasLeft && PreOrderSearcher(BinaryTreeRoot.LeftChild, Value) == true) - return true; + if (hasRight && current.IsLessThan(Value)) + return InOrderSearcher(BinaryTreeRoot.RightChild, Value); + } + else + { + if (hasLeft && InOrderSearcher(BinaryTreeRoot.LeftChild, Value) == true) + return true; - if (hasRight && PreOrderSearcher(BinaryTreeRoot.RightChild, Value) == true) - return true; - } + if (current.IsEqualTo(Value)) + return true; - return false; + if (hasRight && InOrderSearcher(BinaryTreeRoot.RightChild, Value) == true) + return true; } - /// - /// Private helper method for Inorder Searcher. - /// - private static bool InOrderSearcher(BSTNode BinaryTreeRoot, T Value, bool IsBinarySearchTree=false) where T : IComparable + return false; + } + + /// + /// Private helper method for Inorder Searcher. + /// + private static bool PostOrderSearcher(BSTNode BinaryTreeRoot, T Value, bool IsBinarySearchTree=false) where T : IComparable + { + var current = BinaryTreeRoot.Value; + var hasLeft = BinaryTreeRoot.HasLeftChild; + var hasRight = BinaryTreeRoot.HasRightChild; + + if (IsBinarySearchTree == true) { - var current = BinaryTreeRoot.Value; - var hasLeft = BinaryTreeRoot.HasLeftChild; - var hasRight = BinaryTreeRoot.HasRightChild; - - if (IsBinarySearchTree == true) - { - if (hasLeft && current.IsGreaterThan(Value)) - return InOrderSearcher(BinaryTreeRoot.LeftChild, Value); - - if (current.IsEqualTo(Value)) - return true; - - if (hasRight && current.IsLessThan(Value)) - return InOrderSearcher(BinaryTreeRoot.RightChild, Value); - } - else - { - if (hasLeft && InOrderSearcher(BinaryTreeRoot.LeftChild, Value) == true) - return true; - - if (current.IsEqualTo(Value)) - return true; - - if (hasRight && InOrderSearcher(BinaryTreeRoot.RightChild, Value) == true) - return true; - } - - return false; - } + if (hasLeft && current.IsGreaterThan(Value)) + return PostOrderSearcher(BinaryTreeRoot.LeftChild, Value); - /// - /// Private helper method for Inorder Searcher. - /// - private static bool PostOrderSearcher(BSTNode BinaryTreeRoot, T Value, bool IsBinarySearchTree=false) where T : IComparable + if (hasRight && current.IsLessThan(Value)) + return PostOrderSearcher(BinaryTreeRoot.RightChild, Value); + + if (current.IsEqualTo(Value)) + return true; + } + else { - var current = BinaryTreeRoot.Value; - var hasLeft = BinaryTreeRoot.HasLeftChild; - var hasRight = BinaryTreeRoot.HasRightChild; - - if (IsBinarySearchTree == true) - { - if (hasLeft && current.IsGreaterThan(Value)) - return PostOrderSearcher(BinaryTreeRoot.LeftChild, Value); - - if (hasRight && current.IsLessThan(Value)) - return PostOrderSearcher(BinaryTreeRoot.RightChild, Value); - - if (current.IsEqualTo(Value)) - return true; - } - else - { - if (hasLeft && PostOrderSearcher(BinaryTreeRoot.LeftChild, Value) == true) - return true; - - if (hasRight && PostOrderSearcher(BinaryTreeRoot.RightChild, Value) == true) - return true; - - if (current.IsEqualTo(Value)) - return true; - } - - return false; + if (hasLeft && PostOrderSearcher(BinaryTreeRoot.LeftChild, Value) == true) + return true; + + if (hasRight && PostOrderSearcher(BinaryTreeRoot.RightChild, Value) == true) + return true; + + if (current.IsEqualTo(Value)) + return true; } + return false; + } + - /************************************************************************************ - * PUBLIC API SECTION - * - */ + /************************************************************************************ + * PUBLIC API SECTION + * + */ - /// - /// Recusrsivley walks the tree and prints the values of all nodes. - /// By default this method traverses the tree in inorder fashion. - /// - public static void PrintAll(BSTNode BinaryTreeRoot, TraversalMode Mode=TraversalMode.InOrder) where T : IComparable - { - if (BinaryTreeRoot == null) - throw new ArgumentNullException("Tree root cannot be null."); + /// + /// Recusrsivley walks the tree and prints the values of all nodes. + /// By default this method traverses the tree in inorder fashion. + /// + public static void PrintAll(BSTNode BinaryTreeRoot, TraversalMode Mode=TraversalMode.InOrder) where T : IComparable + { + if (BinaryTreeRoot == null) + throw new ArgumentNullException("Tree root cannot be null."); - var printAction = new Action((T nodeValue) => - Console.Write(String.Format("{0} ", nodeValue))); + var printAction = new Action((T nodeValue) => + Console.Write(String.Format("{0} ", nodeValue))); - ForEach(BinaryTreeRoot, printAction, Mode); - Console.WriteLine(); - } + ForEach(BinaryTreeRoot, printAction, Mode); + Console.WriteLine(); + } - /// - /// Recursively Visits All nodes in tree applying a given action to all nodes. - /// By default this method traverses the tree in inorder fashion. - /// - public static void ForEach(BSTNode BinaryTreeRoot, Action Action, TraversalMode Mode=TraversalMode.InOrder) where T : IComparable - { - if (BinaryTreeRoot == null) - throw new ArgumentNullException("Tree root cannot be null."); + /// + /// Recursively Visits All nodes in tree applying a given action to all nodes. + /// By default this method traverses the tree in inorder fashion. + /// + public static void ForEach(BSTNode BinaryTreeRoot, Action Action, TraversalMode Mode=TraversalMode.InOrder) where T : IComparable + { + if (BinaryTreeRoot == null) + throw new ArgumentNullException("Tree root cannot be null."); - if (Action == null) - throw new ArgumentNullException("Action Action cannot be null."); - - // Traverse - switch (Mode) - { - case TraversalMode.PreOrder: - PreOrderVisitor(BinaryTreeRoot, Action); - return; - case TraversalMode.InOrder: - InOrderVisitor(BinaryTreeRoot, Action); - return; - case TraversalMode.PostOrder: - PostOrderVisitor(BinaryTreeRoot, Action); - return; - default: - InOrderVisitor(BinaryTreeRoot, Action); - return; - } - } + if (Action == null) + throw new ArgumentNullException("Action Action cannot be null."); - /// - /// Search the tree for the specified value. - /// By default this method traverses the tree in inorder fashion. - /// - public static bool Contains(BSTNode BinaryTreeRoot, T Value, TraversalMode Mode=TraversalMode.InOrder) where T : IComparable + // Traverse + switch (Mode) { - if (BinaryTreeRoot == null) - throw new ArgumentNullException("Tree root cannot be null."); - - // Traverse - // Traverse - switch (Mode) - { - case TraversalMode.PreOrder: - return PreOrderSearcher(BinaryTreeRoot, Value); - case TraversalMode.InOrder: - return InOrderSearcher(BinaryTreeRoot, Value); - case TraversalMode.PostOrder: - return PostOrderSearcher(BinaryTreeRoot, Value); - default: - return InOrderSearcher(BinaryTreeRoot, Value); - } + case TraversalMode.PreOrder: + PreOrderVisitor(BinaryTreeRoot, Action); + return; + case TraversalMode.InOrder: + InOrderVisitor(BinaryTreeRoot, Action); + return; + case TraversalMode.PostOrder: + PostOrderVisitor(BinaryTreeRoot, Action); + return; + default: + InOrderVisitor(BinaryTreeRoot, Action); + return; } + } - /// - /// Search the tree for the specified value. - /// By default this method traverses the tree in inorder fashion. - /// - public static bool BinarySearch(BSTNode BinaryTreeRoot, T Value, TraversalMode Mode=TraversalMode.InOrder) where T : IComparable + /// + /// Search the tree for the specified value. + /// By default this method traverses the tree in inorder fashion. + /// + public static bool Contains(BSTNode BinaryTreeRoot, T Value, TraversalMode Mode=TraversalMode.InOrder) where T : IComparable + { + if (BinaryTreeRoot == null) + throw new ArgumentNullException("Tree root cannot be null."); + + // Traverse + // Traverse + switch (Mode) { - if (BinaryTreeRoot == null) - throw new ArgumentNullException("Tree root cannot be null."); - - // Traverse - // Traverse - switch (Mode) - { - case TraversalMode.PreOrder: - return PreOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree: true); - case TraversalMode.InOrder: - return InOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree: true); - case TraversalMode.PostOrder: - return PostOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree:true); - default: - return InOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree: true); - } + case TraversalMode.PreOrder: + return PreOrderSearcher(BinaryTreeRoot, Value); + case TraversalMode.InOrder: + return InOrderSearcher(BinaryTreeRoot, Value); + case TraversalMode.PostOrder: + return PostOrderSearcher(BinaryTreeRoot, Value); + default: + return InOrderSearcher(BinaryTreeRoot, Value); } + } - /// - /// Search the tree for all matches for a given predicate function. - /// By default this method traverses the tree in inorder fashion. - /// - public static List FindAllMatches(BSTNode BinaryTreeRoot, Predicate Match, TraversalMode Mode=TraversalMode.InOrder) where T : IComparable + /// + /// Search the tree for the specified value. + /// By default this method traverses the tree in inorder fashion. + /// + public static bool BinarySearch(BSTNode BinaryTreeRoot, T Value, TraversalMode Mode=TraversalMode.InOrder) where T : IComparable + { + if (BinaryTreeRoot == null) + throw new ArgumentNullException("Tree root cannot be null."); + + // Traverse + // Traverse + switch (Mode) { - throw new NotImplementedException(); + case TraversalMode.PreOrder: + return PreOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree: true); + case TraversalMode.InOrder: + return InOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree: true); + case TraversalMode.PostOrder: + return PostOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree:true); + default: + return InOrderSearcher(BinaryTreeRoot, Value, IsBinarySearchTree: true); } } -} + /// + /// Search the tree for all matches for a given predicate function. + /// By default this method traverses the tree in inorder fashion. + /// + public static List FindAllMatches(BSTNode BinaryTreeRoot, Predicate Match, TraversalMode Mode=TraversalMode.InOrder) where T : IComparable + { + /// Search the tree for all matches for a given predicate function. + /// By default this method traverses the tree in inorder fashion. + } +} \ No newline at end of file diff --git a/DataStructures/Common/Comparers.cs b/DataStructures/Common/Comparers.cs index 487c9155..f72284b6 100644 --- a/DataStructures/Common/Comparers.cs +++ b/DataStructures/Common/Comparers.cs @@ -1,93 +1,91 @@ using System; using DataStructures.Trees; -namespace DataStructures.Common +namespace DataStructures.Common; + +public static class Comparers { - public static class Comparers + /// + /// Determines if a specific value is a number. + /// + /// true if the value is a number; otherwise, false. + /// Value. + /// The Type of value. + public static bool IsNumber(this T value) { - /// - /// Determines if a specific value is a number. - /// - /// true if the value is a number; otherwise, false. - /// Value. - /// The Type of value. - public static bool IsNumber(this T value) + switch (value) { - switch (value) - { - case sbyte: - case byte: - case short: - case ushort: - case int: - case uint: - case long: - case ulong: - case float: - case double: - case decimal: - return true; - default: - return false; - } + case sbyte: + case byte: + case short: + case ushort: + case int: + case uint: + case long: + case ulong: + case float: + case double: + case decimal: + return true; + default: + return false; } + } - public static bool IsEqualTo(this T firstValue, T secondValue) where T : IComparable - { - return firstValue.Equals(secondValue); - } + public static bool IsEqualTo(this T firstValue, T secondValue) where T : IComparable + { + return firstValue.Equals(secondValue); + } - public static bool IsGreaterThan(this T firstValue, T secondValue) where T : IComparable - { - return firstValue.CompareTo(secondValue) > 0; - } + public static bool IsGreaterThan(this T firstValue, T secondValue) where T : IComparable + { + return firstValue.CompareTo(secondValue) > 0; + } - public static bool IsLessThan(this T firstValue, T secondValue) where T : IComparable - { - return firstValue.CompareTo(secondValue) < 0; - } + public static bool IsLessThan(this T firstValue, T secondValue) where T : IComparable + { + return firstValue.CompareTo(secondValue) < 0; + } - public static bool IsGreaterThanOrEqualTo(this T firstValue, T secondValue) where T : IComparable - { - return firstValue.IsEqualTo(secondValue) || firstValue.IsGreaterThan(secondValue); - } + public static bool IsGreaterThanOrEqualTo(this T firstValue, T secondValue) where T : IComparable + { + return firstValue.IsEqualTo(secondValue) || firstValue.IsGreaterThan(secondValue); + } - public static bool IsLessThanOrEqualTo(this T firstValue, T secondValue) where T : IComparable - { - return firstValue.IsEqualTo(secondValue) || firstValue.IsLessThan(secondValue); - } + public static bool IsLessThanOrEqualTo(this T firstValue, T secondValue) where T : IComparable + { + return firstValue.IsEqualTo(secondValue) || firstValue.IsLessThan(secondValue); + } - // METHODS FOR BINARY SEARCH TREE - // COMPARES THE VALUE OF TWO NODES TOGETHER - private static bool HandleNullCases(BSTNode first, BSTNode second) where T : IComparable - { - return first != null && second != null; - } - - public static bool IsEqualTo(this BSTNode first, BSTNode second) where T : IComparable - { - return HandleNullCases(first, second) && first.Value.CompareTo(second.Value) == 0; - } + // METHODS FOR BINARY SEARCH TREE + // COMPARES THE VALUE OF TWO NODES TOGETHER + private static bool HandleNullCases(BSTNode first, BSTNode second) where T : IComparable + { + return first != null && second != null; + } - public static bool IsGreaterThan(this BSTNode first, BSTNode second) where T : IComparable - { - return HandleNullCases(first, second) && first.Value.CompareTo(second.Value) > 0; - } + public static bool IsEqualTo(this BSTNode first, BSTNode second) where T : IComparable + { + return HandleNullCases(first, second) && first.Value.CompareTo(second.Value) == 0; + } - public static bool IsLessThan(this BSTNode first, BSTNode second) where T : IComparable - { - return HandleNullCases(first, second) && first.Value.CompareTo(second.Value) < 0; - } + public static bool IsGreaterThan(this BSTNode first, BSTNode second) where T : IComparable + { + return HandleNullCases(first, second) && first.Value.CompareTo(second.Value) > 0; + } - public static bool IsLessThanOrEqualTo(this BSTNode first, BSTNode second) where T : IComparable - { - return first.IsEqualTo(second) || first.IsLessThan(second); - } + public static bool IsLessThan(this BSTNode first, BSTNode second) where T : IComparable + { + return HandleNullCases(first, second) && first.Value.CompareTo(second.Value) < 0; + } - public static bool IsGreaterThanOrEqualTo(this BSTNode first, BSTNode second) where T : IComparable - { - return first.IsEqualTo(second) || first.IsGreaterThan(second); - } + public static bool IsLessThanOrEqualTo(this BSTNode first, BSTNode second) where T : IComparable + { + return first.IsEqualTo(second) || first.IsLessThan(second); } -} + public static bool IsGreaterThanOrEqualTo(this BSTNode first, BSTNode second) where T : IComparable + { + return first.IsEqualTo(second) || first.IsGreaterThan(second); + } +} \ No newline at end of file diff --git a/DataStructures/Common/Helpers.cs b/DataStructures/Common/Helpers.cs index 8b34684b..3f6082a7 100644 --- a/DataStructures/Common/Helpers.cs +++ b/DataStructures/Common/Helpers.cs @@ -2,68 +2,66 @@ using System.Collections.Generic; using DataStructures.Lists; -namespace DataStructures.Common +namespace DataStructures.Common; + +public static class Helpers { - public static class Helpers + /// + /// Swap two values in an IList collection given their indexes. + /// + public static void Swap(this IList list, int firstIndex, int secondIndex) { - /// - /// Swap two values in an IList collection given their indexes. - /// - public static void Swap(this IList list, int firstIndex, int secondIndex) - { - if (list.Count < 2 || firstIndex == secondIndex) //This check is not required but Partition function may make many calls so its for perf reason - return; + if (list.Count < 2 || firstIndex == secondIndex) //This check is not required but Partition function may make many calls so its for perf reason + return; - var temp = list[firstIndex]; - list[firstIndex] = list[secondIndex]; - list[secondIndex] = temp; - } + var temp = list[firstIndex]; + list[firstIndex] = list[secondIndex]; + list[secondIndex] = temp; + } - /// - /// Swap two values in an ArrayList collection given their indexes. - /// - public static void Swap(this ArrayList list, int firstIndex, int secondIndex) - { - if (list.Count < 2 || firstIndex == secondIndex) //This check is not required but Partition function may make many calls so its for perf reason - return; + /// + /// Swap two values in an ArrayList collection given their indexes. + /// + public static void Swap(this ArrayList list, int firstIndex, int secondIndex) + { + if (list.Count < 2 || firstIndex == secondIndex) //This check is not required but Partition function may make many calls so its for perf reason + return; - var temp = list[firstIndex]; - list[firstIndex] = list[secondIndex]; - list[secondIndex] = temp; - } + var temp = list[firstIndex]; + list[firstIndex] = list[secondIndex]; + list[secondIndex] = temp; + } - /// - /// Centralize a text. - /// - public static string PadCenter(this string text, int newWidth, char fillerCharacter = ' ') - { - if (string.IsNullOrEmpty(text)) - return text; + /// + /// Centralize a text. + /// + public static string PadCenter(this string text, int newWidth, char fillerCharacter = ' ') + { + if (string.IsNullOrEmpty(text)) + return text; - int length = text.Length; - int charactersToPad = newWidth - length; - if (charactersToPad < 0) throw new ArgumentException("New width must be greater than string length.", "newWidth"); - int padLeft = charactersToPad / 2 + charactersToPad % 2; - //add a space to the left if the string is an odd number - int padRight = charactersToPad / 2; + int length = text.Length; + int charactersToPad = newWidth - length; + if (charactersToPad < 0) throw new ArgumentException("New width must be greater than string length.", "newWidth"); + int padLeft = charactersToPad / 2 + charactersToPad % 2; + //add a space to the left if the string is an odd number + int padRight = charactersToPad / 2; - return new String(fillerCharacter, padLeft) + text + new String(fillerCharacter, padRight); - } + return new String(fillerCharacter, padLeft) + text + new String(fillerCharacter, padRight); + } - /// - /// Populates the specified two-dimensional with a default value. - /// - public static void Populate(this T[,] array, int rows, int columns, T defaultValue = default) + /// + /// Populates the specified two-dimensional with a default value. + /// + public static void Populate(this T[,] array, int rows, int columns, T defaultValue = default) + { + for (int i = 0; i < rows; ++i) { - for (int i = 0; i < rows; ++i) + for (int j = 0; j < columns; ++j) { - for (int j = 0; j < columns; ++j) - { - array[i, j] = defaultValue; - } + array[i, j] = defaultValue; } } - } } \ No newline at end of file diff --git a/DataStructures/Common/PrimesList.cs b/DataStructures/Common/PrimesList.cs index d1e28702..7fd4f428 100644 --- a/DataStructures/Common/PrimesList.cs +++ b/DataStructures/Common/PrimesList.cs @@ -5,226 +5,225 @@ using System.Reflection; using System.Text; -namespace DataStructures.Common +namespace DataStructures.Common; + +/// +/// Provides a list of the first 10,000 primes. +/// This class is a singleton, and read the primes from the file @"Data\PrimesList_10K.csv". +/// +public sealed class PrimesList { - /// - /// Provides a list of the first 10,000 primes. - /// This class is a singleton, and read the primes from the file @"Data\PrimesList_10K.csv". - /// - public sealed class PrimesList - { - // - // Singleton implementation with an attempted thread-safety using double-check locking - // internal datastorage singleton container - private static PrimesList _instance; + // + // Singleton implementation with an attempted thread-safety using double-check locking + // internal datastorage singleton container + private static PrimesList _instance; - // lock for thread-safety laziness - private static readonly object Mutex = new object(); + // lock for thread-safety laziness + private static readonly object Mutex = new object(); - // - // INSTANCE VARIABLES - private readonly static List _primes = new List(); + // + // INSTANCE VARIABLES + private readonly static List _primes = new List(); - // Picked the HashPrime to be (101) because it is prime, and if the ‘hashSize - 1’ is not a multiple of this HashPrime, which is - // enforced in _getUpperBoundPrime, then expand function has the potential of being every value from 1 to hashSize - 1. - // The choice is largely arbitrary. - public const int HASH_PRIME = 101; + // Picked the HashPrime to be (101) because it is prime, and if the ‘hashSize - 1’ is not a multiple of this HashPrime, which is + // enforced in _getUpperBoundPrime, then expand function has the potential of being every value from 1 to hashSize - 1. + // The choice is largely arbitrary. + public const int HASH_PRIME = 101; - /// - /// Empty private constructor. - /// - private PrimesList() { } + /// + /// Empty private constructor. + /// + private PrimesList() { } - /// - /// Returns the singleton instance of this class. - /// - public static PrimesList Instance + /// + /// Returns the singleton instance of this class. + /// + public static PrimesList Instance + { + get { - get + if (_instance == null) { - if (_instance == null) + lock (Mutex) { - lock (Mutex) + if (_instance == null) { - if (_instance == null) - { - _initializeData(); - _instance = new PrimesList(); - } + _initializeData(); + _instance = new PrimesList(); } } - - return _instance; } + + return _instance; } + } - /// - /// Initializes the primes document path and list. - /// - private static void _initializeData() - { - string[] lines = _readResource("DataStructures.Data.PrimesDocument_10K.csv"); + /// + /// Initializes the primes document path and list. + /// + private static void _initializeData() + { + string[] lines = _readResource("DataStructures.Data.PrimesDocument_10K.csv"); - foreach (var line in lines) - { - // Split the line by commas and convert the collection to a list. - var numbersAsStrings = line.Split(',').ToList(); + foreach (var line in lines) + { + // Split the line by commas and convert the collection to a list. + var numbersAsStrings = line.Split(',').ToList(); - // defensive check against empty strings. - numbersAsStrings.RemoveAll(item => string.IsNullOrEmpty(item) == true); + // defensive check against empty strings. + numbersAsStrings.RemoveAll(item => string.IsNullOrEmpty(item) == true); - if (numbersAsStrings.Count > 0) + if (numbersAsStrings.Count > 0) + { + try { - try - { - // cast them into integers and add them to the primes list - var numbers = numbersAsStrings.Select(item => Convert.ToInt32(item)).ToList(); - _primes.AddRange(numbers); - } - catch (Exception e) - { - throw new Exception(line.Replace("\r","{\\r}").Replace("\n", "{\\n}"), e); - } + // cast them into integers and add them to the primes list + var numbers = numbersAsStrings.Select(item => Convert.ToInt32(item)).ToList(); + _primes.AddRange(numbers); + } + catch (Exception e) + { + throw new Exception(line.Replace("\r","{\\r}").Replace("\n", "{\\n}"), e); } } } + } - /// - /// Return count of primes. - /// - public int Count => _primes.Count; + /// + /// Return count of primes. + /// + public int Count => _primes.Count; - /// - /// Returns prime number at the specified index. - /// - public int this[int index] + /// + /// Returns prime number at the specified index. + /// + public int this[int index] + { + get { - get - { - if (index < 0 || index >= _primes.Count) - throw new ArgumentOutOfRangeException(); + if (index < 0 || index >= _primes.Count) + throw new ArgumentOutOfRangeException(); - return _primes[index]; - } + return _primes[index]; } + } - /// - /// Checks if a number is a Prime Number. - /// - public bool IsPrime(int candidate) + /// + /// Checks if a number is a Prime Number. + /// + public bool IsPrime(int candidate) + { + if ((candidate & 1) != 0) { - if ((candidate & 1) != 0) - { - int limit = (int)Math.Sqrt(candidate); + int limit = (int)Math.Sqrt(candidate); - for (int divisor = 3; divisor <= limit; divisor += 2) - { - if (candidate % divisor == 0) - return false; - } - - return true; + for (int divisor = 3; divisor <= limit; divisor += 2) + { + if (candidate % divisor == 0) + return false; } - return candidate == 2; + return true; } - /// - /// Returns the next biggest prime number. - /// - /// - /// - public int GetNextPrime(int number) - { - if (number < 0) - throw new ArgumentException("Number should be greater than or equal to 0."); - - for (int i = 0; i < _primes.Count; i++) - { - if (_primes[i] >= number) - return _primes[i]; - } + return candidate == 2; + } - // Outside of our predefined table. Compute the prime the hard way. - for (int i = number | 1; i < Int32.MaxValue; i += 2) - { - if (IsPrime(i) && (i - 1) % HASH_PRIME != 0) - return i; - } + /// + /// Returns the next biggest prime number. + /// + /// + /// + public int GetNextPrime(int number) + { + if (number < 0) + throw new ArgumentException("Number should be greater than or equal to 0."); - return number; + for (int i = 0; i < _primes.Count; i++) + { + if (_primes[i] >= number) + return _primes[i]; } - /// - /// Returns the next minimum prime number. - /// - public int GetPreviousPrime(int number) + // Outside of our predefined table. Compute the prime the hard way. + for (int i = number | 1; i < Int32.MaxValue; i += 2) { - if (number < 0) - throw new ArgumentException("Number should be greater than or equal to 0."); + if (IsPrime(i) && (i - 1) % HASH_PRIME != 0) + return i; + } - for (int i = 0; i < _primes.Count; i++) - { - if (_primes[i] >= number) - return _primes[i]; - } + return number; + } - // Outside of our predefined table. Compute the prime the hard way. - for (int i = number | 1; i < Int32.MaxValue; i += 2) - { - if (IsPrime(i) && (i - 1) % HASH_PRIME != 0) - return i; - } + /// + /// Returns the next minimum prime number. + /// + public int GetPreviousPrime(int number) + { + if (number < 0) + throw new ArgumentException("Number should be greater than or equal to 0."); + + for (int i = 0; i < _primes.Count; i++) + { + if (_primes[i] >= number) + return _primes[i]; + } - return number; + // Outside of our predefined table. Compute the prime the hard way. + for (int i = number | 1; i < Int32.MaxValue; i += 2) + { + if (IsPrime(i) && (i - 1) % HASH_PRIME != 0) + return i; } - /// - /// Returns the read-only IList of primes - /// - public IList GetAll => _primes.AsReadOnly(); + return number; + } - /// - /// Copy the primes list to an array, starting from a specified index. - /// - public void CopyTo(int[] array, int index = 0) - { - if (array == null) - array = new int[_primes.Count]; + /// + /// Returns the read-only IList of primes + /// + public IList GetAll => _primes.AsReadOnly(); - if (array.Length <= index) - throw new ArgumentOutOfRangeException(); + /// + /// Copy the primes list to an array, starting from a specified index. + /// + public void CopyTo(int[] array, int index = 0) + { + if (array == null) + array = new int[_primes.Count]; - int count = array.Length - index; - int arrayIndex = index; + if (array.Length <= index) + throw new ArgumentOutOfRangeException(); - if (count - _primes.Count > 0) - count = _primes.Count; + int count = array.Length - index; + int arrayIndex = index; - for (int i = 0; i < count; i++) - { - array[arrayIndex] = _primes[i]; - arrayIndex++; - } + if (count - _primes.Count > 0) + count = _primes.Count; + + for (int i = 0; i < count; i++) + { + array[arrayIndex] = _primes[i]; + arrayIndex++; } + } - /// - /// Reads an embedded resource as a text file. - /// - /// - private static string[] _readResource(string resourceName) + /// + /// Reads an embedded resource as a text file. + /// + /// + private static string[] _readResource(string resourceName) + { + try + { + using (var stream = typeof(PrimesList).GetTypeInfo().Assembly.GetManifestResourceStream(resourceName)) + using (var reader = new StreamReader(stream ?? throw new InvalidOperationException("Failed to read resource"), Encoding.UTF8)) + return reader.ReadToEnd().Split("\n"); + } + catch (Exception ex) { - try - { - using (var stream = typeof(PrimesList).GetTypeInfo().Assembly.GetManifestResourceStream(resourceName)) - using (var reader = new StreamReader(stream ?? throw new InvalidOperationException("Failed to read resource"), Encoding.UTF8)) - return reader.ReadToEnd().Split("\n"); - } - catch (Exception ex) - { - throw new Exception($"Failed to read resource {resourceName}", ex); - } + throw new Exception($"Failed to read resource {resourceName}", ex); } } -} +} \ No newline at end of file diff --git a/DataStructures/Dictionaries/ChainedHashTable.cs b/DataStructures/Dictionaries/ChainedHashTable.cs index 4d700091..82be284a 100644 --- a/DataStructures/Dictionaries/ChainedHashTable.cs +++ b/DataStructures/Dictionaries/ChainedHashTable.cs @@ -10,105 +10,139 @@ using DataStructures.Common; using DataStructures.Lists; -namespace DataStructures.Dictionaries +namespace DataStructures.Dictionaries; + +/// +/// Hash Table with Chaining. +/// +public class ChainedHashTable : IDictionary where TKey : IComparable { /// - /// Hash Table with Chaining. + /// Used in the ensure capacity function /// - public class ChainedHashTable : IDictionary where TKey : IComparable + public enum CapacityManagementMode { - /// - /// Used in the ensure capacity function - /// - public enum CapacityManagementMode - { - Contract = 0, - Expand = 1 - } + Contract = 0, + Expand = 1 + } - /// - /// INSTANCE VARIABLES. - /// - private int _size; + /// + /// INSTANCE VARIABLES. + /// + private int _size; - private decimal _slotsLoadFactor; - private const int _defaultCapacity = 8; - private DLinkedList[] _hashTableStore; - private List _keysCollection { get; set; } - private List _valuesCollection { get; set; } + private decimal _slotsLoadFactor; + private const int _defaultCapacity = 8; + private DLinkedList[] _hashTableStore; + private List _keysCollection { get; set; } + private List _valuesCollection { get; set; } - // Keys and Values Comparers - private EqualityComparer _keysComparer { get; set; } - private EqualityComparer _valuesComparer { get; set; } + // Keys and Values Comparers + private EqualityComparer _keysComparer { get; set; } + private EqualityComparer _valuesComparer { get; set; } - // The C# Maximum Array Length (before encountering overflow) - // Reference: http://referencesource.microsoft.com/#mscorlib/system/array.cs,2d2b551eabe74985 - private const int MAX_ARRAY_LENGTH = 0X7FEFFFFF; + // The C# Maximum Array Length (before encountering overflow) + // Reference: http://referencesource.microsoft.com/#mscorlib/system/array.cs,2d2b551eabe74985 + private const int MAX_ARRAY_LENGTH = 0X7FEFFFFF; - // Initial hash value. - private const uint INITIAL_HASH = 0x9e3779b9; + // Initial hash value. + private const uint INITIAL_HASH = 0x9e3779b9; - /// - /// CONSTRUCTOR - /// - public ChainedHashTable() - { - _size = 0; - _hashTableStore = new DLinkedList[_defaultCapacity]; - _keysComparer = EqualityComparer.Default; - _valuesComparer = EqualityComparer.Default; + /// + /// CONSTRUCTOR + /// + public ChainedHashTable() + { + _size = 0; + _hashTableStore = new DLinkedList[_defaultCapacity]; + _keysComparer = EqualityComparer.Default; + _valuesComparer = EqualityComparer.Default; - _keysCollection = new List(); - _valuesCollection = new List(); - } + _keysCollection = new List(); + _valuesCollection = new List(); + } - /// - /// Rehash the the current collection elements to a new collection. - /// - private void _rehash(ref DLinkedList[] newHashTableStore, int oldHashTableSize) + /// + /// Rehash the the current collection elements to a new collection. + /// + private void _rehash(ref DLinkedList[] newHashTableStore, int oldHashTableSize) + { + // Reset the free slots count + + for (int i = 0; i < oldHashTableSize; ++i) { - // Reset the free slots count + var chain = _hashTableStore[i]; - for (int i = 0; i < oldHashTableSize; ++i) + if (chain != null && chain.Count > 0) { - var chain = _hashTableStore[i]; + var head = chain.Head; - if (chain != null && chain.Count > 0) + while (head != null) { - var head = chain.Head; + uint hash = _getHashOfKey(head.Key, newHashTableStore.Length); - while (head != null) + if (newHashTableStore[hash] == null) { - uint hash = _getHashOfKey(head.Key, newHashTableStore.Length); - - if (newHashTableStore[hash] == null) - { - newHashTableStore[hash] = new DLinkedList(); - } + newHashTableStore[hash] = new DLinkedList(); + } - newHashTableStore[hash].Append(head.Key, head.Value); + newHashTableStore[hash].Append(head.Key, head.Value); - head = head.Next; - } + head = head.Next; } - }//end-for - } + } + }//end-for + } - /// - /// Contracts the capacity of the keys and values arrays. - /// - private void _contractCapacity() + /// + /// Contracts the capacity of the keys and values arrays. + /// + private void _contractCapacity() + { + int oneThird = _hashTableStore.Length / 3; + int twoThirds = 2 * oneThird; + + if (_size <= oneThird) { - int oneThird = _hashTableStore.Length / 3; - int twoThirds = 2 * oneThird; + int newCapacity = _hashTableStore.Length == 0 ? _defaultCapacity : twoThirds; + + // Try to expand the size + DLinkedList[] newHashTableStore = new DLinkedList[newCapacity]; - if (_size <= oneThird) + // Rehash + if (_size > 0) { - int newCapacity = _hashTableStore.Length == 0 ? _defaultCapacity : twoThirds; + _rehash(ref newHashTableStore, _hashTableStore.Length); + }//end-if + + _hashTableStore = newHashTableStore; + } + } + + /// + /// Expands the capacity of the keys and values arrays. + /// + private void _expandCapacity(int minCapacity) + { + if (_hashTableStore.Length < minCapacity) + { + int newCapacity = _hashTableStore.Length == 0 ? _defaultCapacity : _hashTableStore.Length * 2; - // Try to expand the size + // Make sure it doesn't divide by 2 or 10 + if (newCapacity % 2 == 0 || newCapacity % 10 == 0) + newCapacity = newCapacity + 1; + + // Handle overflow + if (newCapacity >= MAX_ARRAY_LENGTH) + newCapacity = MAX_ARRAY_LENGTH; + else if (newCapacity < minCapacity) + newCapacity = minCapacity; + + // Try to expand the size + try + { DLinkedList[] newHashTableStore = new DLinkedList[newCapacity]; // Rehash @@ -119,223 +153,219 @@ private void _contractCapacity() _hashTableStore = newHashTableStore; } + catch (OutOfMemoryException) + { + throw; + } } + } - /// - /// Expands the capacity of the keys and values arrays. - /// - private void _expandCapacity(int minCapacity) + /// + /// A high-level functon that handles both contraction and expansion of the internal collection. + /// + /// Contract or Expand. + /// The new expansion size. + private void _ensureCapacity(CapacityManagementMode mode, int newSize = -1) + { + // If the size of the internal collection is less than or equal to third of + // ... the total capacity then contract the internal collection + int oneThird = _hashTableStore.Length / 3; + + if (mode == CapacityManagementMode.Contract && _size <= oneThird) { - if (_hashTableStore.Length < minCapacity) - { - int newCapacity = _hashTableStore.Length == 0 ? _defaultCapacity : _hashTableStore.Length * 2; + _contractCapacity(); + } + else if (mode == CapacityManagementMode.Expand && newSize > 0) + { + _expandCapacity(newSize); + } + } + + /// + /// Hash Function. + /// The universal hashing principle method. + /// + private uint _universalHashFunction(TKey key, int length) + { + if (length < 0) + throw new IndexOutOfRangeException(); - // Make sure it doesn't divide by 2 or 10 - if (newCapacity % 2 == 0 || newCapacity % 10 == 0) - newCapacity = newCapacity + 1; + // Hashes + uint prehash = 0, hash = INITIAL_HASH; - // Handle overflow - if (newCapacity >= MAX_ARRAY_LENGTH) - newCapacity = MAX_ARRAY_LENGTH; - else if (newCapacity < minCapacity) - newCapacity = minCapacity; + // Primes + int a = 197, b = 4049, p = 7199369; - // Try to expand the size - try - { - DLinkedList[] newHashTableStore = new DLinkedList[newCapacity]; + prehash = _getPreHashOfKey(key); + hash = Convert.ToUInt32((a * prehash + b) % p % length); - // Rehash - if (_size > 0) - { - _rehash(ref newHashTableStore, _hashTableStore.Length); - }//end-if + return hash; + } - _hashTableStore = newHashTableStore; - } - catch (OutOfMemoryException) - { - throw; - } - } - } + /// + /// Hash Function. + /// The division method hashing. + /// + private uint _divisionMethodHashFunction(TKey key, int length) + { + uint prehash = 0, hash = INITIAL_HASH; + + if (length < 0) + throw new IndexOutOfRangeException(); - /// - /// A high-level functon that handles both contraction and expansion of the internal collection. - /// - /// Contract or Expand. - /// The new expansion size. - private void _ensureCapacity(CapacityManagementMode mode, int newSize = -1) + if (key is string && key.IsEqualTo(default) == false) { - // If the size of the internal collection is less than or equal to third of - // ... the total capacity then contract the internal collection - int oneThird = _hashTableStore.Length / 3; + var stringKey = Convert.ToString(key); - if (mode == CapacityManagementMode.Contract && _size <= oneThird) - { - _contractCapacity(); - } - else if (mode == CapacityManagementMode.Expand && newSize > 0) + for (int i = 0; i < stringKey.Length; ++i) { - _expandCapacity(newSize); + hash = (hash ^ stringKey[i]) + (hash << 26) + (hash >> 6); } - } - /// - /// Hash Function. - /// The universal hashing principle method. - /// - private uint _universalHashFunction(TKey key, int length) + if (hash > length) + hash = Convert.ToUInt32(hash % length); + } + else { - if (length < 0) - throw new IndexOutOfRangeException(); - - // Hashes - uint prehash = 0, hash = INITIAL_HASH; - - // Primes - int a = 197, b = 4049, p = 7199369; - prehash = _getPreHashOfKey(key); - hash = Convert.ToUInt32((a * prehash + b) % p % length); - - return hash; + hash = Convert.ToUInt32(37 * prehash % length); } - /// - /// Hash Function. - /// The division method hashing. - /// - private uint _divisionMethodHashFunction(TKey key, int length) - { - uint prehash = 0, hash = INITIAL_HASH; + return hash; + } - if (length < 0) - throw new IndexOutOfRangeException(); + /// + /// Returns an integer that represents the key. + /// Used in the _hashKey function. + /// + private uint _getPreHashOfKey(TKey key) + { + return Convert.ToUInt32(Math.Abs(_keysComparer.GetHashCode(key))); + } - if (key is string && key.IsEqualTo(default) == false) - { - var stringKey = Convert.ToString(key); + /// + /// Returns a key from 0 to m where m is the size of the keys-and-values map. The hash serves as an index. + /// + private uint _getHashOfKey(TKey key, int length) + { + return _universalHashFunction(key, length); + } - for (int i = 0; i < stringKey.Length; ++i) - { - hash = (hash ^ stringKey[i]) + (hash << 26) + (hash >> 6); - } + /// + /// Returns a key from 0 to m where m is the size of the keys-and-values map. The hash serves as an index. + /// Division Method. + /// + private uint _getHashOfKey(TKey key) + { + return _universalHashFunction(key, _hashTableStore.Length); + } - if (hash > length) - hash = Convert.ToUInt32(hash % length); - } - else - { - prehash = _getPreHashOfKey(key); - hash = Convert.ToUInt32(37 * prehash % length); - } + /// + /// Return count of elements in the hash table. + /// + public int Count => _size; - return hash; - } + /// + /// Checks if the hash table is readonly. + /// + public bool IsReadOnly => false; - /// - /// Returns an integer that represents the key. - /// Used in the _hashKey function. - /// - private uint _getPreHashOfKey(TKey key) - { - return Convert.ToUInt32(Math.Abs(_keysComparer.GetHashCode(key))); - } + /// + /// Checks if the hash table is empty. + /// + public bool IsEmpty => Count == 0; - /// - /// Returns a key from 0 to m where m is the size of the keys-and-values map. The hash serves as an index. - /// - private uint _getHashOfKey(TKey key, int length) - { - return _universalHashFunction(key, length); - } + /// + /// Checks whether key exists in the hash table. + /// + public bool ContainsKey(TKey key) + { + // Get hash of the key + var hashcode = _getHashOfKey(key); - /// - /// Returns a key from 0 to m where m is the size of the keys-and-values map. The hash serves as an index. - /// Division Method. - /// - private uint _getHashOfKey(TKey key) + // The chain of colliding keys are found at _keysValuesMap[hashcode] as a doubly-linked-list. + if (_hashTableStore[hashcode] != null && _hashTableStore[hashcode].Count > 0) { - return _universalHashFunction(key, _hashTableStore.Length); + return _hashTableStore[hashcode].ContainsKey(key); } - /// - /// Return count of elements in the hash table. - /// - public int Count => _size; - - /// - /// Checks if the hash table is readonly. - /// - public bool IsReadOnly => false; - - /// - /// Checks if the hash table is empty. - /// - public bool IsEmpty => Count == 0; - - /// - /// Checks whether key exists in the hash table. - /// - public bool ContainsKey(TKey key) + // else + return false; + } + + /// + /// Checks whether a key-value pair exist in the hash table. + /// + public bool Contains(KeyValuePair item) + { + // Get hash of the key + var hashcode = _getHashOfKey(item.Key); + + // The chain of colliding keys are found at _keysValuesMap[hashcode] as a doubly-linked-list. + if (_hashTableStore[hashcode] != null && _hashTableStore[hashcode].Count > 0) { - // Get hash of the key - var hashcode = _getHashOfKey(key); + try + { + var existingPair = _hashTableStore[hashcode].Find(item.Key); - // The chain of colliding keys are found at _keysValuesMap[hashcode] as a doubly-linked-list. - if (_hashTableStore[hashcode] != null && _hashTableStore[hashcode].Count > 0) + if (existingPair.Key.IsEqualTo(item.Key) && _valuesComparer.Equals(existingPair.Value, item.Value)) + return true; + } + catch (KeyNotFoundException) { - return _hashTableStore[hashcode].ContainsKey(key); + // do nothing } - - // else - return false; } - /// - /// Checks whether a key-value pair exist in the hash table. - /// - public bool Contains(KeyValuePair item) - { - // Get hash of the key - var hashcode = _getHashOfKey(item.Key); + // else + return false; + } - // The chain of colliding keys are found at _keysValuesMap[hashcode] as a doubly-linked-list. - if (_hashTableStore[hashcode] != null && _hashTableStore[hashcode].Count > 0) - { - try - { - var existingPair = _hashTableStore[hashcode].Find(item.Key); + /// + /// List of hash table keys. + /// + public ICollection Keys => _keysCollection; - if (existingPair.Key.IsEqualTo(item.Key) && _valuesComparer.Equals(existingPair.Value, item.Value)) - return true; - } - catch (KeyNotFoundException) - { - // do nothing - } - } + /// + /// List of hash table values. + /// + public ICollection Values => _valuesCollection; - // else - return false; - } - /// - /// List of hash table keys. - /// - public ICollection Keys => _keysCollection; + /// + /// Tries to get the value of key which might not be in the dictionary. + /// + public bool TryGetValue(TKey key, out TValue value) + { + // Get hash of the key + var hashcode = _getHashOfKey(key); - /// - /// List of hash table values. - /// - public ICollection Values => _valuesCollection; + // The chain of colliding keys are found at _keysValuesMap[hashcode] as a doubly-linked-list. + if (_hashTableStore[hashcode] != null && _hashTableStore[hashcode].Count > 0) + { + try + { + var existingPair = _hashTableStore[hashcode].Find(key); + value = existingPair.Value; + return true; + } + catch (KeyNotFoundException) + { + // do nothing + } + } + // NOT FOUND + value = default; + return false; + } - /// - /// Tries to get the value of key which might not be in the dictionary. - /// - public bool TryGetValue(TKey key, out TValue value) + /// + /// Gets or sets the value of a key. + /// + public TValue this[TKey key] + { + get { // Get hash of the key var hashcode = _getHashOfKey(key); @@ -346,8 +376,7 @@ public bool TryGetValue(TKey key, out TValue value) try { var existingPair = _hashTableStore[hashcode].Find(key); - value = existingPair.Value; - return true; + return existingPair.Value; } catch (KeyNotFoundException) { @@ -356,265 +385,234 @@ public bool TryGetValue(TKey key, out TValue value) } // NOT FOUND - value = default; - return false; + throw new KeyNotFoundException(); } - - /// - /// Gets or sets the value of a key. - /// - public TValue this[TKey key] - { - get - { - // Get hash of the key - var hashcode = _getHashOfKey(key); - - // The chain of colliding keys are found at _keysValuesMap[hashcode] as a doubly-linked-list. - if (_hashTableStore[hashcode] != null && _hashTableStore[hashcode].Count > 0) - { - try - { - var existingPair = _hashTableStore[hashcode].Find(key); - return existingPair.Value; - } - catch (KeyNotFoundException) - { - // do nothing - } - } - - // NOT FOUND - throw new KeyNotFoundException(); - } - set - { - // Get hash of the key - var hashcode = _getHashOfKey(key); - - // The chain of colliding keys are found at _keysValuesMap[hashcode] as a doubly-linked-list. - if (_hashTableStore[hashcode] != null && _hashTableStore[hashcode].Count > 0) - { - bool exists = _hashTableStore[hashcode].ContainsKey(key); - - if (exists == true) - _hashTableStore[hashcode].UpdateValueByKey(key, value); - } - - // NOT FOUND - throw new KeyNotFoundException(); - } - } - - /// - /// Add a key and value to the hash table. - /// - public void Add(TKey key, TValue value) + set { // Get hash of the key var hashcode = _getHashOfKey(key); // The chain of colliding keys are found at _keysValuesMap[hashcode] as a doubly-linked-list. - if (_hashTableStore[hashcode] == null) + if (_hashTableStore[hashcode] != null && _hashTableStore[hashcode].Count > 0) { - // This is an empty slot. Initialize the chain of collisions. - _hashTableStore[hashcode] = new DLinkedList(); + bool exists = _hashTableStore[hashcode].ContainsKey(key); - // Decrease the number of free slots. - } - else if (_hashTableStore[hashcode].Count > 0) - { - if (_hashTableStore[hashcode].ContainsKey(key) == true) - throw new ArgumentException("Key already exists in the hash table."); + if (exists == true) + _hashTableStore[hashcode].UpdateValueByKey(key, value); } - _hashTableStore[hashcode].Append(key, value); - _size++; + // NOT FOUND + throw new KeyNotFoundException(); + } + } - //Add the key-value to the keys and values collections - _keysCollection.Add(key); - _valuesCollection.Add(value); + /// + /// Add a key and value to the hash table. + /// + public void Add(TKey key, TValue value) + { + // Get hash of the key + var hashcode = _getHashOfKey(key); - _slotsLoadFactor = Decimal.Divide( - Convert.ToDecimal(_size), - Convert.ToDecimal(_hashTableStore.Length)); + // The chain of colliding keys are found at _keysValuesMap[hashcode] as a doubly-linked-list. + if (_hashTableStore[hashcode] == null) + { + // This is an empty slot. Initialize the chain of collisions. + _hashTableStore[hashcode] = new DLinkedList(); - // Capacity management - if (_slotsLoadFactor.IsGreaterThanOrEqualTo(Convert.ToDecimal(0.90))) - { - _ensureCapacity(CapacityManagementMode.Expand, _hashTableStore.Length + 1); - } + // Decrease the number of free slots. } - - /// - /// Add a key-value pair to the hash table. - /// - public void Add(KeyValuePair item) + else if (_hashTableStore[hashcode].Count > 0) { - Add(item.Key, item.Value); + if (_hashTableStore[hashcode].ContainsKey(key) == true) + throw new ArgumentException("Key already exists in the hash table."); } - /// - /// Remove a key from the hash table and return the status. - /// - public bool Remove(TKey key) + _hashTableStore[hashcode].Append(key, value); + _size++; + + //Add the key-value to the keys and values collections + _keysCollection.Add(key); + _valuesCollection.Add(value); + + _slotsLoadFactor = Decimal.Divide( + Convert.ToDecimal(_size), + Convert.ToDecimal(_hashTableStore.Length)); + + // Capacity management + if (_slotsLoadFactor.IsGreaterThanOrEqualTo(Convert.ToDecimal(0.90))) { - // Get hash of the key - var hashcode = _getHashOfKey(key); + _ensureCapacity(CapacityManagementMode.Expand, _hashTableStore.Length + 1); + } + } - // The chain of colliding keys are found at _keysValuesMap[hashcode] as a doubly-linked-list. - if (_hashTableStore[hashcode] != null && _hashTableStore[hashcode].Count > 0) + /// + /// Add a key-value pair to the hash table. + /// + public void Add(KeyValuePair item) + { + Add(item.Key, item.Value); + } + + /// + /// Remove a key from the hash table and return the status. + /// + public bool Remove(TKey key) + { + // Get hash of the key + var hashcode = _getHashOfKey(key); + + // The chain of colliding keys are found at _keysValuesMap[hashcode] as a doubly-linked-list. + if (_hashTableStore[hashcode] != null && _hashTableStore[hashcode].Count > 0) + { + try { - try + var keyValuePair = _hashTableStore[hashcode].Find(key); + + if (keyValuePair.Key.IsEqualTo(key)) { - var keyValuePair = _hashTableStore[hashcode].Find(key); + _hashTableStore[hashcode].RemoveBy(key); + _size--; - if (keyValuePair.Key.IsEqualTo(key)) + // check if no other keys exist in this slot. + if (_hashTableStore[hashcode].Count == 0) { - _hashTableStore[hashcode].RemoveBy(key); - _size--; + // Nullify the chain of collisions at this slot. + _hashTableStore[hashcode] = null; - // check if no other keys exist in this slot. - if (_hashTableStore[hashcode].Count == 0) - { - // Nullify the chain of collisions at this slot. - _hashTableStore[hashcode] = null; + // Increase the number of free slots. - // Increase the number of free slots. - - // Capacity management - _ensureCapacity(CapacityManagementMode.Contract); - } + // Capacity management + _ensureCapacity(CapacityManagementMode.Contract); + } - _keysCollection.Remove(key); - _valuesCollection.Remove(keyValuePair.Value); + _keysCollection.Remove(key); + _valuesCollection.Remove(keyValuePair.Value); - return true; - } - } - catch - { - // do nothing + return true; } } - - // else - return false; + catch + { + // do nothing + } } - /// - /// Remove a key-value pair from the hash table and return the status. - /// - public bool Remove(KeyValuePair item) - { - // Get hash of the key - var hashcode = _getHashOfKey(item.Key); + // else + return false; + } - // The chain of colliding keys are found at _keysValuesMap[hashcode] as a doubly-linked-list. - if (_hashTableStore[hashcode] != null && _hashTableStore[hashcode].Count > 0) + /// + /// Remove a key-value pair from the hash table and return the status. + /// + public bool Remove(KeyValuePair item) + { + // Get hash of the key + var hashcode = _getHashOfKey(item.Key); + + // The chain of colliding keys are found at _keysValuesMap[hashcode] as a doubly-linked-list. + if (_hashTableStore[hashcode] != null && _hashTableStore[hashcode].Count > 0) + { + try { - try + var keyValuePair = _hashTableStore[hashcode].Find(item.Key); + + if (keyValuePair.Key.IsEqualTo(item.Key) && _valuesComparer.Equals(keyValuePair.Value, item.Value)) { - var keyValuePair = _hashTableStore[hashcode].Find(item.Key); + _hashTableStore[hashcode].RemoveBy(item.Key); + _size--; - if (keyValuePair.Key.IsEqualTo(item.Key) && _valuesComparer.Equals(keyValuePair.Value, item.Value)) + // check if no other keys exist in this slot. + if (_hashTableStore[hashcode].Count == 0) { - _hashTableStore[hashcode].RemoveBy(item.Key); - _size--; - - // check if no other keys exist in this slot. - if (_hashTableStore[hashcode].Count == 0) - { - // Nullify the chain of collisions at this slot. - _hashTableStore[hashcode] = null; + // Nullify the chain of collisions at this slot. + _hashTableStore[hashcode] = null; - // Increase the number of free slots. + // Increase the number of free slots. - // Capacity management - _ensureCapacity(CapacityManagementMode.Contract); - } + // Capacity management + _ensureCapacity(CapacityManagementMode.Contract); + } - _keysCollection.Remove(keyValuePair.Key); - _valuesCollection.Remove(keyValuePair.Value); + _keysCollection.Remove(keyValuePair.Key); + _valuesCollection.Remove(keyValuePair.Value); - return true; - } - } - catch - { - // do nothing + return true; } } - - // else - return false; + catch + { + // do nothing + } } - /// - /// Copy the key-value pairs in the hash table to an array starting from the specified index. - /// - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - if (array == null) - array = new KeyValuePair[_size]; + // else + return false; + } - int i = arrayIndex; - int hashTableIndex = 0; - var currentChainNode = new DLinkedListNode(); + /// + /// Copy the key-value pairs in the hash table to an array starting from the specified index. + /// + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + if (array == null) + array = new KeyValuePair[_size]; - while (true) - { - KeyValuePair pair; + int i = arrayIndex; + int hashTableIndex = 0; + var currentChainNode = new DLinkedListNode(); - if (i >= array.Length) - break; + while (true) + { + KeyValuePair pair; - if (_hashTableStore[hashTableIndex] != null) - { - currentChainNode = _hashTableStore[hashTableIndex].Head; - while (currentChainNode != null && i < array.Length) - { - pair = new KeyValuePair(currentChainNode.Key, currentChainNode.Value); - array[i] = pair; - i++; - hashTableIndex++; + if (i >= array.Length) + break; - currentChainNode = currentChainNode.Next; - } - } - else + if (_hashTableStore[hashTableIndex] != null) + { + currentChainNode = _hashTableStore[hashTableIndex].Head; + while (currentChainNode != null && i < array.Length) { + pair = new KeyValuePair(currentChainNode.Key, currentChainNode.Value); + array[i] = pair; + i++; hashTableIndex++; + + currentChainNode = currentChainNode.Next; } } + else + { + hashTableIndex++; + } } + } - /// - /// Clears this instance. - /// - public void Clear() - { - // Clear the elements in the store - Array.Clear(_hashTableStore, 0, _hashTableStore.Length); - - // Re-initialize to empty collection. - _hashTableStore = new DLinkedList[_defaultCapacity]; + /// + /// Clears this instance. + /// + public void Clear() + { + // Clear the elements in the store + Array.Clear(_hashTableStore, 0, _hashTableStore.Length); - _size = 0; - _slotsLoadFactor = 0; - } + // Re-initialize to empty collection. + _hashTableStore = new DLinkedList[_defaultCapacity]; + _size = 0; + _slotsLoadFactor = 0; + } - public IEnumerator> GetEnumerator() - { - throw new NotImplementedException(); - } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } + public IEnumerator> GetEnumerator() + { + throw new NotImplementedException(); + } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); } -} +} \ No newline at end of file diff --git a/DataStructures/Dictionaries/CuckooHashTable.cs b/DataStructures/Dictionaries/CuckooHashTable.cs index 7efe114d..9d148678 100644 --- a/DataStructures/Dictionaries/CuckooHashTable.cs +++ b/DataStructures/Dictionaries/CuckooHashTable.cs @@ -12,356 +12,354 @@ using DataStructures.Hashing; using System.Threading.Tasks; -namespace DataStructures.Dictionaries +namespace DataStructures.Dictionaries; + +/// +/// THE CUCKOO HASH TABLE Data Structure. +/// +public class CuckooHashTable where TKey : IComparable { /// - /// THE CUCKOO HASH TABLE Data Structure. + /// THE CUCKOO HASH TABLE ENTERY /// - public class CuckooHashTable where TKey : IComparable + private class CHashEntry where TKey : IComparable { - /// - /// THE CUCKOO HASH TABLE ENTERY - /// - private class CHashEntry where TKey : IComparable - { - public TKey Key { get; set; } - public TValue Value { get; set; } - public bool IsActive { get; set; } + public TKey Key { get; set; } + public TValue Value { get; set; } + public bool IsActive { get; set; } - public CHashEntry() : this(default, default, false) { } + public CHashEntry() : this(default, default, false) { } - public CHashEntry(TKey key, TValue value, bool isActive) - { - Key = key; - Value = value; - IsActive = isActive; - } + public CHashEntry(TKey key, TValue value, bool isActive) + { + Key = key; + Value = value; + IsActive = isActive; } + } - /// - /// INSTANCE VARIABLES - /// - private const int DEFAULT_CAPACITY = 11; - private const double MAX_LOAD_FACTOR = 0.45; - private const int ALLOWED_REHASHES = 5; - private const int NUMBER_OF_HASH_FUNCTIONS = 7; // number of hash functions to use, selected 7 because it's prime. The choice was arbitrary. - internal readonly PrimesList PRIMES = PrimesList.Instance; + /// + /// INSTANCE VARIABLES + /// + private const int DEFAULT_CAPACITY = 11; + private const double MAX_LOAD_FACTOR = 0.45; + private const int ALLOWED_REHASHES = 5; + private const int NUMBER_OF_HASH_FUNCTIONS = 7; // number of hash functions to use, selected 7 because it's prime. The choice was arbitrary. + internal readonly PrimesList PRIMES = PrimesList.Instance; - // Random number generator - private Random _randomizer; + // Random number generator + private Random _randomizer; - private int _size { get; set; } - private int _numberOfRehashes { get; set; } - private CHashEntry[] _collection { get; set; } - private UniversalHashingFamily _universalHashingFamily { get; set; } - private EqualityComparer _equalityComparer = EqualityComparer.Default; + private int _size { get; set; } + private int _numberOfRehashes { get; set; } + private CHashEntry[] _collection { get; set; } + private UniversalHashingFamily _universalHashingFamily { get; set; } + private EqualityComparer _equalityComparer = EqualityComparer.Default; - // The C# Maximum Array Length (before encountering overflow) - // Reference: http://referencesource.microsoft.com/#mscorlib/system/array.cs,2d2b551eabe74985 - private const int MAX_ARRAY_LENGTH = 0X7FEFFFFF; + // The C# Maximum Array Length (before encountering overflow) + // Reference: http://referencesource.microsoft.com/#mscorlib/system/array.cs,2d2b551eabe74985 + private const int MAX_ARRAY_LENGTH = 0X7FEFFFFF; - /// - /// CONSTRUCTOR - /// - public CuckooHashTable() - { - _size = 0; - _numberOfRehashes = 0; - _randomizer = new Random(); - _collection = new CHashEntry[DEFAULT_CAPACITY]; - _universalHashingFamily = new UniversalHashingFamily(NUMBER_OF_HASH_FUNCTIONS); - } + /// + /// CONSTRUCTOR + /// + public CuckooHashTable() + { + _size = 0; + _numberOfRehashes = 0; + _randomizer = new Random(); + _collection = new CHashEntry[DEFAULT_CAPACITY]; + _universalHashingFamily = new UniversalHashingFamily(NUMBER_OF_HASH_FUNCTIONS); + } - /// - /// Expands the size of internal collection. - /// - private void _expandCapacity(int minCapacity) - { - int newCapacity = _collection.Length == 0 ? DEFAULT_CAPACITY : _collection.Length * 2; + /// + /// Expands the size of internal collection. + /// + private void _expandCapacity(int minCapacity) + { + int newCapacity = _collection.Length == 0 ? DEFAULT_CAPACITY : _collection.Length * 2; - // Handle overflow - if (newCapacity >= MAX_ARRAY_LENGTH) - newCapacity = MAX_ARRAY_LENGTH; - else if (newCapacity < minCapacity) - newCapacity = minCapacity; + // Handle overflow + if (newCapacity >= MAX_ARRAY_LENGTH) + newCapacity = MAX_ARRAY_LENGTH; + else if (newCapacity < minCapacity) + newCapacity = minCapacity; - _rehash(Convert.ToInt32(newCapacity)); - } + _rehash(Convert.ToInt32(newCapacity)); + } - /// - /// Contracts the size of internal collection to half. - /// - private void _contractCapacity() - { - _rehash(_size / 2); - } + /// + /// Contracts the size of internal collection to half. + /// + private void _contractCapacity() + { + _rehash(_size / 2); + } - /// - /// Rehashes the internal internal collection. - /// Table size stays the same, but generates new hash functions. - /// - private void _rehash() - { - _universalHashingFamily.GenerateNewFunctions(); - _rehash(_collection.Length); - } + /// + /// Rehashes the internal internal collection. + /// Table size stays the same, but generates new hash functions. + /// + private void _rehash() + { + _universalHashingFamily.GenerateNewFunctions(); + _rehash(_collection.Length); + } - /// - /// Rehashes the internal collection to a new size. - /// New hash table size, but the hash functions stay the same. - /// - private void _rehash(int newCapacity) - { - int primeCapacity = PRIMES.GetNextPrime(newCapacity); + /// + /// Rehashes the internal collection to a new size. + /// New hash table size, but the hash functions stay the same. + /// + private void _rehash(int newCapacity) + { + int primeCapacity = PRIMES.GetNextPrime(newCapacity); - var oldSize = _size; - var oldCollection = _collection; + var oldSize = _size; + var oldCollection = _collection; - try - { - _collection = new CHashEntry[newCapacity]; + try + { + _collection = new CHashEntry[newCapacity]; - // Reset size - _size = 0; + // Reset size + _size = 0; - for (int i = 0; i < oldCollection.Length; ++i) + for (int i = 0; i < oldCollection.Length; ++i) + { + if (oldCollection[i] != null && oldCollection[i].IsActive == true) { - if (oldCollection[i] != null && oldCollection[i].IsActive == true) - { - _insertHelper(oldCollection[i].Key, oldCollection[i].Value); - } + _insertHelper(oldCollection[i].Key, oldCollection[i].Value); } } - catch (OutOfMemoryException ex) - { - // In case a memory overflow happens, return the data to it's old state - // ... then throw the exception. - _collection = oldCollection; - _size = oldSize; + } + catch (OutOfMemoryException ex) + { + // In case a memory overflow happens, return the data to it's old state + // ... then throw the exception. + _collection = oldCollection; + _size = oldSize; - throw ex.InnerException; - } + throw ex.InnerException; } + } - /// - /// Hashes a key, using the specified hash function number which belongs to the internal hash functions family. - /// - private int _cuckooHash(TKey key, int whichHashFunction) - { - if (whichHashFunction <= 0 || whichHashFunction > _universalHashingFamily.NumberOfFunctions) - throw new ArgumentOutOfRangeException("Which Hash Function parameter must be betwwen 1 and " + NUMBER_OF_HASH_FUNCTIONS + "."); + /// + /// Hashes a key, using the specified hash function number which belongs to the internal hash functions family. + /// + private int _cuckooHash(TKey key, int whichHashFunction) + { + if (whichHashFunction <= 0 || whichHashFunction > _universalHashingFamily.NumberOfFunctions) + throw new ArgumentOutOfRangeException("Which Hash Function parameter must be betwwen 1 and " + NUMBER_OF_HASH_FUNCTIONS + "."); - int hashCode = Math.Abs(_universalHashingFamily.UniversalHash(_equalityComparer.GetHashCode(key), whichHashFunction)); + int hashCode = Math.Abs(_universalHashingFamily.UniversalHash(_equalityComparer.GetHashCode(key), whichHashFunction)); - return hashCode % _collection.Length; - } + return hashCode % _collection.Length; + } - /// - /// Checks whether there is an entry at the specified position and that the entry is active. - /// - private bool _isActive(int index) - { - if (index < 0 || index > _collection.Length) - throw new IndexOutOfRangeException(); + /// + /// Checks whether there is an entry at the specified position and that the entry is active. + /// + private bool _isActive(int index) + { + if (index < 0 || index > _collection.Length) + throw new IndexOutOfRangeException(); - return _collection[index] != null && _collection[index].IsActive == true; - } + return _collection[index] != null && _collection[index].IsActive == true; + } - /// - /// Returns the array position (index) of the specified key. - /// - private int _findPosition(TKey key) + /// + /// Returns the array position (index) of the specified key. + /// + private int _findPosition(TKey key) + { + // The hash functions numbers are indexed from 1 not zero + for (int i = 1; i <= NUMBER_OF_HASH_FUNCTIONS; ++i) { - // The hash functions numbers are indexed from 1 not zero - for (int i = 1; i <= NUMBER_OF_HASH_FUNCTIONS; ++i) - { - int index = _cuckooHash(key, i); - - if (_isActive(index) && _collection[index].Key.IsEqualTo(key)) - return index; - } + int index = _cuckooHash(key, i); - return -1; + if (_isActive(index) && _collection[index].Key.IsEqualTo(key)) + return index; } - /// - /// Inserts a key-value pair into hash table. - /// - private void _insertHelper(TKey key, TValue value) + return -1; + } + + /// + /// Inserts a key-value pair into hash table. + /// + private void _insertHelper(TKey key, TValue value) + { + int COUNT_LIMIT = 100; + var newEntry = new CHashEntry(key, value, isActive: true); + + while (true) { - int COUNT_LIMIT = 100; - var newEntry = new CHashEntry(key, value, isActive: true); + int position, lastPosition = -1; - while (true) + for (int count = 0; count < COUNT_LIMIT; count++) { - int position, lastPosition = -1; - - for (int count = 0; count < COUNT_LIMIT; count++) + // The hash functions numbers are indexed from 1 not zero + for (int i = 1; i <= NUMBER_OF_HASH_FUNCTIONS; i++) { - // The hash functions numbers are indexed from 1 not zero - for (int i = 1; i <= NUMBER_OF_HASH_FUNCTIONS; i++) - { - position = _cuckooHash(key, i); + position = _cuckooHash(key, i); - if (!_isActive(position)) - { - _collection[position] = newEntry; + if (!_isActive(position)) + { + _collection[position] = newEntry; - // Increment size - ++_size; + // Increment size + ++_size; - return; - } + return; } + } - // Eviction strategy: - // No available spot was found. Choose a random one. - int j = 0; - do - { - position = _cuckooHash(key, _randomizer.Next(1, NUMBER_OF_HASH_FUNCTIONS)); - } while (position == lastPosition && j++ < NUMBER_OF_HASH_FUNCTIONS); + // Eviction strategy: + // No available spot was found. Choose a random one. + int j = 0; + do + { + position = _cuckooHash(key, _randomizer.Next(1, NUMBER_OF_HASH_FUNCTIONS)); + } while (position == lastPosition && j++ < NUMBER_OF_HASH_FUNCTIONS); - // SWAP ENTRY - lastPosition = position; + // SWAP ENTRY + lastPosition = position; - var temp = _collection[position]; - _collection[position] = newEntry; - newEntry = temp; + var temp = _collection[position]; + _collection[position] = newEntry; + newEntry = temp; - }//end-for + }//end-for - if (++_numberOfRehashes > ALLOWED_REHASHES) - { - // Expand the table. - _expandCapacity(_collection.Length + 1); + if (++_numberOfRehashes > ALLOWED_REHASHES) + { + // Expand the table. + _expandCapacity(_collection.Length + 1); - // Reset number of rehashes. - _numberOfRehashes = 0; - } - else - { - // Rehash the table with the same current size. - _rehash(); - } - }//end-while - } + // Reset number of rehashes. + _numberOfRehashes = 0; + } + else + { + // Rehash the table with the same current size. + _rehash(); + } + }//end-while + } - /// - /// Returns number of items in hash table. - /// - /// - public int Count() - { - return _size; - } + /// + /// Returns number of items in hash table. + /// + /// + public int Count() + { + return _size; + } - /// - /// Returns true if hash table is empty; otherwise, false. - /// - public bool IsEmpty() - { - return _size == 0; - } + /// + /// Returns true if hash table is empty; otherwise, false. + /// + public bool IsEmpty() + { + return _size == 0; + } - /// - /// Returns the value of the specified key, if exists; otherwise, raises an exception. - /// - public TValue this[TKey key] + /// + /// Returns the value of the specified key, if exists; otherwise, raises an exception. + /// + public TValue this[TKey key] + { + get { - get - { - int position = _findPosition(key); + int position = _findPosition(key); - if (position != -1) - return _collection[position].Value; + if (position != -1) + return _collection[position].Value; - throw new KeyNotFoundException(); - } - set - { - if (ContainsKey(key) == true) - Update(key, value); - - throw new KeyNotFoundException(); - } + throw new KeyNotFoundException(); } - - /// - /// Checks if a key exists in the hash table. - /// - /// - /// - public bool ContainsKey(TKey key) + set { - return _findPosition(key) != -1; + if (ContainsKey(key) == true) + Update(key, value); + + throw new KeyNotFoundException(); } + } - /// - /// Insert key-value pair into hash table. - /// - public void Add(TKey key, TValue value) - { - if (ContainsKey(key)) - throw new Exception("Key already exists in the hash table."); + /// + /// Checks if a key exists in the hash table. + /// + /// + /// + public bool ContainsKey(TKey key) + { + return _findPosition(key) != -1; + } - if (_size >= _collection.Length * MAX_LOAD_FACTOR) - _expandCapacity(_collection.Length + 1); + /// + /// Insert key-value pair into hash table. + /// + public void Add(TKey key, TValue value) + { + if (ContainsKey(key)) + throw new Exception("Key already exists in the hash table."); - _insertHelper(key, value); - } + if (_size >= _collection.Length * MAX_LOAD_FACTOR) + _expandCapacity(_collection.Length + 1); - /// - /// Updates a key-value pair with a new value. - /// - public void Update(TKey key, TValue value) - { - int position = _findPosition(key); + _insertHelper(key, value); + } - if (position == -1) - throw new KeyNotFoundException(); + /// + /// Updates a key-value pair with a new value. + /// + public void Update(TKey key, TValue value) + { + int position = _findPosition(key); - _collection[position].Value = value; - } + if (position == -1) + throw new KeyNotFoundException(); - /// - /// Remove the key-value pair specified by the given key. - /// - public bool Remove(TKey key) - { - int currentPosition = _findPosition(key); + _collection[position].Value = value; + } - if (!_isActive(currentPosition)) - return false; + /// + /// Remove the key-value pair specified by the given key. + /// + public bool Remove(TKey key) + { + int currentPosition = _findPosition(key); - // Mark the entry as not active - _collection[currentPosition].IsActive = false; + if (!_isActive(currentPosition)) + return false; - // Decrease the size - --_size; + // Mark the entry as not active + _collection[currentPosition].IsActive = false; - return true; - } + // Decrease the size + --_size; - /// - /// Clears this hash table. - /// - public void Clear() - { - _size = 0; + return true; + } + + /// + /// Clears this hash table. + /// + public void Clear() + { + _size = 0; - Parallel.ForEach(_collection, - (item) => + Parallel.ForEach(_collection, + (item) => + { + if (item != null && item.IsActive == true) { - if (item != null && item.IsActive == true) - { - item.IsActive = false; - } - }); - } + item.IsActive = false; + } + }); } - -} +} \ No newline at end of file diff --git a/DataStructures/Dictionaries/OpenAddressingHashTable.cs b/DataStructures/Dictionaries/OpenAddressingHashTable.cs index 67acc55b..ebe17e53 100644 --- a/DataStructures/Dictionaries/OpenAddressingHashTable.cs +++ b/DataStructures/Dictionaries/OpenAddressingHashTable.cs @@ -2,378 +2,377 @@ using System.Collections.Generic; using System.Text; -namespace DataStructures.Dictionaries +namespace DataStructures.Dictionaries; + +/// +/// Open Addressing Data Structure +/// +/// +/// +public class OpenAddressingHashTable : IDictionary where TKey : IComparable { + /// - /// Open Addressing Data Structure + /// Open Addressing Entry /// /// /// - public class OpenAddressingHashTable : IDictionary where TKey : IComparable + private class OAHashEntry where TKey : IComparable { - - /// - /// Open Addressing Entry - /// - /// - /// - private class OAHashEntry where TKey : IComparable + public TKey key { get; set; } + public TValue value { get; set; } + public bool occupied { get; set; } + public OAHashEntry(TKey Key, TValue Value, bool occp) { - public TKey key { get; set; } - public TValue value { get; set; } - public bool occupied { get; set; } - public OAHashEntry(TKey Key, TValue Value, bool occp) - { - key = Key; - value = Value; - occupied = occp; - } + key = Key; + value = Value; + occupied = occp; } + } + + private int _size { get; set; } + private double _loadFactor { get; set; } + private int _inTable { get; set; } + private OAHashEntry[] _table { get; set; } + private List _keys { get; set; } + private List _values { get; set; } - private int _size { get; set; } - private double _loadFactor { get; set; } - private int _inTable { get; set; } - private OAHashEntry[] _table { get; set; } - private List _keys { get; set; } - private List _values { get; set; } - - /// - /// CONSTRUCTOR - /// - /// - public OpenAddressingHashTable(int size) + /// + /// CONSTRUCTOR + /// + /// + public OpenAddressingHashTable(int size) + { + _size = size; + _loadFactor = 0.40; + _inTable = 0; + _table = new OAHashEntry[_size]; + _keys = new List(); + _values = new List(); + + //initialize all values to -1 + for (int i = 0; i < _table.Length; i++) { - _size = size; - _loadFactor = 0.40; - _inTable = 0; - _table = new OAHashEntry[_size]; - _keys = new List(); - _values = new List(); - - //initialize all values to -1 - for (int i = 0; i < _table.Length; i++) - { - //initialize each slot - _table[i] = new OAHashEntry(default, default, false); - } + //initialize each slot + _table[i] = new OAHashEntry(default, default, false); } + } - //doubles the size of the table - private void _expand() + //doubles the size of the table + private void _expand() + { + //will hold contents of _table to copy over + OAHashEntry[] temp = new OAHashEntry[_size]; + temp = _table; + //double the size and rehash + _size *= 2; + OAHashEntry[] exp = new OAHashEntry[_size]; + for (int i = 0; i < exp.Length; i++) { - //will hold contents of _table to copy over - OAHashEntry[] temp = new OAHashEntry[_size]; - temp = _table; - //double the size and rehash - _size *= 2; - OAHashEntry[] exp = new OAHashEntry[_size]; - for (int i = 0; i < exp.Length; i++) - { - //initialize each slot - exp[i] = new OAHashEntry(default, default, false); - } - - _inTable = 0; - _table = exp; - //rehash over the newly sized table - for (int i = 0; i < temp.Length; i++) - { - //this should rehash since the size is now doubled so the hashing will be different - //inserts the key into _table - Add(temp[i].key, temp[i].value); - } + //initialize each slot + exp[i] = new OAHashEntry(default, default, false); } - //rehashes table - private void _rehash() + _inTable = 0; + _table = exp; + //rehash over the newly sized table + for (int i = 0; i < temp.Length; i++) { - //will hold contents of _table to copy over - OAHashEntry[] temp = new OAHashEntry[_size]; - temp = _table; - - OAHashEntry[] rehash = new OAHashEntry[_size]; - for (int i = 0; i < rehash.Length; i++) - { - //initialize each slot - rehash[i] = new OAHashEntry(default, default, false); - } + //this should rehash since the size is now doubled so the hashing will be different + //inserts the key into _table + Add(temp[i].key, temp[i].value); + } + } - _inTable = 0; - _table = rehash; - //rehash over the newly sized table - for (int i = 0; i < temp.Length; i++) - { - //this should rehash since the size is now doubled so the hashing will be different - //inserts the key into _table - Add(temp[i].key, temp[i].value); - } + //rehashes table + private void _rehash() + { + //will hold contents of _table to copy over + OAHashEntry[] temp = new OAHashEntry[_size]; + temp = _table; + OAHashEntry[] rehash = new OAHashEntry[_size]; + for (int i = 0; i < rehash.Length; i++) + { + //initialize each slot + rehash[i] = new OAHashEntry(default, default, false); } - private int _double_hash(TKey key, int i) + _inTable = 0; + _table = rehash; + //rehash over the newly sized table + for (int i = 0; i < temp.Length; i++) { - int hash_value = 0; - int second_hash_value = 0; - int slot = 0; + //this should rehash since the size is now doubled so the hashing will be different + //inserts the key into _table + Add(temp[i].key, temp[i].value); + } - //grabs hash value for a string - if (typeof(TKey) == typeof(string)) - { - //https://stackoverflow.com/questions/4092393/value-of-type-t-cannot-be-converted-to - TKey newTkeyString = (TKey)(object)key; - string newTkeyString2 = (string)(object)newTkeyString; - - //https://stackoverflow.com/questions/400733/how-to-get-ascii-value-of-string-in-c-sharp - byte[] asciiBytes = Encoding.ASCII.GetBytes(newTkeyString2); - - int string_value = 0; - foreach (byte bite in asciiBytes) - { - string_value += (int)bite; - } - - //calculates first hash values - hash_value = Convert.ToInt32(string_value) % _size; - //calculate second hash value - second_hash_value = 1 + Convert.ToInt32(string_value) % (_size - 1); - } - //grabs a hash value for a char - else if (typeof(TKey) == typeof(char)) - { - //https://stackoverflow.com/questions/4092393/value-of-type-t-cannot-be-converted-to - TKey newTkeyChar = (TKey)(object)key; - char newTkeyChar2 = (char)(object)newTkeyChar; + } - int char_value = (int)newTkeyChar2; + private int _double_hash(TKey key, int i) + { + int hash_value = 0; + int second_hash_value = 0; + int slot = 0; - //calculates first hash values - hash_value = Convert.ToInt32(char_value) % _size; - //calculate second hash value - second_hash_value = 1 + Convert.ToInt32(char_value) % (_size - 1); - } - else + //grabs hash value for a string + if (typeof(TKey) == typeof(string)) + { + //https://stackoverflow.com/questions/4092393/value-of-type-t-cannot-be-converted-to + TKey newTkeyString = (TKey)(object)key; + string newTkeyString2 = (string)(object)newTkeyString; + + //https://stackoverflow.com/questions/400733/how-to-get-ascii-value-of-string-in-c-sharp + byte[] asciiBytes = Encoding.ASCII.GetBytes(newTkeyString2); + + int string_value = 0; + foreach (byte bite in asciiBytes) { - //calculates first hash values - hash_value = Convert.ToInt32(key) % _size; - //calculate second hash value - second_hash_value = 1 + Convert.ToInt32(key) % (_size - 1); + string_value += (int)bite; } - //slot index based on first hash value, second hash value as an offset based on a counter, will also guarentee that the slot will be within the range 0 to size - slot = (hash_value + i * second_hash_value) % _size; - - return slot; + //calculates first hash values + hash_value = Convert.ToInt32(string_value) % _size; + //calculate second hash value + second_hash_value = 1 + Convert.ToInt32(string_value) % (_size - 1); } - - public void Add(TKey key, TValue value) + //grabs a hash value for a char + else if (typeof(TKey) == typeof(char)) { - int i = 0; + //https://stackoverflow.com/questions/4092393/value-of-type-t-cannot-be-converted-to + TKey newTkeyChar = (TKey)(object)key; + char newTkeyChar2 = (char)(object)newTkeyChar; - //makes sure there are no duplicate keys - if (ContainsKey(key)) - { - return; - } + int char_value = (int)newTkeyChar2; - do - { - //calculate index - int index = _double_hash(key, i); + //calculates first hash values + hash_value = Convert.ToInt32(char_value) % _size; + //calculate second hash value + second_hash_value = 1 + Convert.ToInt32(char_value) % (_size - 1); + } + else + { + //calculates first hash values + hash_value = Convert.ToInt32(key) % _size; + //calculate second hash value + second_hash_value = 1 + Convert.ToInt32(key) % (_size - 1); + } + //slot index based on first hash value, second hash value as an offset based on a counter, will also guarentee that the slot will be within the range 0 to size + slot = (hash_value + i * second_hash_value) % _size; - if (_table[index].occupied == false) - { - var newEntry = new OAHashEntry(key, value, true); - _keys.Add(key); - _values.Add(value); + return slot; + } - //set value and key - _table[index] = newEntry; - //increment how many items are in the table - _inTable++; - break; - } + public void Add(TKey key, TValue value) + { + int i = 0; - i++; + //makes sure there are no duplicate keys + if (ContainsKey(key)) + { + return; + } + + do + { + //calculate index + int index = _double_hash(key, i); - } while (i != _size); - //every slot is in the table is occupied - if (_inTable == _size) + if (_table[index].occupied == false) { - //expand and rehash - _expand(); + var newEntry = new OAHashEntry(key, value, true); + _keys.Add(key); + _values.Add(value); + + //set value and key + _table[index] = newEntry; + //increment how many items are in the table + _inTable++; + break; } - } - public void Add(KeyValuePair item) + i++; + + } while (i != _size); + + //every slot is in the table is occupied + if (_inTable == _size) { - Add(item.Key, item.Value); + //expand and rehash + _expand(); } + } - //returns value - public TValue this[TKey key] - { - get{ - int index = search(key); + public void Add(KeyValuePair item) + { + Add(item.Key, item.Value); + } - if (index != -1) - { - return _table[index].value; - } + //returns value + public TValue this[TKey key] + { + get{ + int index = search(key); - throw new KeyNotFoundException(); + if (index != -1) + { + return _table[index].value; } - set { - if (ContainsKey(key) == true) - { + throw new KeyNotFoundException(); + } + set { - int index = search(key); + if (ContainsKey(key) == true) + { - _table[index].value = value; + int index = search(key); - throw new KeyNotFoundException(); + _table[index].value = value; - } throw new KeyNotFoundException(); + } + throw new KeyNotFoundException(); } + } + + //removes key-value pair from the table + public bool Remove(TKey key) + { - //removes key-value pair from the table - public bool Remove(TKey key) + if (ContainsKey(key)) { + //find position and reset values + int index = search(key); + _keys.Clear(); + _values.Clear(); - if (ContainsKey(key)) - { - //find position and reset values - int index = search(key); - _keys.Clear(); - _values.Clear(); + _table[index].key = default; + _table[index].value = default; + _table[index].occupied = false; - _table[index].key = default; - _table[index].value = default; - _table[index].occupied = false; + //number of items in the table decreases + _inTable--; + //rehash table --necessary for Open Addressing since keys could have different positions due to this key + _rehash(); - //number of items in the table decreases - _inTable--; - //rehash table --necessary for Open Addressing since keys could have different positions due to this key - _rehash(); + return true; + } - return true; - } + return false; + } - return false; - } + //removes key-value pair from the table + public bool Remove(KeyValuePair item) + { + return Remove(item.Key); + } - //removes key-value pair from the table - public bool Remove(KeyValuePair item) + //clears table of all values + public void Clear() + { + _keys.Clear(); + _values.Clear(); + for (int i = 0; i < _table.Length; i++) { - return Remove(item.Key); + _table[i].key = default; + _table[i].value = default; + _table[i].occupied = false; } + _inTable = 0; + } - //clears table of all values - public void Clear() - { - _keys.Clear(); - _values.Clear(); - for (int i = 0; i < _table.Length; i++) - { - _table[i].key = default; - _table[i].value = default; - _table[i].occupied = false; - } - _inTable = 0; - } + //Tries to get the value of key which might not be in the dictionary. + public bool TryGetValue(TKey key, out TValue value) + { + int index = search(key); - //Tries to get the value of key which might not be in the dictionary. - public bool TryGetValue(TKey key, out TValue value) + if (index != -1) { - int index = search(key); + value = _table[index].value; - if (index != -1) - { - value = _table[index].value; + return true; + } - return true; - } + //not found + value = default; + return false; + } - //not found - value = default; - return false; - } + //finds the key and returns index in the table + public int search(TKey key) + { + int i = 0; - //finds the key and returns index in the table - public int search(TKey key) + do { - int i = 0; - - do + //calculate index + int index = _double_hash(key, i); + if (Equals(_table[index].key, key)) { - //calculate index - int index = _double_hash(key, i); - if (Equals(_table[index].key, key)) - { - return index; - } - i++; + return index; + } + i++; - } while (i < _size); + } while (i < _size); - return -1; - } + return -1; + } - //returns true if the key is in the table - public bool ContainsKey(TKey key) + //returns true if the key is in the table + public bool ContainsKey(TKey key) + { + if (search(key) != -1) { - if (search(key) != -1) - { - return true; - } - return false; + return true; } + return false; + } - //returns true if the key is in the table - public bool Contains(KeyValuePair item) + //returns true if the key is in the table + public bool Contains(KeyValuePair item) + { + if (ContainsKey(item.Key)) { - if (ContainsKey(item.Key)) - { - return true; - } - - return false; + return true; } - //returns the number of items in the table - public int Count => _inTable; + return false; + } - //returns bool depending on whether or not the table is read only - public bool IsReadOnly => false; + //returns the number of items in the table + public int Count => _inTable; - //returns a list of keys in the table - public ICollection Keys => _keys; + //returns bool depending on whether or not the table is read only + public bool IsReadOnly => false; - //returns a list of values in the table - public ICollection Values => _values; + //returns a list of keys in the table + public ICollection Keys => _keys; - //---------------------------------------------------------------------- - //-----------------------NOT IMPLEMENTED YET---------------------------- - //---------------------------------------------------------------------- + //returns a list of values in the table + public ICollection Values => _values; - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - throw new NotImplementedException(); - } + //---------------------------------------------------------------------- + //-----------------------NOT IMPLEMENTED YET---------------------------- + //---------------------------------------------------------------------- - public IEnumerator> GetEnumerator() - { - throw new NotImplementedException(); - } + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + throw new NotImplementedException(); + } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } + public IEnumerator> GetEnumerator() + { + throw new NotImplementedException(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); } -} +} \ No newline at end of file diff --git a/DataStructures/Dictionaries/OpenScatterHashTable.cs b/DataStructures/Dictionaries/OpenScatterHashTable.cs index 3e2d698d..49e61ec9 100644 --- a/DataStructures/Dictionaries/OpenScatterHashTable.cs +++ b/DataStructures/Dictionaries/OpenScatterHashTable.cs @@ -2,124 +2,149 @@ using System.Collections.Generic; using DataStructures.Common; -namespace DataStructures.Dictionaries -{ +namespace DataStructures.Dictionaries; +/// +/// Hash Table with Open Addressing. +/// +public class OpenScatterHashTable : IDictionary where TKey : IComparable +{ /// - /// Hash Table with Open Addressing. + /// Hash Table Cell. /// - public class OpenScatterHashTable : IDictionary where TKey : IComparable + private class HashTableEntry where TKey : IComparable { - /// - /// Hash Table Cell. - /// - private class HashTableEntry where TKey : IComparable + public TKey Key { get; set; } + public TValue Value { get; set; } + public EntryStatus Status { get; set; } + + public HashTableEntry() : this(default, default) { } + public HashTableEntry(TKey key, TValue value, EntryStatus status = EntryStatus.Occupied) { - public TKey Key { get; set; } - public TValue Value { get; set; } - public EntryStatus Status { get; set; } + Key = key; + Value = value; + Status = status; + } - public HashTableEntry() : this(default, default) { } - public HashTableEntry(TKey key, TValue value, EntryStatus status = EntryStatus.Occupied) - { - Key = key; - Value = value; - Status = status; - } + public bool IsEmpty => Status == EntryStatus.Empty; - public bool IsEmpty => Status == EntryStatus.Empty; + public bool IsOccupied => Status == EntryStatus.Occupied; - public bool IsOccupied => Status == EntryStatus.Occupied; + public bool IsDeleted => Status == EntryStatus.Deleted; + } - public bool IsDeleted => Status == EntryStatus.Deleted; - } + /// + /// INSTANCE VARIABLES + /// + private int _size; + private decimal _loadFactor; + private HashTableEntry[] _hashTableStore; - /// - /// INSTANCE VARIABLES - /// - private int _size; - private decimal _loadFactor; - private HashTableEntry[] _hashTableStore; + // Initialization-related + private const int _defaultCapacity = 7; + private static readonly HashTableEntry[] _emptyArray = new HashTableEntry[_defaultCapacity]; - // Initialization-related - private const int _defaultCapacity = 7; - private static readonly HashTableEntry[] _emptyArray = new HashTableEntry[_defaultCapacity]; + // Helper collections. + private List _keysCollection { get; set; } + private List _valuesCollection { get; set; } - // Helper collections. - private List _keysCollection { get; set; } - private List _valuesCollection { get; set; } + // Keys and Values Comparers + private EqualityComparer _keysComparer { get; set; } + private EqualityComparer _valuesComparer { get; set; } - // Keys and Values Comparers - private EqualityComparer _keysComparer { get; set; } - private EqualityComparer _valuesComparer { get; set; } + // A collection of prime numbers to use as hash table sizes. + internal static readonly PrimesList _primes = PrimesList.Instance; - // A collection of prime numbers to use as hash table sizes. - internal static readonly PrimesList _primes = PrimesList.Instance; + // This is the maximum prime that is smaller than the C# maximum allowed size of arrays. + // Check the following reference: + // C# Maximum Array Length (before encountering overflow). + // Link: http://referencesource.microsoft.com/#mscorlib/system/array.cs,2d2b551eabe74985 + private const int MAX_PRIME_ARRAY_LENGTH = 0x7FEFFFFD; - // This is the maximum prime that is smaller than the C# maximum allowed size of arrays. - // Check the following reference: - // C# Maximum Array Length (before encountering overflow). - // Link: http://referencesource.microsoft.com/#mscorlib/system/array.cs,2d2b551eabe74985 - private const int MAX_PRIME_ARRAY_LENGTH = 0x7FEFFFFD; + // Picked the HashPrime to be (101) because it is prime, and if the ‘hashSize - 1’ is not a multiple of this HashPrime, which is + // enforced in _getUpperBoundPrime, then expand function has the potential of being every value from 1 to hashSize - 1. + // The choice is largely arbitrary. + private const int HASH_PRIME = 101; - // Picked the HashPrime to be (101) because it is prime, and if the ‘hashSize - 1’ is not a multiple of this HashPrime, which is - // enforced in _getUpperBoundPrime, then expand function has the potential of being every value from 1 to hashSize - 1. - // The choice is largely arbitrary. - private const int HASH_PRIME = 101; + /// + /// The hash table cell status modes: Empty cell, Occupied cell, Deleted cell. + /// + private enum EntryStatus { Empty = 0, Occupied = 1, Deleted = 2 } - /// - /// The hash table cell status modes: Empty cell, Occupied cell, Deleted cell. - /// - private enum EntryStatus { Empty = 0, Occupied = 1, Deleted = 2 } + /// + /// Used in the ensure capacity function + /// + private enum CapacityManagementMode { Contract = 0, Expand = 1 } - /// - /// Used in the ensure capacity function - /// - private enum CapacityManagementMode { Contract = 0, Expand = 1 } + /// + /// Returns the next biggest prime that is greater than twice the size of the interal array (size * 2). + /// + private int _getExpandPrime(int oldSize) + { + int newSize = 2 * oldSize; - /// - /// Returns the next biggest prime that is greater than twice the size of the interal array (size * 2). - /// - private int _getExpandPrime(int oldSize) + // Allow the hashtables to grow to maximum possible size (~2G elements) before encoutering capacity overflow. + // Note that this check works even when _items.Length overflowed thanks to the (uint) cast + if ((uint)newSize > MAX_PRIME_ARRAY_LENGTH && MAX_PRIME_ARRAY_LENGTH > oldSize) { - int newSize = 2 * oldSize; + return MAX_PRIME_ARRAY_LENGTH; + } - // Allow the hashtables to grow to maximum possible size (~2G elements) before encoutering capacity overflow. - // Note that this check works even when _items.Length overflowed thanks to the (uint) cast - if ((uint)newSize > MAX_PRIME_ARRAY_LENGTH && MAX_PRIME_ARRAY_LENGTH > oldSize) - { - return MAX_PRIME_ARRAY_LENGTH; - } + return _primes.GetNextPrime(newSize); + } - return _primes.GetNextPrime(newSize); - } + /// + /// Get the next smaller prime that is smaller than half the size of the internal array (size / 2); + /// + private int _getContractPrime(int oldSize) + { + int newSize = oldSize / 2; + + return _primes.GetNextPrime(newSize); + } + + /// + /// Contracts the capacity of the keys and values arrays. + /// + private void _contractCapacity() + { + // Only contract the array if the number of elements is less than 1/3 of the total array size. + int oneThird = _hashTableStore.Length / 3; - /// - /// Get the next smaller prime that is smaller than half the size of the internal array (size / 2); - /// - private int _getContractPrime(int oldSize) + if (_size <= oneThird) { - int newSize = oldSize / 2; + int newCapacity = _hashTableStore.Length == 0 ? _defaultCapacity : _getContractPrime(_hashTableStore.Length); + + // Try to expand the size + HashTableEntry[] newKeysMap = new HashTableEntry[newCapacity]; + + if (_size > 0) + { + // REHASH + } - return _primes.GetNextPrime(newSize); + _hashTableStore = newKeysMap; } + } - /// - /// Contracts the capacity of the keys and values arrays. - /// - private void _contractCapacity() + /// + /// Expands the capacity of the keys and values arrays. + /// + private void _expandCapacity(int minCapacity) + { + if (_hashTableStore.Length < minCapacity) { - // Only contract the array if the number of elements is less than 1/3 of the total array size. - int oneThird = _hashTableStore.Length / 3; + int newCapacity = _hashTableStore.Length == 0 ? _defaultCapacity : _getExpandPrime(_hashTableStore.Length * 2); - if (_size <= oneThird) - { - int newCapacity = _hashTableStore.Length == 0 ? _defaultCapacity : _getContractPrime(_hashTableStore.Length); + if (newCapacity >= MAX_PRIME_ARRAY_LENGTH) + newCapacity = MAX_PRIME_ARRAY_LENGTH; - // Try to expand the size + // Try to expand the size + try + { HashTableEntry[] newKeysMap = new HashTableEntry[newCapacity]; if (_size > 0) @@ -129,137 +154,110 @@ private void _contractCapacity() _hashTableStore = newKeysMap; } - } - - /// - /// Expands the capacity of the keys and values arrays. - /// - private void _expandCapacity(int minCapacity) - { - if (_hashTableStore.Length < minCapacity) + catch (OutOfMemoryException) { - int newCapacity = _hashTableStore.Length == 0 ? _defaultCapacity : _getExpandPrime(_hashTableStore.Length * 2); - - if (newCapacity >= MAX_PRIME_ARRAY_LENGTH) - newCapacity = MAX_PRIME_ARRAY_LENGTH; - - // Try to expand the size - try - { - HashTableEntry[] newKeysMap = new HashTableEntry[newCapacity]; - - if (_size > 0) - { - // REHASH - } - - _hashTableStore = newKeysMap; - } - catch (OutOfMemoryException) - { - throw; - } + throw; } } + } - /// - /// A high-level functon that handles both contraction and expansion of the internal collection. - /// - /// Contract or Expand. - /// The new expansion size. - private void _ensureCapacity(CapacityManagementMode mode, int newSize = -1) - { - // If the size of the internal collection is less than or equal to third of - // ... the total capacity then contract the internal collection - int oneThird = _hashTableStore.Length / 3; + /// + /// A high-level functon that handles both contraction and expansion of the internal collection. + /// + /// Contract or Expand. + /// The new expansion size. + private void _ensureCapacity(CapacityManagementMode mode, int newSize = -1) + { + // If the size of the internal collection is less than or equal to third of + // ... the total capacity then contract the internal collection + int oneThird = _hashTableStore.Length / 3; - if (mode == CapacityManagementMode.Contract && _size <= oneThird) - { - _contractCapacity(); - } - else if (mode == CapacityManagementMode.Expand && newSize > 0) - { - _expandCapacity(newSize); - } + if (mode == CapacityManagementMode.Contract && _size <= oneThird) + { + _contractCapacity(); } - - /// - /// Returns an integer that represents the key. - /// Used in the _hashKey function. - /// - private int _getPreHashOfKey(TKey key) + else if (mode == CapacityManagementMode.Expand && newSize > 0) { - return Math.Abs(_keysComparer.GetHashCode(key)); + _expandCapacity(newSize); } + } + /// + /// Returns an integer that represents the key. + /// Used in the _hashKey function. + /// + private int _getPreHashOfKey(TKey key) + { + return Math.Abs(_keysComparer.GetHashCode(key)); + } - public void Add(TKey key, TValue value) - { - throw new NotImplementedException(); - } - public bool ContainsKey(TKey key) - { - throw new NotImplementedException(); - } + public void Add(TKey key, TValue value) + { + throw new NotImplementedException(); + } - public ICollection Keys => throw new NotImplementedException(); + public bool ContainsKey(TKey key) + { + throw new NotImplementedException(); + } - public bool Remove(TKey key) - { - throw new NotImplementedException(); - } + public ICollection Keys => throw new NotImplementedException(); - public bool TryGetValue(TKey key, out TValue value) - { - throw new NotImplementedException(); - } + public bool Remove(TKey key) + { + throw new NotImplementedException(); + } - public ICollection Values => throw new NotImplementedException(); + public bool TryGetValue(TKey key, out TValue value) + { + throw new NotImplementedException(); + } - public TValue this[TKey key] - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } + public ICollection Values => throw new NotImplementedException(); - public void Add(KeyValuePair item) - { - throw new NotImplementedException(); - } + public TValue this[TKey key] + { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } - public void Clear() - { - throw new NotImplementedException(); - } + public void Add(KeyValuePair item) + { + throw new NotImplementedException(); + } - public bool Contains(KeyValuePair item) - { - throw new NotImplementedException(); - } + public void Clear() + { + throw new NotImplementedException(); + } - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - throw new NotImplementedException(); - } + public bool Contains(KeyValuePair item) + { + throw new NotImplementedException(); + } - public int Count => throw new NotImplementedException(); + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + throw new NotImplementedException(); + } - public bool IsReadOnly => throw new NotImplementedException(); + public int Count => throw new NotImplementedException(); - public bool Remove(KeyValuePair item) - { - throw new NotImplementedException(); - } + public bool IsReadOnly => throw new NotImplementedException(); - public IEnumerator> GetEnumerator() - { - throw new NotImplementedException(); - } + public bool Remove(KeyValuePair item) + { + throw new NotImplementedException(); + } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } + public IEnumerator> GetEnumerator() + { + throw new NotImplementedException(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); } -} +} \ No newline at end of file diff --git a/DataStructures/Graphs/CliqueGraph.cs b/DataStructures/Graphs/CliqueGraph.cs index 03c76a3d..8f3d7fa8 100644 --- a/DataStructures/Graphs/CliqueGraph.cs +++ b/DataStructures/Graphs/CliqueGraph.cs @@ -2,802 +2,800 @@ using System.Collections.Generic; using DataStructures.Lists; -namespace DataStructures.Graphs +namespace DataStructures.Graphs; + +/// +/// Represents an unweighted undirected graph, modeling with a set of its maximal complete subgraphs of it. +/// Should be fast in clustered graphs +/// +public class CliqueGraph : IGraph where T : IComparable, IEquatable { - /// - /// Represents an unweighted undirected graph, modeling with a set of its maximal complete subgraphs of it. - /// Should be fast in clustered graphs - /// - public class CliqueGraph : IGraph where T : IComparable, IEquatable + public class Clique : HashSet, IComparable { - public class Clique : HashSet, IComparable + public Clique() + : base() { - public Clique() - : base() - { - } + } - public Clique(ISet elements) - : base(elements) - { - } + public Clique(ISet elements) + : base(elements) + { + } - #region IComparable implementation + #region IComparable implementation - int IComparable.CompareTo(Clique other) - { - throw new NotImplementedException(); - } + int IComparable.CompareTo(Clique other) + { + throw new NotImplementedException(); + } - #endregion + #endregion - public override string ToString() + public override string ToString() + { + string ret = "{"; + foreach (var x in this) { - string ret = "{"; - foreach (var x in this) - { - ret += x.ToString() + " "; - } - ret += "}"; - return ret; + ret += x.ToString() + " "; } + ret += "}"; + return ret; } + } - #region Model + #region Model - /// - /// Vertices of the graph. - /// - ICollection _vertices = new HashSet(); + /// + /// Vertices of the graph. + /// + ICollection _vertices = new HashSet(); - /// - /// A set of cliques minimal with the hability of charaterize the graph. - /// - ISet _cliques = new HashSet(); + /// + /// A set of cliques minimal with the hability of charaterize the graph. + /// + ISet _cliques = new HashSet(); - #endregion + #endregion - #region Constructors + #region Constructors - public CliqueGraph() - { - } + public CliqueGraph() + { + } - /// - /// Initializes a new instance of the class. - /// Copies the model from another graph. - /// - /// Graph. - public CliqueGraph(IGraph graph) - : this(graph.Vertices) + /// + /// Initializes a new instance of the class. + /// Copies the model from another graph. + /// + /// Graph. + public CliqueGraph(IGraph graph) + : this(graph.Vertices) + { + foreach (var startVert in Vertices) { - foreach (var startVert in Vertices) + foreach (var endVert in graph.Neighbours(startVert)) { - foreach (var endVert in graph.Neighbours(startVert)) + if (!HasEdge(startVert, endVert)) { - if (!HasEdge(startVert, endVert)) - { - // Add vortex - Clique newClan = new Clique(); - newClan.Add(startVert); - newClan.Add(endVert); - - ExpandToMaximal(graph, newClan); - _cliques.Add(newClan); - } + // Add vortex + Clique newClan = new Clique(); + newClan.Add(startVert); + newClan.Add(endVert); + + ExpandToMaximal(graph, newClan); + _cliques.Add(newClan); } } } + } - /// - /// Initializes a new instance of the class. - /// - /// Initial vertices of the graph - public CliqueGraph(IEnumerable vertices) - : this() + /// + /// Initializes a new instance of the class. + /// + /// Initial vertices of the graph + public CliqueGraph(IEnumerable vertices) + : this() + { + if (vertices == null) { - if (vertices == null) - { - System.Diagnostics.Debug.WriteLine("Cannot initialize an instance of a CliqueGraph with NULL vertices;\ninvoking default constructor."); - } - else - { - AddVertices(vertices); - } + System.Diagnostics.Debug.WriteLine("Cannot initialize an instance of a CliqueGraph with NULL vertices;\ninvoking default constructor."); + } + else + { + AddVertices(vertices); } + } - #endregion + #endregion - #region Internal + #region Internal - /// - /// Determines if a set of vertices is complete as a subgraph of this - /// - /// true, if the set is a complete subgraph, false otherwise. - /// A set of vertices of this graph. - public bool IsComplete(ISet vertices) - { - if (!vertices.IsSubsetOf(_vertices)) - throw new Exception("The param in CliqueGraph.IsComplete should be a subset of Vertices"); + /// + /// Determines if a set of vertices is complete as a subgraph of this + /// + /// true, if the set is a complete subgraph, false otherwise. + /// A set of vertices of this graph. + public bool IsComplete(ISet vertices) + { + if (!vertices.IsSubsetOf(_vertices)) + throw new Exception("The param in CliqueGraph.IsComplete should be a subset of Vertices"); - /* - * vertices is complete iff [vertices]² \subseteq \bigcup_{c \in cliques} [c]² - * where [x]² is the set of all subsets of x of cardinality 2. - */ + /* + * vertices is complete iff [vertices]² \subseteq \bigcup_{c \in cliques} [c]² + * where [x]² is the set of all subsets of x of cardinality 2. +*/ - ISet> H = getPairs(vertices); + ISet> H = getPairs(vertices); - foreach (var clan in _cliques) - { - ISet> exc = getPairs(clan); - H.ExceptWith(exc); - } - return H.Count == 0; + foreach (var clan in _cliques) + { + ISet> exc = getPairs(clan); + H.ExceptWith(exc); } + return H.Count == 0; + } - /// - /// Determines if a set of vertices is complete as a subgraph of another graph - /// - /// true, if the set is a complete subgraph, false otherwise. - /// A graph to determine 'completness' - /// A set of vertices of graph. - static bool IsComplete(IGraph graph, ISet vertices) + /// + /// Determines if a set of vertices is complete as a subgraph of another graph + /// + /// true, if the set is a complete subgraph, false otherwise. + /// A graph to determine 'completness' + /// A set of vertices of graph. + static bool IsComplete(IGraph graph, ISet vertices) + { + foreach (var x in vertices) { - foreach (var x in vertices) + foreach (var y in vertices) { - foreach (var y in vertices) - { - if (!graph.HasEdge(x, y)) - return false; - } + if (!graph.HasEdge(x, y)) + return false; } - return true; } + return true; + } - /// - /// Expands a clique to a maximal complete - /// - /// Clique to expand - void ExpandToMaximal(Clique clan) - { - Clique maximalityChecker; // Temporal clique for checking maximality - - // Expand NewClique to a maximal complete subgraph - foreach (var z in Vertices) - { - if (!clan.Contains(z)) - { - maximalityChecker = new Clique(clan); - maximalityChecker.Add(z); - if (IsComplete(maximalityChecker)) - clan.Add(z); - } - } + /// + /// Expands a clique to a maximal complete + /// + /// Clique to expand + void ExpandToMaximal(Clique clan) + { + Clique maximalityChecker; // Temporal clique for checking maximality - // Destroy every no maximal elements of the graph - HashSet clone = new HashSet(_cliques); - clone.Remove(clan); - foreach (var c in clone) // Iterate over a clone of _cliques + // Expand NewClique to a maximal complete subgraph + foreach (var z in Vertices) + { + if (!clan.Contains(z)) { - if (clan.IsSupersetOf(c)) - _cliques.Remove(c); + maximalityChecker = new Clique(clan); + maximalityChecker.Add(z); + if (IsComplete(maximalityChecker)) + clan.Add(z); } - } - /// - /// Expands a clique to a maximal complete in a given graph - /// - /// Graph to use to determine maximality. - /// Clique to expand. - static void ExpandToMaximal(IGraph graph, Clique clan) + // Destroy every no maximal elements of the graph + HashSet clone = new HashSet(_cliques); + clone.Remove(clan); + foreach (var c in clone) // Iterate over a clone of _cliques { - Clique tempo; // Temporal clique for checking maximality - // Expand NewClique to a maximal complete subgraph - foreach (var z in graph.Vertices) - { - if (!clan.Contains(z)) - { - tempo = new Clique(clan); - tempo.Add(z); - if (IsComplete(graph, tempo)) - clan.Add(z); - } - } + if (clan.IsSupersetOf(c)) + _cliques.Remove(c); } - /// - /// Some (temporary) class to compare unorderer pairs. - /// - class PairComparer : IEqualityComparer> - { - #region IEqualityComparer implementation + } - bool IEqualityComparer>.Equals(UnordererPair x, UnordererPair y) + /// + /// Expands a clique to a maximal complete in a given graph + /// + /// Graph to use to determine maximality. + /// Clique to expand. + static void ExpandToMaximal(IGraph graph, Clique clan) + { + Clique tempo; // Temporal clique for checking maximality + // Expand NewClique to a maximal complete subgraph + foreach (var z in graph.Vertices) + { + if (!clan.Contains(z)) { - return ((IEquatable>)x).Equals(y); + tempo = new Clique(clan); + tempo.Add(z); + if (IsComplete(graph, tempo)) + clan.Add(z); } + } + } - int IEqualityComparer>.GetHashCode(UnordererPair obj) - { - return obj.Item1.GetHashCode() + obj.Item2.GetHashCode(); - } + /// + /// Some (temporary) class to compare unorderer pairs. + /// + class PairComparer : IEqualityComparer> + { + #region IEqualityComparer implementation - #endregion + bool IEqualityComparer>.Equals(UnordererPair x, UnordererPair y) + { + return ((IEquatable>)x).Equals(y); + } + int IEqualityComparer>.GetHashCode(UnordererPair obj) + { + return obj.Item1.GetHashCode() + obj.Item2.GetHashCode(); } - /// - /// Return the subsets of cardinality 2 of a given collection. ie [vertices]². - /// - /// Returns an ISet whose elements are every subset of a given set of cardinality 2. - /// Collection whose pairs are going to be returned. - ISet> getPairs(ICollection vertices) + #endregion + + } + + /// + /// Return the subsets of cardinality 2 of a given collection. ie [vertices]². + /// + /// Returns an ISet whose elements are every subset of a given set of cardinality 2. + /// Collection whose pairs are going to be returned. + ISet> getPairs(ICollection vertices) + { + T[] arr = new T[vertices.Count]; + ISet> ret = new HashSet>(new PairComparer()); + vertices.CopyTo(arr, 0); + for (int i = 0; i < vertices.Count; i++) { - T[] arr = new T[vertices.Count]; - ISet> ret = new HashSet>(new PairComparer()); - vertices.CopyTo(arr, 0); - for (int i = 0; i < vertices.Count; i++) + for (int j = i + 1; j < vertices.Count; j++) { - for (int j = i + 1; j < vertices.Count; j++) - { - ret.Add(new UnordererPair(arr[i], arr[j])); - } + ret.Add(new UnordererPair(arr[i], arr[j])); } - return ret; } + return ret; + } - #endregion + #endregion - #region IGraph implementation + #region IGraph implementation - /// - /// An enumerable collection of all graph edges. - /// - public IEnumerable> Edges + /// + /// An enumerable collection of all graph edges. + /// + public IEnumerable> Edges + { + get { - get - { - List> returnEdges = new List>(); + List> returnEdges = new List>(); - foreach (var edge in getEdges()) - { - returnEdges.Add(new UnweightedEdge(edge.Item1, edge.Item2)); - returnEdges.Add(new UnweightedEdge(edge.Item2, edge.Item1)); - } - return returnEdges; + foreach (var edge in getEdges()) + { + returnEdges.Add(new UnweightedEdge(edge.Item1, edge.Item2)); + returnEdges.Add(new UnweightedEdge(edge.Item2, edge.Item1)); } + return returnEdges; } + } - /// - /// Get all incoming edges to vertex. - /// - public IEnumerable> IncomingEdges(T vertex) - { - List> incomingEdges = new List>(); + /// + /// Get all incoming edges to vertex. + /// + public IEnumerable> IncomingEdges(T vertex) + { + List> incomingEdges = new List>(); - foreach (var c in _cliques) + foreach (var c in _cliques) + { + if (c.Contains(vertex)) { - if (c.Contains(vertex)) + foreach (var item in c) { - foreach (var item in c) - { - if (!incomingEdges.Exists(x => x.Source.Equals(item))) - incomingEdges.Add(new UnweightedEdge(item, vertex)); - } + if (!incomingEdges.Exists(x => x.Source.Equals(item))) + incomingEdges.Add(new UnweightedEdge(item, vertex)); } } + } - return incomingEdges; + return incomingEdges; - } + } - /// - /// Get all outgoing edges from a vertex. - /// - public IEnumerable> OutgoingEdges(T vertex) - { - List> outgoingEdges = new List>(); + /// + /// Get all outgoing edges from a vertex. + /// + public IEnumerable> OutgoingEdges(T vertex) + { + List> outgoingEdges = new List>(); - foreach (var c in _cliques) + foreach (var c in _cliques) + { + if (c.Contains(vertex)) { - if (c.Contains(vertex)) + foreach (var item in c) { - foreach (var item in c) - { - if (!outgoingEdges.Exists(x => x.Destination.Equals(item))) - outgoingEdges.Add(new UnweightedEdge(vertex, item)); - } + if (!outgoingEdges.Exists(x => x.Destination.Equals(item))) + outgoingEdges.Add(new UnweightedEdge(vertex, item)); } } - - return outgoingEdges; } - /// - /// Connects two vertices together. - /// - /// true, if edge was added, false otherwise. - /// First vertex. - /// Second vertex. - public bool AddEdge(T firstVertex, T secondVertex) - { - if (HasEdge(firstVertex, secondVertex)) - return false; - Clique NewClique = new Clique(); // The new clique that contains the edge (firstVertex, secondVertex) - _cliques.Add(NewClique); + return outgoingEdges; + } - _vertices.Add(firstVertex); - _vertices.Add(secondVertex); + /// + /// Connects two vertices together. + /// + /// true, if edge was added, false otherwise. + /// First vertex. + /// Second vertex. + public bool AddEdge(T firstVertex, T secondVertex) + { + if (HasEdge(firstVertex, secondVertex)) + return false; + Clique NewClique = new Clique(); // The new clique that contains the edge (firstVertex, secondVertex) + _cliques.Add(NewClique); - NewClique.Add(firstVertex); - NewClique.Add(secondVertex); + _vertices.Add(firstVertex); + _vertices.Add(secondVertex); - ExpandToMaximal(NewClique); - return true; - } + NewClique.Add(firstVertex); + NewClique.Add(secondVertex); - /// - /// Deletes an edge, if exists, between two vertices. - /// - /// true, if edge was removed, false otherwise. - /// First vertex. - /// Second vertex. - public bool RemoveEdge(T firstVertex, T secondVertex) - { - bool ret = false; - Clique splitting; - Clique removing = new Clique(); - removing.Add(firstVertex); - removing.Add(secondVertex); + ExpandToMaximal(NewClique); + return true; + } - foreach (var clan in new HashSet(_cliques)) //Iterating over a clone of cliques + /// + /// Deletes an edge, if exists, between two vertices. + /// + /// true, if edge was removed, false otherwise. + /// First vertex. + /// Second vertex. + public bool RemoveEdge(T firstVertex, T secondVertex) + { + bool ret = false; + Clique splitting; + Clique removing = new Clique(); + removing.Add(firstVertex); + removing.Add(secondVertex); + + foreach (var clan in new HashSet(_cliques)) //Iterating over a clone of cliques + { + if (clan.IsSupersetOf(removing)) { - if (clan.IsSupersetOf(removing)) - { - // clan should be eliminated from cliques and replaced by maximal refinements - _cliques.Remove(clan); + // clan should be eliminated from cliques and replaced by maximal refinements + _cliques.Remove(clan); - splitting = new Clique(clan); - splitting.Remove(firstVertex); - _cliques.Add(splitting); - ExpandToMaximal(splitting); + splitting = new Clique(clan); + splitting.Remove(firstVertex); + _cliques.Add(splitting); + ExpandToMaximal(splitting); - splitting = new Clique(clan); - splitting.Remove(secondVertex); - _cliques.Add(splitting); - ExpandToMaximal(splitting); + splitting = new Clique(clan); + splitting.Remove(secondVertex); + _cliques.Add(splitting); + ExpandToMaximal(splitting); - ret = true; // return true when finished - } + ret = true; // return true when finished } - return ret; } + return ret; + } - /// - /// Adds a list of vertices to the graph. - /// - /// Collection. - public void AddVertices(IEnumerable collection) - { - if (collection == null) - throw new ArgumentException(); - - foreach (var vertex in collection) - { - AddVertex(vertex); - } - } + /// + /// Adds a list of vertices to the graph. + /// + /// Collection. + public void AddVertices(IEnumerable collection) + { + if (collection == null) + throw new ArgumentException(); - /// - /// Adds a list of vertices to the graph. - /// - /// Collection. - void IGraph.AddVertices(IList collection) + foreach (var vertex in collection) { - AddVertices(collection); + AddVertex(vertex); } + } - /// - /// Adds a new vertex to graph. - /// - /// true, if vertex was added, false otherwise. - /// Vertex. - public bool AddVertex(T vertex) - { - bool ret = !_vertices.Contains(vertex); - _vertices.Add(vertex); - return ret; - } + /// + /// Adds a list of vertices to the graph. + /// + /// Collection. + void IGraph.AddVertices(IList collection) + { + AddVertices(collection); + } - /// - /// Removes the specified vertex from graph. - /// - /// true, if vertex was removed, false otherwise. - /// Vertex. - public bool RemoveVertex(T vertex) - { - // Remove vertex from set of vertices, return false if nothing was removed. - if (!_vertices.Remove(vertex)) - return false; + /// + /// Adds a new vertex to graph. + /// + /// true, if vertex was added, false otherwise. + /// Vertex. + public bool AddVertex(T vertex) + { + bool ret = !_vertices.Contains(vertex); + _vertices.Add(vertex); + return ret; + } + + /// + /// Removes the specified vertex from graph. + /// + /// true, if vertex was removed, false otherwise. + /// Vertex. + public bool RemoveVertex(T vertex) + { + // Remove vertex from set of vertices, return false if nothing was removed. + if (!_vertices.Remove(vertex)) + return false; - // Make the cliques consistent - foreach (var clan in new HashSet(_cliques)) // clone _cliques and iterate + // Make the cliques consistent + foreach (var clan in new HashSet(_cliques)) // clone _cliques and iterate + { + if (clan.Remove(vertex)) { - if (clan.Remove(vertex)) + // if clan was exhausted, remove it; + if (clan.Count <= 1) { - // if clan was exhausted, remove it; - if (clan.Count <= 1) - { - _cliques.Remove(clan); - } - else // else make it maximal - { - ExpandToMaximal(clan); - } + _cliques.Remove(clan); + } + else // else make it maximal + { + ExpandToMaximal(clan); } } - return true; } + return true; + } - /// - /// Determines whether this instance has edge the specified firstVertex secondVertex. - /// - /// true if this instance has edge the specified firstVertex secondVertex; otherwise, false. - /// First vertex. - /// Second vertex. - public bool HasEdge(T firstVertex, T secondVertex) - { - ISet edge = new HashSet(); - edge.Add(firstVertex); - edge.Add(secondVertex); - - // If [edge]² (= edge) is contained in some clan, there is an edge. - foreach (var clan in _cliques) - { - if (clan.IsSupersetOf(edge)) - return true; - } - return false; - } + /// + /// Determines whether this instance has edge the specified firstVertex secondVertex. + /// + /// true if this instance has edge the specified firstVertex secondVertex; otherwise, false. + /// First vertex. + /// Second vertex. + public bool HasEdge(T firstVertex, T secondVertex) + { + ISet edge = new HashSet(); + edge.Add(firstVertex); + edge.Add(secondVertex); - /// - /// Determines whether this graph has the specified vertex. - /// - /// true if this instance has vertex the specified vertex; otherwise, false. - /// Vertex. - public bool HasVertex(T vertex) + // If [edge]² (= edge) is contained in some clan, there is an edge. + foreach (var clan in _cliques) { - return _vertices.Contains(vertex); + if (clan.IsSupersetOf(edge)) + return true; } + return false; + } - /// - /// Returns the neighbours doubly-linked list for the specified vertex. - /// - /// Vertex. - public DLinkedList Neighbours(T vertex) - { - DLinkedList returnList = new DLinkedList(); + /// + /// Determines whether this graph has the specified vertex. + /// + /// true if this instance has vertex the specified vertex; otherwise, false. + /// Vertex. + public bool HasVertex(T vertex) + { + return _vertices.Contains(vertex); + } - foreach (var c in _cliques) + /// + /// Returns the neighbours doubly-linked list for the specified vertex. + /// + /// Vertex. + public DLinkedList Neighbours(T vertex) + { + DLinkedList returnList = new DLinkedList(); + + foreach (var c in _cliques) + { + if (c.Contains(vertex)) { - if (c.Contains(vertex)) + foreach (var item in c) { - foreach (var item in c) - { - if (!returnList.Contains(item)) - returnList.Append(item); - } + if (!returnList.Contains(item)) + returnList.Append(item); } } - - return returnList; } - public int Degree(T vertex) - { - return Neighbours(vertex).Count; - } + return returnList; + } - public string ToReadable() - { - throw new NotImplementedException(); - } + public int Degree(T vertex) + { + return Neighbours(vertex).Count; + } - public IEnumerable DepthFirstWalk() - { - throw new NotImplementedException(); - } + public string ToReadable() + { + throw new NotImplementedException(); + } - public IEnumerable DepthFirstWalk(T startingVertex) - { - throw new NotImplementedException(); - } + public IEnumerable DepthFirstWalk() + { + throw new NotImplementedException(); + } - public IEnumerable BreadthFirstWalk() - { - throw new NotImplementedException(); - } + public IEnumerable DepthFirstWalk(T startingVertex) + { + throw new NotImplementedException(); + } - public IEnumerable BreadthFirstWalk(T startingVertex) - { - throw new NotImplementedException(); - } + public IEnumerable BreadthFirstWalk() + { + throw new NotImplementedException(); + } - /// - /// Clear this graph. - /// - public void Clear() - { - _vertices.Clear(); - _cliques.Clear(); - } + public IEnumerable BreadthFirstWalk(T startingVertex) + { + throw new NotImplementedException(); + } - /// - /// Returns true, if graph is directed; false otherwise. - /// - /// true if this instance is directed; otherwise, false. - public bool IsDirected => false; - - /// - /// Returns true, if graph is weighted; false otherwise. - /// - /// true if this instance is weighted; otherwise, false. - public bool IsWeighted => false; - - /// - /// Gets the count of vetices. - /// - /// The vertices count. - public int VerticesCount => _vertices.Count; - - public int EdgesCount => getEdges().Count; - - /// - /// Returns the list of edges. - /// - /// - ICollection> getEdges() - { - ISet> H = new HashSet>(); + /// + /// Clear this graph. + /// + public void Clear() + { + _vertices.Clear(); + _cliques.Clear(); + } - foreach (var clan in _cliques) - { - ISet> union = getPairs(clan); - H.UnionWith(union); - } - return H; - } + /// + /// Returns true, if graph is directed; false otherwise. + /// + /// true if this instance is directed; otherwise, false. + public bool IsDirected => false; - /// - /// Returns the list of Vertices. - /// - /// The vertices. - IEnumerable IGraph.Vertices => _vertices; - - /// - /// Returns the list of Vertices. - /// - /// The vertices. - public ICollection Vertices => _vertices; - - /// - /// Gets the cloud of a collection of vetices. - /// A cloud of a collection is the union if the neighborhoods of its elements - /// - /// The cloud. - /// Collection. - public ISet GetCloud(ISet collection) - { - _getCloud(collection, new HashSet(_cliques)); - return collection; + /// + /// Returns true, if graph is weighted; false otherwise. + /// + /// true if this instance is weighted; otherwise, false. + public bool IsWeighted => false; - } + /// + /// Gets the count of vetices. + /// + /// The vertices count. + public int VerticesCount => _vertices.Count; - /// - /// Gets the cloud of a collection of vetices. - /// A cloud of a collection is the union if the neighborhoods of its elements - /// - /// The cloud. - /// Collection. - /// A set of cliques to use - private void _getCloud(ISet cloud, ICollection useCliques) - { + public int EdgesCount => getEdges().Count; - foreach (var clan in new HashSet(useCliques)) - { - if (cloud.Overlaps(clan)) - { - cloud.UnionWith(clan); - useCliques.Remove(clan); - } - } + /// + /// Returns the list of edges. + /// + /// + ICollection> getEdges() + { + ISet> H = new HashSet>(); + foreach (var clan in _cliques) + { + ISet> union = getPairs(clan); + H.UnionWith(union); } + return H; + } + + /// + /// Returns the list of Vertices. + /// + /// The vertices. + IEnumerable IGraph.Vertices => _vertices; - /// - /// Returns the conext component of a collection - /// - /// The component. - /// Collection. - private void _getComponentCollection(ISet collection) + /// + /// Returns the list of Vertices. + /// + /// The vertices. + public ICollection Vertices => _vertices; + + /// + /// Gets the cloud of a collection of vetices. + /// A cloud of a collection is the union if the neighborhoods of its elements + /// + /// The cloud. + /// Collection. + public ISet GetCloud(ISet collection) + { + _getCloud(collection, new HashSet(_cliques)); + return collection; + + } + + /// + /// Gets the cloud of a collection of vetices. + /// A cloud of a collection is the union if the neighborhoods of its elements + /// + /// The cloud. + /// Collection. + /// A set of cliques to use + private void _getCloud(ISet cloud, ICollection useCliques) + { + + foreach (var clan in new HashSet(useCliques)) { - int count = 0; - ICollection UnusedCliques = new HashSet(_cliques); - while (count < collection.Count) + if (cloud.Overlaps(clan)) { - count = collection.Count; - _getCloud(collection, UnusedCliques); + cloud.UnionWith(clan); + useCliques.Remove(clan); } } - /// - /// Returns the only connected component containing a given vertex. - /// - /// A collection containing the vertex of a connected component - /// Vertex. - public ICollection GetConnectedComponent(T vertex) + } + + /// + /// Returns the conext component of a collection + /// + /// The component. + /// Collection. + private void _getComponentCollection(ISet collection) + { + int count = 0; + ICollection UnusedCliques = new HashSet(_cliques); + while (count < collection.Count) { - if (!_vertices.Contains(vertex)) - throw new Exception("vertex should be a vertex of this graph."); - HashSet component = new HashSet(); - component.Add(vertex); - _getComponentCollection(component); - return component; + count = collection.Count; + _getCloud(collection, UnusedCliques); } + } - #endregion + /// + /// Returns the only connected component containing a given vertex. + /// + /// A collection containing the vertex of a connected component + /// Vertex. + public ICollection GetConnectedComponent(T vertex) + { + if (!_vertices.Contains(vertex)) + throw new Exception("vertex should be a vertex of this graph."); + HashSet component = new HashSet(); + component.Add(vertex); + _getComponentCollection(component); + return component; + } + + #endregion - #region Clique invariants - - /// - /// Returns the list of maximal cliques - /// - /// The get cliques. - public IReadOnlyCollection getCliques => - // TODO: getCliques, this does not return all the maximal cliques; - // only return enough of them. - (IReadOnlyCollection)_cliques; - - /// - /// Returns the clique number of the current graph. - /// - /// The clique number. - public int cliqueNumber => Pick(getMaximumCliques).Count; - - /// - /// Returns the collection of the maxium-sized cliques - /// - /// The get maximum cliques. - public IEnumerable getMaximumCliques + #region Clique invariants + + /// + /// Returns the list of maximal cliques + /// + /// The get cliques. + public IReadOnlyCollection getCliques => + // TODO: getCliques, this does not return all the maximal cliques; + // only return enough of them. + (IReadOnlyCollection)_cliques; + + /// + /// Returns the clique number of the current graph. + /// + /// The clique number. + public int cliqueNumber => Pick(getMaximumCliques).Count; + + /// + /// Returns the collection of the maxium-sized cliques + /// + /// The get maximum cliques. + public IEnumerable getMaximumCliques + { + get { - get + int maxSize = 0; + ICollection maxCliques = new HashSet(); + + foreach (var clan in getCliques) { - int maxSize = 0; - ICollection maxCliques = new HashSet(); + if (clan.Count > maxSize) + { + maxCliques.Clear(); + maxSize = clan.Count; + } - foreach (var clan in getCliques) + if (clan.Count == maxSize) { - if (clan.Count > maxSize) - { - maxCliques.Clear(); - maxSize = clan.Count; - } - - if (clan.Count == maxSize) - { - maxCliques.Add(clan); - } + maxCliques.Add(clan); } - return maxCliques; } + return maxCliques; } + } - #endregion + #endregion - #region Clique methods + #region Clique methods - /// - /// Determines if a set of vertices is complete as a subgraph of another graph - /// - /// true, if the set is a complete subgraph, false otherwise. - /// A set of vertices of graph. - public bool isComplete(IEnumerable vertices) - { - if (vertices == null) - throw new ArgumentException(); + /// + /// Determines if a set of vertices is complete as a subgraph of another graph + /// + /// true, if the set is a complete subgraph, false otherwise. + /// A set of vertices of graph. + public bool isComplete(IEnumerable vertices) + { + if (vertices == null) + throw new ArgumentException(); - foreach (var x in _cliques) - { - if (x.IsSupersetOf(vertices)) - return true; - } - return false; + foreach (var x in _cliques) + { + if (x.IsSupersetOf(vertices)) + return true; } + return false; + } - /// - /// Builds the graph of cliques of this graph - /// - /// The dual graph. - public IGraph buildDualGraph() + /// + /// Builds the graph of cliques of this graph + /// + /// The dual graph. + public IGraph buildDualGraph() + { + IGraph dualGraph = new UndirectedDenseGraph((uint)VerticesCount); + foreach (var clan in _cliques) { - IGraph dualGraph = new UndirectedDenseGraph((uint)VerticesCount); - foreach (var clan in _cliques) - { - dualGraph.AddVertex(clan); - } - foreach (var clan0 in _cliques) + dualGraph.AddVertex(clan); + } + foreach (var clan0 in _cliques) + { + foreach (var clan1 in _cliques) { - foreach (var clan1 in _cliques) + if (!clan0.Equals(clan1) && clan0.Overlaps(clan1)) // Equals = SetEquals here since cliques are maximal. { - if (!clan0.Equals(clan1) && clan0.Overlaps(clan1)) // Equals = SetEquals here since cliques are maximal. - { - dualGraph.AddEdge(clan0, clan1); - } + dualGraph.AddEdge(clan0, clan1); } } - return dualGraph; } + return dualGraph; + } - /// - /// Given a path in a dual graph, it return a corresponding path in this graph - /// - /// An equivalent path of the clique path. - /// Path. - public IEnumerable ReturnPathFromCliquePath(IEnumerable path) - { - ArrayList returnPath = new ArrayList(); - IList listPath = new List(path); - ISet intersection; - - // Pick any element of each intersection - for (int i = 0; i < listPath.Count - 1; i++) - { - intersection = new HashSet(listPath[i]); - intersection.IntersectWith(listPath[i + 1]); // intersection is never empty because 'path' should be a path in a dual graph. + /// + /// Given a path in a dual graph, it return a corresponding path in this graph + /// + /// An equivalent path of the clique path. + /// Path. + public IEnumerable ReturnPathFromCliquePath(IEnumerable path) + { + ArrayList returnPath = new ArrayList(); + IList listPath = new List(path); + ISet intersection; - returnPath.Add(Pick(intersection)); - } + // Pick any element of each intersection + for (int i = 0; i < listPath.Count - 1; i++) + { + intersection = new HashSet(listPath[i]); + intersection.IntersectWith(listPath[i + 1]); // intersection is never empty because 'path' should be a path in a dual graph. - return returnPath; + returnPath.Add(Pick(intersection)); } - #endregion + return returnPath; + } - /// - /// Picks any object in a ISet - /// - /// Set. - /// The 1st type parameter. - static V Pick(IEnumerable Set) - { - IEnumerator enumerator = ((IEnumerable)Set).GetEnumerator(); - V ret = enumerator.Current; - enumerator.Dispose(); - return ret; - } + #endregion + /// + /// Picks any object in a ISet + /// + /// Set. + /// The 1st type parameter. + static V Pick(IEnumerable Set) + { + IEnumerator enumerator = ((IEnumerable)Set).GetEnumerator(); + V ret = enumerator.Current; + enumerator.Dispose(); + return ret; } - internal class UnordererPair : Tuple, IEquatable> where T : IEquatable +} + +internal class UnordererPair : Tuple, IEquatable> where T : IEquatable +{ + public UnordererPair(T item0, T item1) + : base(item0, item1) { - public UnordererPair(T item0, T item1) - : base(item0, item1) - { - } + } - #region IEquatable implementation + #region IEquatable implementation - bool IEquatable>.Equals(UnordererPair other) - { - return - (Item1.Equals(other.Item1) && Item2.Equals(other.Item2)) || + bool IEquatable>.Equals(UnordererPair other) + { + return + (Item1.Equals(other.Item1) && Item2.Equals(other.Item2)) || (Item1.Equals(other.Item2) && Item2.Equals(other.Item1)); - } - - #endregion } -} + #endregion +} \ No newline at end of file diff --git a/DataStructures/Graphs/DirectedDenseGraph.cs b/DataStructures/Graphs/DirectedDenseGraph.cs index 5dd3bc93..0dc026de 100644 --- a/DataStructures/Graphs/DirectedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedDenseGraph.cs @@ -16,471 +16,468 @@ using DataStructures.Common; using DataStructures.Lists; -namespace DataStructures.Graphs +namespace DataStructures.Graphs; + +public class DirectedDenseGraph : IGraph where T : IComparable { - public class DirectedDenseGraph : IGraph where T : IComparable + /// + /// INSTANCE VARIABLES + /// + private const object EMPTY_VERTEX_SLOT = (object)null; + + protected virtual int _edgesCount { get; set; } + protected virtual int _verticesCount { get; set; } + protected virtual int _verticesCapacity { get; set; } + protected virtual ArrayList _vertices { get; set; } + protected virtual T _firstInsertedNode { get; set; } + protected virtual bool[,] _adjacencyMatrix { get; set; } + + + /// + /// CONSTRUCTOR + /// + public DirectedDenseGraph(uint capacity = 10) { - /// - /// INSTANCE VARIABLES - /// - private const object EMPTY_VERTEX_SLOT = (object)null; - - protected virtual int _edgesCount { get; set; } - protected virtual int _verticesCount { get; set; } - protected virtual int _verticesCapacity { get; set; } - protected virtual ArrayList _vertices { get; set; } - protected virtual T _firstInsertedNode { get; set; } - protected virtual bool[,] _adjacencyMatrix { get; set; } - - - /// - /// CONSTRUCTOR - /// - public DirectedDenseGraph(uint capacity = 10) - { - _edgesCount = 0; - _verticesCount = 0; - _verticesCapacity = (int)capacity; + _edgesCount = 0; + _verticesCount = 0; + _verticesCapacity = (int)capacity; - _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new bool[_verticesCapacity, _verticesCapacity]; - _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: false); - } + _vertices = new ArrayList(_verticesCapacity); + _adjacencyMatrix = new bool[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: false); + } - /// - /// Helper function. Checks if edge exist in graph. - /// - protected virtual bool _doesEdgeExist(int source, int destination) - { - return _adjacencyMatrix[source, destination] == true; - } + /// + /// Helper function. Checks if edge exist in graph. + /// + protected virtual bool _doesEdgeExist(int source, int destination) + { + return _adjacencyMatrix[source, destination] == true; + } - /// - /// Returns true, if graph is directed; false otherwise. - /// - public virtual bool IsDirected => true; - - /// - /// Returns true, if graph is weighted; false otherwise. - /// - public virtual bool IsWeighted => false; - - /// - /// Gets the count of vetices. - /// - public virtual int VerticesCount => _verticesCount; - - /// - /// Gets the count of edges. - /// - public virtual int EdgesCount => _edgesCount; - - /// - /// Returns the list of Vertices. - /// - public virtual IEnumerable Vertices + /// + /// Returns true, if graph is directed; false otherwise. + /// + public virtual bool IsDirected => true; + + /// + /// Returns true, if graph is weighted; false otherwise. + /// + public virtual bool IsWeighted => false; + + /// + /// Gets the count of vetices. + /// + public virtual int VerticesCount => _verticesCount; + + /// + /// Gets the count of edges. + /// + public virtual int EdgesCount => _edgesCount; + + /// + /// Returns the list of Vertices. + /// + public virtual IEnumerable Vertices + { + get { - get - { - foreach (var vertex in _vertices) - if (vertex != null) - yield return (T)vertex; - } + foreach (var vertex in _vertices) + if (vertex != null) + yield return (T)vertex; } + } - IEnumerable> IGraph.Edges => Edges; + IEnumerable> IGraph.Edges => Edges; - IEnumerable> IGraph.IncomingEdges(T vertex) - { - return IncomingEdges(vertex); - } + IEnumerable> IGraph.IncomingEdges(T vertex) + { + return IncomingEdges(vertex); + } - IEnumerable> IGraph.OutgoingEdges(T vertex) - { - return OutgoingEdges(vertex); - } + IEnumerable> IGraph.OutgoingEdges(T vertex) + { + return OutgoingEdges(vertex); + } - /// - /// An enumerable collection of all directed unweighted edges in graph. - /// - public virtual IEnumerable> Edges + /// + /// An enumerable collection of all directed unweighted edges in graph. + /// + public virtual IEnumerable> Edges + { + get { - get - { - foreach (var vertex in _vertices) - foreach (var outgoingEdge in OutgoingEdges((T)vertex)) - yield return outgoingEdge; - } + foreach (var vertex in _vertices) + foreach (var outgoingEdge in OutgoingEdges((T)vertex)) + yield return outgoingEdge; } + } - /// - /// Get all incoming directed unweighted edges to a vertex. - /// - public virtual IEnumerable> IncomingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); + /// + /// Get all incoming directed unweighted edges to a vertex. + /// + public virtual IEnumerable> IncomingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); - int source = _vertices.IndexOf(vertex); + int source = _vertices.IndexOf(vertex); - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + { + if (_vertices[adjacent] != null && _doesEdgeExist(adjacent, source)) { - if (_vertices[adjacent] != null && _doesEdgeExist(adjacent, source)) - { - yield return new UnweightedEdge( - (T)_vertices[adjacent], // from - vertex // to - ); - } - }//end-for - } + yield return new UnweightedEdge( + (T)_vertices[adjacent], // from + vertex // to + ); + } + }//end-for + } - /// - /// Get all outgoing directed unweighted edges from a vertex. - /// - public virtual IEnumerable> OutgoingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); + /// + /// Get all outgoing directed unweighted edges from a vertex. + /// + public virtual IEnumerable> OutgoingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); - int source = _vertices.IndexOf(vertex); + int source = _vertices.IndexOf(vertex); - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + { + if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) - { - yield return new UnweightedEdge( - vertex, // from - (T)_vertices[adjacent] // to - ); - } - }//end-for - } + yield return new UnweightedEdge( + vertex, // from + (T)_vertices[adjacent] // to + ); + } + }//end-for + } - /// - /// Connects two vertices together in the direction: first->second. - /// - public virtual bool AddEdge(T source, T destination) - { - // Get indices of vertices - int srcIndex = _vertices.IndexOf(source); - int dstIndex = _vertices.IndexOf(destination); + /// + /// Connects two vertices together in the direction: first->second. + /// + public virtual bool AddEdge(T source, T destination) + { + // Get indices of vertices + int srcIndex = _vertices.IndexOf(source); + int dstIndex = _vertices.IndexOf(destination); - // Check existence of vertices and non-existence of edge - if (srcIndex == -1 || dstIndex == -1) - return false; - if (_doesEdgeExist(srcIndex, dstIndex)) - return false; + // Check existence of vertices and non-existence of edge + if (srcIndex == -1 || dstIndex == -1) + return false; + if (_doesEdgeExist(srcIndex, dstIndex)) + return false; - _adjacencyMatrix[srcIndex, dstIndex] = true; + _adjacencyMatrix[srcIndex, dstIndex] = true; - // Increment edges count - ++_edgesCount; + // Increment edges count + ++_edgesCount; - return true; - } + return true; + } - /// - /// Removes edge, if exists, from source to destination. - /// - public virtual bool RemoveEdge(T source, T destination) - { - // Get indices of vertices - int srcIndex = _vertices.IndexOf(source); - int dstIndex = _vertices.IndexOf(destination); + /// + /// Removes edge, if exists, from source to destination. + /// + public virtual bool RemoveEdge(T source, T destination) + { + // Get indices of vertices + int srcIndex = _vertices.IndexOf(source); + int dstIndex = _vertices.IndexOf(destination); - // Check existence of vertices and non-existence of edge - if (srcIndex == -1 || dstIndex == -1) - return false; - if (!_doesEdgeExist(srcIndex, dstIndex)) - return false; + // Check existence of vertices and non-existence of edge + if (srcIndex == -1 || dstIndex == -1) + return false; + if (!_doesEdgeExist(srcIndex, dstIndex)) + return false; - _adjacencyMatrix[srcIndex, dstIndex] = false; + _adjacencyMatrix[srcIndex, dstIndex] = false; - // Increment edges count - --_edgesCount; + // Increment edges count + --_edgesCount; - return true; - } + return true; + } - /// - /// Add a collection of vertices to the graph. - /// - public virtual void AddVertices(IList collection) - { - if (collection == null) - throw new ArgumentNullException(); + /// + /// Add a collection of vertices to the graph. + /// + public virtual void AddVertices(IList collection) + { + if (collection == null) + throw new ArgumentNullException(); - foreach (var vertex in collection) - AddVertex(vertex); - } + foreach (var vertex in collection) + AddVertex(vertex); + } - /// - /// Add vertex to the graph - /// - public virtual bool AddVertex(T vertex) - { - // Return of the capacity is reached - if (_verticesCount >= _verticesCapacity) - return false; + /// + /// Add vertex to the graph + /// + public virtual bool AddVertex(T vertex) + { + // Return of the capacity is reached + if (_verticesCount >= _verticesCapacity) + return false; - // Return if vertex already exists - if (HasVertex(vertex)) - return false; + // Return if vertex already exists + if (HasVertex(vertex)) + return false; - // Initialize first inserted node - if (_verticesCount == 0) - _firstInsertedNode = vertex; + // Initialize first inserted node + if (_verticesCount == 0) + _firstInsertedNode = vertex; - // Try inserting vertex at previously lazy-deleted slot - int indexOfNull = _vertices.IndexOf(EMPTY_VERTEX_SLOT); + // Try inserting vertex at previously lazy-deleted slot + int indexOfNull = _vertices.IndexOf(EMPTY_VERTEX_SLOT); - if (indexOfNull != -1) - _vertices[indexOfNull] = vertex; - else - _vertices.Add(vertex); + if (indexOfNull != -1) + _vertices[indexOfNull] = vertex; + else + _vertices.Add(vertex); - // Increment vertices count - ++_verticesCount; + // Increment vertices count + ++_verticesCount; - return true; - } + return true; + } - /// - /// Removes the specified vertex from graph. - /// - public virtual bool RemoveVertex(T vertex) - { - // Return if graph is empty - if (_verticesCount == 0) - return false; + /// + /// Removes the specified vertex from graph. + /// + public virtual bool RemoveVertex(T vertex) + { + // Return if graph is empty + if (_verticesCount == 0) + return false; - // Get index of vertex - int index = _vertices.IndexOf(vertex); + // Get index of vertex + int index = _vertices.IndexOf(vertex); - // Return if vertex doesn't exists - if (index == -1) - return false; + // Return if vertex doesn't exists + if (index == -1) + return false; - // Lazy-delete the vertex from graph - //_vertices.Remove (vertex); - _vertices[index] = EMPTY_VERTEX_SLOT; + // Lazy-delete the vertex from graph + //_vertices.Remove (vertex); + _vertices[index] = EMPTY_VERTEX_SLOT; - // Decrement the vertices count - --_verticesCount; + // Decrement the vertices count + --_verticesCount; - // Remove all outgoing and incoming edges to this vertex - for (int i = 0; i < _verticesCapacity; ++i) + // Remove all outgoing and incoming edges to this vertex + for (int i = 0; i < _verticesCapacity; ++i) + { + // Source edge + if (_doesEdgeExist(index, i)) { - // Source edge - if (_doesEdgeExist(index, i)) - { - _adjacencyMatrix[index, i] = false; + _adjacencyMatrix[index, i] = false; - // Decrement the edges count - --_edgesCount; - } + // Decrement the edges count + --_edgesCount; + } - // Destination edge - if (_doesEdgeExist(i, index)) - { - _adjacencyMatrix[i, index] = false; + // Destination edge + if (_doesEdgeExist(i, index)) + { + _adjacencyMatrix[i, index] = false; - // Decrement the edges count - --_edgesCount; - } + // Decrement the edges count + --_edgesCount; } - - return true; } - /// - /// Checks whether there is an edge from source to destination. - /// - public virtual bool HasEdge(T source, T destination) - { - // Get indices of vertices - int srcIndex = _vertices.IndexOf(source); - int dstIndex = _vertices.IndexOf(destination); + return true; + } - // Check the existence of vertices and the directed edge - return srcIndex != -1 && dstIndex != -1 && _doesEdgeExist(srcIndex, dstIndex); - } + /// + /// Checks whether there is an edge from source to destination. + /// + public virtual bool HasEdge(T source, T destination) + { + // Get indices of vertices + int srcIndex = _vertices.IndexOf(source); + int dstIndex = _vertices.IndexOf(destination); - /// - /// Determines whether this graph has the specified vertex. - /// - public virtual bool HasVertex(T vertex) - { - return _vertices.Contains(vertex); - } + // Check the existence of vertices and the directed edge + return srcIndex != -1 && dstIndex != -1 && _doesEdgeExist(srcIndex, dstIndex); + } - /// - /// Returns the neighbours doubly-linked list for the specified vertex. - /// - public virtual DLinkedList Neighbours(T vertex) - { - var neighbors = new DLinkedList(); - int source = _vertices.IndexOf(vertex); + /// + /// Determines whether this graph has the specified vertex. + /// + public virtual bool HasVertex(T vertex) + { + return _vertices.Contains(vertex); + } - // Check existence of vertex - if (source != -1) - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) - if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) - neighbors.Append((T)_vertices[adjacent]); + /// + /// Returns the neighbours doubly-linked list for the specified vertex. + /// + public virtual DLinkedList Neighbours(T vertex) + { + var neighbors = new DLinkedList(); + int source = _vertices.IndexOf(vertex); - return neighbors; - } + // Check existence of vertex + if (source != -1) + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) + neighbors.Append((T)_vertices[adjacent]); - /// - /// Returns the degree of the specified vertex. - /// - public virtual int Degree(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException(); + return neighbors; + } - return Neighbours(vertex).Count; - } + /// + /// Returns the degree of the specified vertex. + /// + public virtual int Degree(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException(); - /// - /// Returns a human-readable string of the graph. - /// - public virtual string ToReadable() - { - string output = string.Empty; + return Neighbours(vertex).Count; + } - for (int i = 0; i < _vertices.Count; ++i) - { - if (_vertices[i] == null) - continue; + /// + /// Returns a human-readable string of the graph. + /// + public virtual string ToReadable() + { + string output = string.Empty; - var node = (T)_vertices[i]; - var adjacents = string.Empty; + for (int i = 0; i < _vertices.Count; ++i) + { + if (_vertices[i] == null) + continue; - output = String.Format("{0}\r\n{1}: [", output, node); + var node = (T)_vertices[i]; + var adjacents = string.Empty; - foreach (var adjacentNode in Neighbours(node)) - adjacents = String.Format("{0}{1},", adjacents, adjacentNode); + output = String.Format("{0}\r\n{1}: [", output, node); - if (adjacents.Length > 0) - adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); + foreach (var adjacentNode in Neighbours(node)) + adjacents = String.Format("{0}{1},", adjacents, adjacentNode); - output = String.Format("{0}{1}]", output, adjacents); - } + if (adjacents.Length > 0) + adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); - return output; + output = String.Format("{0}{1}]", output, adjacents); } - /// - /// A depth first search traversal of the graph starting from the first inserted node. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable DepthFirstWalk() - { - return DepthFirstWalk(_firstInsertedNode); - } + return output; + } - /// - /// A depth first search traversal of the graph, starting from a specified vertex. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable DepthFirstWalk(T source) - { - if (_verticesCount == 0) - return new ArrayList(); - if (!HasVertex(source)) - throw new Exception("The specified starting vertex doesn't exist."); + /// + /// A depth first search traversal of the graph starting from the first inserted node. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable DepthFirstWalk() + { + return DepthFirstWalk(_firstInsertedNode); + } - var stack = new Lists.Stack(_verticesCount); - var visited = new HashSet(); - var listOfNodes = new ArrayList(_verticesCount); + /// + /// A depth first search traversal of the graph, starting from a specified vertex. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable DepthFirstWalk(T source) + { + if (_verticesCount == 0) + return new ArrayList(); + if (!HasVertex(source)) + throw new Exception("The specified starting vertex doesn't exist."); - stack.Push(source); + var stack = new Lists.Stack(_verticesCount); + var visited = new HashSet(); + var listOfNodes = new ArrayList(_verticesCount); - while (!stack.IsEmpty) - { - var current = stack.Pop(); + stack.Push(source); - if (!visited.Contains(current)) - { - listOfNodes.Add(current); - visited.Add(current); + while (!stack.IsEmpty) + { + var current = stack.Pop(); - foreach (var adjacent in Neighbours(current)) - if (!visited.Contains(adjacent)) - stack.Push(adjacent); - } - } + if (!visited.Contains(current)) + { + listOfNodes.Add(current); + visited.Add(current); - return listOfNodes; + foreach (var adjacent in Neighbours(current)) + if (!visited.Contains(adjacent)) + stack.Push(adjacent); + } } - /// - /// A breadth first search traversal of the graphstarting from the first inserted node. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable BreadthFirstWalk() - { - return BreadthFirstWalk(_firstInsertedNode); - } + return listOfNodes; + } - /// - /// A breadth first search traversal of the graph, starting from a specified vertex. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable BreadthFirstWalk(T source) - { - if (_verticesCount == 0) - return new ArrayList(); - if (!HasVertex(source)) - throw new Exception("The specified starting vertex doesn't exist."); + /// + /// A breadth first search traversal of the graphstarting from the first inserted node. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable BreadthFirstWalk() + { + return BreadthFirstWalk(_firstInsertedNode); + } + + /// + /// A breadth first search traversal of the graph, starting from a specified vertex. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable BreadthFirstWalk(T source) + { + if (_verticesCount == 0) + return new ArrayList(); + if (!HasVertex(source)) + throw new Exception("The specified starting vertex doesn't exist."); - var visited = new HashSet(); - var queue = new Lists.Queue(VerticesCount); - var listOfNodes = new ArrayList(VerticesCount); + var visited = new HashSet(); + var queue = new Lists.Queue(VerticesCount); + var listOfNodes = new ArrayList(VerticesCount); - listOfNodes.Add(source); - visited.Add(source); + listOfNodes.Add(source); + visited.Add(source); - queue.Enqueue(source); + queue.Enqueue(source); - while (!queue.IsEmpty) - { - var current = queue.Dequeue(); - var neighbors = Neighbours(current); + while (!queue.IsEmpty) + { + var current = queue.Dequeue(); + var neighbors = Neighbours(current); - foreach (var adjacent in neighbors) + foreach (var adjacent in neighbors) + { + if (!visited.Contains(adjacent)) { - if (!visited.Contains(adjacent)) - { - listOfNodes.Add(adjacent); - visited.Add(adjacent); - queue.Enqueue(adjacent); - } + listOfNodes.Add(adjacent); + visited.Add(adjacent); + queue.Enqueue(adjacent); } } - - return listOfNodes; - } - - /// - /// Clear this graph. - /// - public virtual void Clear() - { - _edgesCount = 0; - _verticesCount = 0; - _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new bool[_verticesCapacity, _verticesCapacity]; - _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: false); } + return listOfNodes; } -} + /// + /// Clear this graph. + /// + public virtual void Clear() + { + _edgesCount = 0; + _verticesCount = 0; + _vertices = new ArrayList(_verticesCapacity); + _adjacencyMatrix = new bool[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: false); + } +} \ No newline at end of file diff --git a/DataStructures/Graphs/DirectedSparseGraph.cs b/DataStructures/Graphs/DirectedSparseGraph.cs index 257020c3..61b15853 100644 --- a/DataStructures/Graphs/DirectedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedSparseGraph.cs @@ -14,399 +14,397 @@ using DataStructures.Lists; -namespace DataStructures.Graphs +namespace DataStructures.Graphs; + +public class DirectedSparseGraph : IGraph where T : IComparable { - public class DirectedSparseGraph : IGraph where T : IComparable - { - /// - /// INSTANCE VARIABLES - /// - protected virtual int _edgesCount { get; set; } - protected virtual T _firstInsertedNode { get; set; } - protected virtual Dictionary> _adjacencyList { get; set; } + /// + /// INSTANCE VARIABLES + /// + protected virtual int _edgesCount { get; set; } + protected virtual T _firstInsertedNode { get; set; } + protected virtual Dictionary> _adjacencyList { get; set; } - /// - /// CONSTRUCTOR - /// - public DirectedSparseGraph() : this(10) { } + /// + /// CONSTRUCTOR + /// + public DirectedSparseGraph() : this(10) { } - public DirectedSparseGraph(uint initialCapacity) - { - _edgesCount = 0; - _adjacencyList = new Dictionary>((int)initialCapacity); - } + public DirectedSparseGraph(uint initialCapacity) + { + _edgesCount = 0; + _adjacencyList = new Dictionary>((int)initialCapacity); + } - /// - /// Helper function. Checks if edge exist in graph. - /// - protected virtual bool _doesEdgeExist(T vertex1, T vertex2) - { - return _adjacencyList[vertex1].Contains(vertex2); - } + /// + /// Helper function. Checks if edge exist in graph. + /// + protected virtual bool _doesEdgeExist(T vertex1, T vertex2) + { + return _adjacencyList[vertex1].Contains(vertex2); + } - /// - /// Returns true, if graph is directed; false otherwise. - /// - public virtual bool IsDirected => true; + /// + /// Returns true, if graph is directed; false otherwise. + /// + public virtual bool IsDirected => true; - /// - /// Returns true, if graph is weighted; false otherwise. - /// - public virtual bool IsWeighted => false; + /// + /// Returns true, if graph is weighted; false otherwise. + /// + public virtual bool IsWeighted => false; - /// - /// Gets the count of vetices. - /// - public virtual int VerticesCount => _adjacencyList.Count; + /// + /// Gets the count of vetices. + /// + public virtual int VerticesCount => _adjacencyList.Count; - /// - /// Gets the count of edges. - /// - public virtual int EdgesCount => _edgesCount; + /// + /// Gets the count of edges. + /// + public virtual int EdgesCount => _edgesCount; - /// - /// Returns the list of Vertices. - /// - public virtual IEnumerable Vertices + /// + /// Returns the list of Vertices. + /// + public virtual IEnumerable Vertices + { + get { - get - { - foreach (var vertex in _adjacencyList) - yield return vertex.Key; - } + foreach (var vertex in _adjacencyList) + yield return vertex.Key; } + } - IEnumerable> IGraph.Edges => Edges; + IEnumerable> IGraph.Edges => Edges; - IEnumerable> IGraph.IncomingEdges(T vertex) - { - return IncomingEdges(vertex); - } + IEnumerable> IGraph.IncomingEdges(T vertex) + { + return IncomingEdges(vertex); + } - IEnumerable> IGraph.OutgoingEdges(T vertex) - { - return OutgoingEdges(vertex); - } + IEnumerable> IGraph.OutgoingEdges(T vertex) + { + return OutgoingEdges(vertex); + } - /// - /// An enumerable collection of all directed unweighted edges in graph. - /// - public virtual IEnumerable> Edges + /// + /// An enumerable collection of all directed unweighted edges in graph. + /// + public virtual IEnumerable> Edges + { + get { - get - { - foreach (var vertex in _adjacencyList) - foreach (var adjacent in vertex.Value) - yield return new UnweightedEdge( - vertex.Key, // from - adjacent // to - ); - } + foreach (var vertex in _adjacencyList) + foreach (var adjacent in vertex.Value) + yield return new UnweightedEdge( + vertex.Key, // from + adjacent // to + ); } + } - /// - /// Get all incoming directed unweighted edges to a vertex. - /// - public virtual IEnumerable> IncomingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); + /// + /// Get all incoming directed unweighted edges to a vertex. + /// + public virtual IEnumerable> IncomingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); - foreach(var adjacent in _adjacencyList.Keys) - { - if (_adjacencyList[adjacent].Contains(vertex)) - yield return new UnweightedEdge( - adjacent, // from - vertex // to - ); - }//end-foreach - } - - /// - /// Get all outgoing directed unweighted edges from a vertex. - /// - public virtual IEnumerable> OutgoingEdges(T vertex) + foreach(var adjacent in _adjacencyList.Keys) { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); - - foreach(var adjacent in _adjacencyList[vertex]) + if (_adjacencyList[adjacent].Contains(vertex)) yield return new UnweightedEdge( - vertex, // from - adjacent // to + adjacent, // from + vertex // to ); - } + }//end-foreach + } + /// + /// Get all outgoing directed unweighted edges from a vertex. + /// + public virtual IEnumerable> OutgoingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); + + foreach(var adjacent in _adjacencyList[vertex]) + yield return new UnweightedEdge( + vertex, // from + adjacent // to + ); + } - /// - /// Connects two vertices together in the direction: first->second. - /// - public virtual bool AddEdge(T source, T destination) - { - // Check existence of nodes and non-existence of edge - if (!HasVertex(source) || !HasVertex(destination)) - return false; - if (_doesEdgeExist(source, destination)) - return false; - // Add edge from source to destination - _adjacencyList[source].Append(destination); + /// + /// Connects two vertices together in the direction: first->second. + /// + public virtual bool AddEdge(T source, T destination) + { + // Check existence of nodes and non-existence of edge + if (!HasVertex(source) || !HasVertex(destination)) + return false; + if (_doesEdgeExist(source, destination)) + return false; - // Increment edges count - ++_edgesCount; + // Add edge from source to destination + _adjacencyList[source].Append(destination); - return true; - } + // Increment edges count + ++_edgesCount; - /// - /// Removes edge, if exists, from source to destination. - /// - public virtual bool RemoveEdge(T source, T destination) - { - // Check existence of nodes and non-existence of edge - if (!HasVertex(source) || !HasVertex(destination)) - return false; - if (!_doesEdgeExist(source, destination)) - return false; + return true; + } - // Remove edge from source to destination - _adjacencyList[source].Remove(destination); + /// + /// Removes edge, if exists, from source to destination. + /// + public virtual bool RemoveEdge(T source, T destination) + { + // Check existence of nodes and non-existence of edge + if (!HasVertex(source) || !HasVertex(destination)) + return false; + if (!_doesEdgeExist(source, destination)) + return false; - // Decrement the edges count - --_edgesCount; + // Remove edge from source to destination + _adjacencyList[source].Remove(destination); - return true; - } + // Decrement the edges count + --_edgesCount; - /// - /// Add a collection of vertices to the graph. - /// - public virtual void AddVertices(IList collection) - { - if (collection == null) - throw new ArgumentNullException(); + return true; + } - foreach (var vertex in collection) - AddVertex(vertex); - } + /// + /// Add a collection of vertices to the graph. + /// + public virtual void AddVertices(IList collection) + { + if (collection == null) + throw new ArgumentNullException(); - /// - /// Add vertex to the graph - /// - public virtual bool AddVertex(T vertex) - { - if (HasVertex(vertex)) - return false; + foreach (var vertex in collection) + AddVertex(vertex); + } - if (_adjacencyList.Count == 0) - _firstInsertedNode = vertex; + /// + /// Add vertex to the graph + /// + public virtual bool AddVertex(T vertex) + { + if (HasVertex(vertex)) + return false; - _adjacencyList.Add(vertex, new DLinkedList()); + if (_adjacencyList.Count == 0) + _firstInsertedNode = vertex; - return true; - } + _adjacencyList.Add(vertex, new DLinkedList()); - /// - /// Removes the specified vertex from graph. - /// - public virtual bool RemoveVertex(T vertex) - { - // Check existence of vertex - if (!HasVertex(vertex)) - return false; + return true; + } - // Subtract the number of edges for this vertex from the total edges count - _edgesCount = _edgesCount - _adjacencyList[vertex].Count; + /// + /// Removes the specified vertex from graph. + /// + public virtual bool RemoveVertex(T vertex) + { + // Check existence of vertex + if (!HasVertex(vertex)) + return false; + + // Subtract the number of edges for this vertex from the total edges count + _edgesCount = _edgesCount - _adjacencyList[vertex].Count; - // Remove vertex from graph - _adjacencyList.Remove(vertex); + // Remove vertex from graph + _adjacencyList.Remove(vertex); - // Remove destination edges to this vertex - foreach (var adjacent in _adjacencyList) + // Remove destination edges to this vertex + foreach (var adjacent in _adjacencyList) + { + if (adjacent.Value.Contains(vertex)) { - if (adjacent.Value.Contains(vertex)) - { - adjacent.Value.Remove(vertex); + adjacent.Value.Remove(vertex); - // Decrement the edges count. - --_edgesCount; - } + // Decrement the edges count. + --_edgesCount; } - - return true; } - /// - /// Checks whether there is an edge from source to destination. - /// - public virtual bool HasEdge(T source, T destination) - { - return _adjacencyList.ContainsKey(source) && _adjacencyList.ContainsKey(destination) && _doesEdgeExist(source, destination); - } + return true; + } - /// - /// Checks whether a vertex exists in the graph - /// - public virtual bool HasVertex(T vertex) - { - return _adjacencyList.ContainsKey(vertex); - } + /// + /// Checks whether there is an edge from source to destination. + /// + public virtual bool HasEdge(T source, T destination) + { + return _adjacencyList.ContainsKey(source) && _adjacencyList.ContainsKey(destination) && _doesEdgeExist(source, destination); + } - /// - /// Returns the neighbours doubly-linked list for the specified vertex. - /// - public virtual DLinkedList Neighbours(T vertex) - { - if (!HasVertex(vertex)) - return null; + /// + /// Checks whether a vertex exists in the graph + /// + public virtual bool HasVertex(T vertex) + { + return _adjacencyList.ContainsKey(vertex); + } - return _adjacencyList[vertex]; - } + /// + /// Returns the neighbours doubly-linked list for the specified vertex. + /// + public virtual DLinkedList Neighbours(T vertex) + { + if (!HasVertex(vertex)) + return null; - /// - /// Returns the degree of the specified vertex. - /// - public virtual int Degree(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException(); + return _adjacencyList[vertex]; + } - return _adjacencyList[vertex].Count; - } + /// + /// Returns the degree of the specified vertex. + /// + public virtual int Degree(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException(); - /// - /// Returns a human-readable string of the graph. - /// - public virtual string ToReadable() - { - string output = string.Empty; + return _adjacencyList[vertex].Count; + } - foreach (var node in _adjacencyList) - { - var adjacents = string.Empty; + /// + /// Returns a human-readable string of the graph. + /// + public virtual string ToReadable() + { + string output = string.Empty; - output = String.Format("{0}\r\n{1}: [", output, node.Key); + foreach (var node in _adjacencyList) + { + var adjacents = string.Empty; - foreach (var adjacentNode in node.Value) - adjacents = String.Format("{0}{1},", adjacents, adjacentNode); + output = String.Format("{0}\r\n{1}: [", output, node.Key); - if (adjacents.Length > 0) - adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); + foreach (var adjacentNode in node.Value) + adjacents = String.Format("{0}{1},", adjacents, adjacentNode); - output = String.Format("{0}{1}]", output, adjacents); - } + if (adjacents.Length > 0) + adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); - return output; + output = String.Format("{0}{1}]", output, adjacents); } - /// - /// A depth first search traversal of the graph starting from the first inserted node. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable DepthFirstWalk() - { - return DepthFirstWalk(_firstInsertedNode); - } + return output; + } - /// - /// A depth first search traversal of the graph, starting from a specified vertex. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable DepthFirstWalk(T source) - { - // Check for existence of source - if (VerticesCount == 0) - return new ArrayList(0); - if (!HasVertex(source)) - throw new KeyNotFoundException("The source vertex doesn't exist."); + /// + /// A depth first search traversal of the graph starting from the first inserted node. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable DepthFirstWalk() + { + return DepthFirstWalk(_firstInsertedNode); + } - var visited = new HashSet(); - var stack = new Lists.Stack(); - var listOfNodes = new ArrayList(VerticesCount); + /// + /// A depth first search traversal of the graph, starting from a specified vertex. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable DepthFirstWalk(T source) + { + // Check for existence of source + if (VerticesCount == 0) + return new ArrayList(0); + if (!HasVertex(source)) + throw new KeyNotFoundException("The source vertex doesn't exist."); - stack.Push(source); + var visited = new HashSet(); + var stack = new Lists.Stack(); + var listOfNodes = new ArrayList(VerticesCount); - while (!stack.IsEmpty) - { - var current = stack.Pop(); + stack.Push(source); - if (!visited.Contains(current)) - { - listOfNodes.Add(current); - visited.Add(current); + while (!stack.IsEmpty) + { + var current = stack.Pop(); - foreach (var adjacent in Neighbours(current)) - if (!visited.Contains(adjacent)) - stack.Push(adjacent); - } - } + if (!visited.Contains(current)) + { + listOfNodes.Add(current); + visited.Add(current); - return listOfNodes; + foreach (var adjacent in Neighbours(current)) + if (!visited.Contains(adjacent)) + stack.Push(adjacent); + } } - /// - /// A breadth first search traversal of the graphstarting from the first inserted node. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable BreadthFirstWalk() - { - return BreadthFirstWalk(_firstInsertedNode); - } + return listOfNodes; + } - /// - /// A breadth first search traversal of the graph, starting from a specified vertex. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable BreadthFirstWalk(T source) - { - // Check for existence of source - if (VerticesCount == 0) - return new ArrayList(0); - if (!HasVertex(source)) - throw new KeyNotFoundException("The source vertex doesn't exist."); + /// + /// A breadth first search traversal of the graphstarting from the first inserted node. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable BreadthFirstWalk() + { + return BreadthFirstWalk(_firstInsertedNode); + } - var visited = new HashSet(); - var queue = new Lists.Queue(); - var listOfNodes = new ArrayList(VerticesCount); + /// + /// A breadth first search traversal of the graph, starting from a specified vertex. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable BreadthFirstWalk(T source) + { + // Check for existence of source + if (VerticesCount == 0) + return new ArrayList(0); + if (!HasVertex(source)) + throw new KeyNotFoundException("The source vertex doesn't exist."); - listOfNodes.Add(source); - visited.Add(source); + var visited = new HashSet(); + var queue = new Lists.Queue(); + var listOfNodes = new ArrayList(VerticesCount); - queue.Enqueue(source); + listOfNodes.Add(source); + visited.Add(source); - while (!queue.IsEmpty) - { - var current = queue.Dequeue(); - var neighbors = Neighbours(current); + queue.Enqueue(source); + + while (!queue.IsEmpty) + { + var current = queue.Dequeue(); + var neighbors = Neighbours(current); - foreach (var adjacent in neighbors) + foreach (var adjacent in neighbors) + { + if (!visited.Contains(adjacent)) { - if (!visited.Contains(adjacent)) - { - listOfNodes.Add(adjacent); - visited.Add(adjacent); - queue.Enqueue(adjacent); - } + listOfNodes.Add(adjacent); + visited.Add(adjacent); + queue.Enqueue(adjacent); } } - - return listOfNodes; } - /// - /// Clear this graph. - /// - public virtual void Clear() - { - _edgesCount = 0; - _adjacencyList.Clear(); - } + return listOfNodes; + } + /// + /// Clear this graph. + /// + public virtual void Clear() + { + _edgesCount = 0; + _adjacencyList.Clear(); } -} +} \ No newline at end of file diff --git a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs index 6b187580..4085b396 100644 --- a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs @@ -17,342 +17,338 @@ using DataStructures.Common; using DataStructures.Lists; -namespace DataStructures.Graphs +namespace DataStructures.Graphs; + +/// +/// This class represents the graph as an adjacency-matrix (two dimensional integer array). +/// +public class DirectedWeightedDenseGraph : DirectedDenseGraph, IWeightedGraph where T : IComparable { + /// + /// INSTANCE VARIABLES + /// + private const long EMPTY_EDGE_SLOT = 0; + private const object EMPTY_VERTEX_SLOT = (object)null; + + // Store edges and their weights as integers. + // Any edge with a value of zero means it doesn't exist. Otherwise, it exist with a specific weight value. + // Default value for positive edges is 1. + protected new long[,] _adjacencyMatrix { get; set; } + /// - /// This class represents the graph as an adjacency-matrix (two dimensional integer array). + /// CONSTRUCTOR /// - public class DirectedWeightedDenseGraph : DirectedDenseGraph, IWeightedGraph where T : IComparable + public DirectedWeightedDenseGraph(uint capacity = 10) { - /// - /// INSTANCE VARIABLES - /// - private const long EMPTY_EDGE_SLOT = 0; - private const object EMPTY_VERTEX_SLOT = (object)null; - - // Store edges and their weights as integers. - // Any edge with a value of zero means it doesn't exist. Otherwise, it exist with a specific weight value. - // Default value for positive edges is 1. - protected new long[,] _adjacencyMatrix { get; set; } - - - /// - /// CONSTRUCTOR - /// - public DirectedWeightedDenseGraph(uint capacity = 10) - { - _edgesCount = 0; - _verticesCount = 0; - _verticesCapacity = (int)capacity; + _edgesCount = 0; + _verticesCount = 0; + _verticesCapacity = (int)capacity; - _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; - _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); - } + _vertices = new ArrayList(_verticesCapacity); + _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); + } - /// - /// Helper function. Checks if edge exist in graph. - /// - protected override bool _doesEdgeExist(int source, int destination) - { - return _adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT; - } + /// + /// Helper function. Checks if edge exist in graph. + /// + protected override bool _doesEdgeExist(int source, int destination) + { + return _adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT; + } - /// - /// Helper function. Gets the weight of a directed edge. - /// - private long _getEdgeWeight(int source, int destination) - { - return _adjacencyMatrix[source, destination]; - } + /// + /// Helper function. Gets the weight of a directed edge. + /// + private long _getEdgeWeight(int source, int destination) + { + return _adjacencyMatrix[source, destination]; + } - /// - /// Returns true, if graph is weighted; false otherwise. - /// - public override bool IsWeighted => true; + /// + /// Returns true, if graph is weighted; false otherwise. + /// + public override bool IsWeighted => true; - /// - /// An enumerable collection of all weighted directed edges in graph. - /// - public virtual IEnumerable> Edges + /// + /// An enumerable collection of all weighted directed edges in graph. + /// + public virtual IEnumerable> Edges + { + get { - get - { - foreach (var vertex in _vertices) - foreach (var outgoingEdge in OutgoingEdges((T)vertex)) - yield return outgoingEdge; - } + foreach (var vertex in _vertices) + foreach (var outgoingEdge in OutgoingEdges((T)vertex)) + yield return outgoingEdge; } + } - /// - /// Get all incoming unweighted edges to a vertex. - /// - public virtual IEnumerable> IncomingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); + /// + /// Get all incoming unweighted edges to a vertex. + /// + public virtual IEnumerable> IncomingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); - int source = _vertices.IndexOf(vertex); + int source = _vertices.IndexOf(vertex); - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + { + if (_vertices[adjacent] != null && _doesEdgeExist(adjacent, source)) { - if (_vertices[adjacent] != null && _doesEdgeExist(adjacent, source)) - { - yield return new WeightedEdge( - (T)_vertices[adjacent], // from - vertex, // to - _getEdgeWeight(source, adjacent) // weight - ); - } - }//end-for - } + yield return new WeightedEdge( + (T)_vertices[adjacent], // from + vertex, // to + _getEdgeWeight(source, adjacent) // weight + ); + } + }//end-for + } - /// - /// Get all outgoing unweighted edges from a vertex. - /// - public virtual IEnumerable> OutgoingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); + /// + /// Get all outgoing unweighted edges from a vertex. + /// + public virtual IEnumerable> OutgoingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); - int source = _vertices.IndexOf(vertex); + int source = _vertices.IndexOf(vertex); - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + { + if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) - { - yield return new WeightedEdge( - vertex, // from - (T)_vertices[adjacent], // to - _getEdgeWeight(source, adjacent) // weight - ); - } - }//end-for - } + yield return new WeightedEdge( + vertex, // from + (T)_vertices[adjacent], // to + _getEdgeWeight(source, adjacent) // weight + ); + } + }//end-for + } - /// - /// Obsolete. Another AddEdge function is implemented with a weight parameter. - /// - [Obsolete("Use the AddEdge method with the weight parameter.")] - public new bool AddEdge(T source, T destination) - { - throw new NotImplementedException(); - } + /// + /// Obsolete. Another AddEdge function is implemented with a weight parameter. + /// + [Obsolete("Use the AddEdge method with the weight parameter.")] + public new bool AddEdge(T source, T destination) + { + throw new NotImplementedException(); + } - /// - /// Connects two vertices together with a weight, in the direction: first->second. - /// - public virtual bool AddEdge(T source, T destination, long weight) - { - // Return if the weight is equals to the empty edge value - if (weight == EMPTY_EDGE_SLOT) - return false; + /// + /// Connects two vertices together with a weight, in the direction: first->second. + /// + public virtual bool AddEdge(T source, T destination, long weight) + { + // Return if the weight is equals to the empty edge value + if (weight == EMPTY_EDGE_SLOT) + return false; - // Get indices of vertices - int srcIndex = _vertices.IndexOf(source); - int dstIndex = _vertices.IndexOf(destination); + // Get indices of vertices + int srcIndex = _vertices.IndexOf(source); + int dstIndex = _vertices.IndexOf(destination); - // Check existence of vertices and non-existence of edge - if (srcIndex == -1 || dstIndex == -1) - return false; - if (_doesEdgeExist(srcIndex, dstIndex)) - return false; + // Check existence of vertices and non-existence of edge + if (srcIndex == -1 || dstIndex == -1) + return false; + if (_doesEdgeExist(srcIndex, dstIndex)) + return false; - _adjacencyMatrix[srcIndex, dstIndex] = weight; + _adjacencyMatrix[srcIndex, dstIndex] = weight; - // Increment edges count - ++_edgesCount; + // Increment edges count + ++_edgesCount; - return true; - } + return true; + } - /// - /// Removes edge, if exists, from source to destination. - /// - public override bool RemoveEdge(T source, T destination) - { - // Get indices of vertices - int srcIndex = _vertices.IndexOf(source); - int dstIndex = _vertices.IndexOf(destination); + /// + /// Removes edge, if exists, from source to destination. + /// + public override bool RemoveEdge(T source, T destination) + { + // Get indices of vertices + int srcIndex = _vertices.IndexOf(source); + int dstIndex = _vertices.IndexOf(destination); - // Check existence of vertices and non-existence of edge - if (srcIndex == -1 || dstIndex == -1) - return false; - if (!_doesEdgeExist(srcIndex, dstIndex)) - return false; + // Check existence of vertices and non-existence of edge + if (srcIndex == -1 || dstIndex == -1) + return false; + if (!_doesEdgeExist(srcIndex, dstIndex)) + return false; - _adjacencyMatrix[srcIndex, dstIndex] = EMPTY_EDGE_SLOT; + _adjacencyMatrix[srcIndex, dstIndex] = EMPTY_EDGE_SLOT; - // Increment edges count - --_edgesCount; + // Increment edges count + --_edgesCount; - return true; - } + return true; + } - /// - /// Updates the edge weight from source to destination. - /// - public virtual bool UpdateEdgeWeight(T source, T destination, long weight) - { - // Return if the weight is equals to the empty edge value - if (weight == EMPTY_EDGE_SLOT) - return false; + /// + /// Updates the edge weight from source to destination. + /// + public virtual bool UpdateEdgeWeight(T source, T destination, long weight) + { + // Return if the weight is equals to the empty edge value + if (weight == EMPTY_EDGE_SLOT) + return false; - // Get indices of vertices - int srcIndex = _vertices.IndexOf(source); - int dstIndex = _vertices.IndexOf(destination); + // Get indices of vertices + int srcIndex = _vertices.IndexOf(source); + int dstIndex = _vertices.IndexOf(destination); - // Check existence of vertices and non-existence of edge - if (srcIndex == -1 || dstIndex == -1) - return false; - if (!_doesEdgeExist(srcIndex, dstIndex)) - return false; + // Check existence of vertices and non-existence of edge + if (srcIndex == -1 || dstIndex == -1) + return false; + if (!_doesEdgeExist(srcIndex, dstIndex)) + return false; - _adjacencyMatrix[srcIndex, dstIndex] = weight; + _adjacencyMatrix[srcIndex, dstIndex] = weight; - return true; - } + return true; + } - /// - /// Removes the specified vertex from graph. - /// - public override bool RemoveVertex(T vertex) - { - // Return if graph is empty - if (_verticesCount == 0) - return false; + /// + /// Removes the specified vertex from graph. + /// + public override bool RemoveVertex(T vertex) + { + // Return if graph is empty + if (_verticesCount == 0) + return false; - // Get index of vertex - int index = _vertices.IndexOf(vertex); + // Get index of vertex + int index = _vertices.IndexOf(vertex); - // Return if vertex doesn't exists - if (index == -1) - return false; + // Return if vertex doesn't exists + if (index == -1) + return false; - // Lazy-delete the vertex from graph - //_vertices.Remove (vertex); - _vertices[index] = EMPTY_VERTEX_SLOT; + // Lazy-delete the vertex from graph + //_vertices.Remove (vertex); + _vertices[index] = EMPTY_VERTEX_SLOT; - // Decrement the vertices count - --_verticesCount; + // Decrement the vertices count + --_verticesCount; - // Remove all outgoing and incoming edges to this vertex - for (int i = 0; i < _verticesCapacity; ++i) + // Remove all outgoing and incoming edges to this vertex + for (int i = 0; i < _verticesCapacity; ++i) + { + // Outgoing edge + if (_doesEdgeExist(index, i)) { - // Outgoing edge - if (_doesEdgeExist(index, i)) - { - _adjacencyMatrix[index, i] = EMPTY_EDGE_SLOT; - - // Decrement the edges count - --_edgesCount; - } - - // Incoming edge - if (_doesEdgeExist(i, index)) - { - _adjacencyMatrix[i, index] = EMPTY_EDGE_SLOT; - - // Decrement the edges count - --_edgesCount; - } + _adjacencyMatrix[index, i] = EMPTY_EDGE_SLOT; + + // Decrement the edges count + --_edgesCount; } - return true; + // Incoming edge + if (_doesEdgeExist(i, index)) + { + _adjacencyMatrix[i, index] = EMPTY_EDGE_SLOT; + + // Decrement the edges count + --_edgesCount; + } } - /// - /// Get edge object from source to destination. - /// - public virtual WeightedEdge GetEdge(T source, T destination) - { - // Get indices of vertices - int srcIndex = _vertices.IndexOf(source); - int dstIndex = _vertices.IndexOf(destination); + return true; + } - // Check the existence of vertices and the directed edge - if (srcIndex == -1 || dstIndex == -1) - throw new Exception("One of the vertices or both of them doesn't exist."); - if (!_doesEdgeExist(srcIndex, dstIndex)) - throw new Exception("Edge doesn't exist."); + /// + /// Get edge object from source to destination. + /// + public virtual WeightedEdge GetEdge(T source, T destination) + { + // Get indices of vertices + int srcIndex = _vertices.IndexOf(source); + int dstIndex = _vertices.IndexOf(destination); - return new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex)); - } + // Check the existence of vertices and the directed edge + if (srcIndex == -1 || dstIndex == -1) + throw new Exception("One of the vertices or both of them doesn't exist."); + if (!_doesEdgeExist(srcIndex, dstIndex)) + throw new Exception("Edge doesn't exist."); - /// - /// Returns the edge weight from source to destination. - /// - public virtual long GetEdgeWeight(T source, T destination) - { - return GetEdge(source, destination).Weight; - } - - /// - /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. - /// - public virtual Dictionary NeighboursMap(T vertex) - { - if (!HasVertex(vertex)) - return null; + return new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex)); + } - var neighbors = new Dictionary(); - int source = _vertices.IndexOf(vertex); + /// + /// Returns the edge weight from source to destination. + /// + public virtual long GetEdgeWeight(T source, T destination) + { + return GetEdge(source, destination).Weight; + } - // Check existence of vertex - if (source != -1) - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) - if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) - neighbors.Add((T)_vertices[adjacent], _getEdgeWeight(source, adjacent)); + /// + /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. + /// + public virtual Dictionary NeighboursMap(T vertex) + { + if (!HasVertex(vertex)) + return null; - return neighbors; - } + var neighbors = new Dictionary(); + int source = _vertices.IndexOf(vertex); - /// - /// Returns a human-readable string of the graph. - /// - public override string ToReadable() - { - string output = string.Empty; + // Check existence of vertex + if (source != -1) + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) + neighbors.Add((T)_vertices[adjacent], _getEdgeWeight(source, adjacent)); - for (int i = 0; i < _vertices.Count; ++i) - { - if (_vertices[i] == null) - continue; + return neighbors; + } - var node = (T)_vertices[i]; - var adjacents = string.Empty; + /// + /// Returns a human-readable string of the graph. + /// + public override string ToReadable() + { + string output = string.Empty; - output = String.Format("{0}\r\n{1}: [", output, node); + for (int i = 0; i < _vertices.Count; ++i) + { + if (_vertices[i] == null) + continue; - foreach (var adjacentNode in NeighboursMap(node)) - adjacents = String.Format("{0}{1}({2}), ", adjacents, adjacentNode.Key, adjacentNode.Value); + var node = (T)_vertices[i]; + var adjacents = string.Empty; - if (adjacents.Length > 0) - adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); + output = String.Format("{0}\r\n{1}: [", output, node); - output = String.Format("{0}{1}]", output, adjacents); - } + foreach (var adjacentNode in NeighboursMap(node)) + adjacents = String.Format("{0}{1}({2}), ", adjacents, adjacentNode.Key, adjacentNode.Value); - return output; - } + if (adjacents.Length > 0) + adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); - /// - /// Clear this graph. - /// - public override void Clear() - { - _edgesCount = 0; - _verticesCount = 0; - _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; - _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); + output = String.Format("{0}{1}]", output, adjacents); } + return output; } -} + /// + /// Clear this graph. + /// + public override void Clear() + { + _edgesCount = 0; + _verticesCount = 0; + _vertices = new ArrayList(_verticesCapacity); + _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); + } +} \ No newline at end of file diff --git a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs index f7c3840d..d4aed869 100644 --- a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs @@ -16,511 +16,509 @@ using DataStructures.Common; using DataStructures.Lists; -namespace DataStructures.Graphs +namespace DataStructures.Graphs; + +public class DirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable { - public class DirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable - { - /// - /// INSTANCE VARIABLES - /// - private const long EMPTY_EDGE_VALUE = 0; - protected virtual int _edgesCount { get; set; } - protected virtual T _firstInsertedNode { get; set; } - protected virtual Dictionary>> _adjacencyList { get; set; } + /// + /// INSTANCE VARIABLES + /// + private const long EMPTY_EDGE_VALUE = 0; + protected virtual int _edgesCount { get; set; } + protected virtual T _firstInsertedNode { get; set; } + protected virtual Dictionary>> _adjacencyList { get; set; } - /// - /// CONSTRUCTOR - /// - public DirectedWeightedSparseGraph() : this(10) { } + /// + /// CONSTRUCTOR + /// + public DirectedWeightedSparseGraph() : this(10) { } - public DirectedWeightedSparseGraph(uint initialCapacity) - { - _edgesCount = 0; - _adjacencyList = new Dictionary>>((int)initialCapacity); - } + public DirectedWeightedSparseGraph(uint initialCapacity) + { + _edgesCount = 0; + _adjacencyList = new Dictionary>>((int)initialCapacity); + } - /// - /// Helper function. Returns edge object from source to destination, if exists; otherwise, null. - /// - protected virtual WeightedEdge _tryGetEdge(T source, T destination) - { - WeightedEdge edge = null; + /// + /// Helper function. Returns edge object from source to destination, if exists; otherwise, null. + /// + protected virtual WeightedEdge _tryGetEdge(T source, T destination) + { + WeightedEdge edge = null; - // Predicate - var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); + // Predicate + var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); - // Try to find a match - if(_adjacencyList.ContainsKey(source)) - _adjacencyList[source].TryFindFirst(sourceToDestinationPredicate, out edge); + // Try to find a match + if(_adjacencyList.ContainsKey(source)) + _adjacencyList[source].TryFindFirst(sourceToDestinationPredicate, out edge); - // Return! - // Might return a null object. - return edge; - } + // Return! + // Might return a null object. + return edge; + } - /// - /// Helper function. Checks if edge exist in graph. - /// - protected virtual bool _doesEdgeExist(T source, T destination) - { - return _tryGetEdge(source, destination) != null; - } + /// + /// Helper function. Checks if edge exist in graph. + /// + protected virtual bool _doesEdgeExist(T source, T destination) + { + return _tryGetEdge(source, destination) != null; + } - /// - /// Helper function. Gets the weight of a directed edge. - /// Presumes edge does already exist. - /// - private long _getEdgeWeight(T source, T destination) - { - return _tryGetEdge(source, destination).Weight; - } + /// + /// Helper function. Gets the weight of a directed edge. + /// Presumes edge does already exist. + /// + private long _getEdgeWeight(T source, T destination) + { + return _tryGetEdge(source, destination).Weight; + } - /// - /// Returns true, if graph is directed; false otherwise. - /// - public virtual bool IsDirected => true; + /// + /// Returns true, if graph is directed; false otherwise. + /// + public virtual bool IsDirected => true; - /// - /// Returns true, if graph is weighted; false otherwise. - /// - public virtual bool IsWeighted => true; + /// + /// Returns true, if graph is weighted; false otherwise. + /// + public virtual bool IsWeighted => true; - /// - /// Gets the count of vetices. - /// - public int EdgesCount => _edgesCount; + /// + /// Gets the count of vetices. + /// + public int EdgesCount => _edgesCount; - /// - /// Gets the count of edges. - /// - public int VerticesCount => _adjacencyList.Count; + /// + /// Gets the count of edges. + /// + public int VerticesCount => _adjacencyList.Count; - /// - /// Returns the list of Vertices. - /// - public IEnumerable Vertices + /// + /// Returns the list of Vertices. + /// + public IEnumerable Vertices + { + get { - get - { - foreach (var vertex in _adjacencyList) - yield return vertex.Key; - } + foreach (var vertex in _adjacencyList) + yield return vertex.Key; } + } - IEnumerable> IGraph.Edges => Edges; + IEnumerable> IGraph.Edges => Edges; - IEnumerable> IGraph.IncomingEdges(T vertex) - { - return IncomingEdges(vertex); - } + IEnumerable> IGraph.IncomingEdges(T vertex) + { + return IncomingEdges(vertex); + } - IEnumerable> IGraph.OutgoingEdges(T vertex) - { - return OutgoingEdges(vertex); - } + IEnumerable> IGraph.OutgoingEdges(T vertex) + { + return OutgoingEdges(vertex); + } - /// - /// An enumerable collection of all directed weighted edges in graph. - /// - public virtual IEnumerable> Edges + /// + /// An enumerable collection of all directed weighted edges in graph. + /// + public virtual IEnumerable> Edges + { + get { - get - { - foreach (var vertex in _adjacencyList) - foreach (var edge in vertex.Value) - yield return edge; - } + foreach (var vertex in _adjacencyList) + foreach (var edge in vertex.Value) + yield return edge; } + } - /// - /// Get all incoming directed weighted edges to a vertex. - /// - public virtual IEnumerable> IncomingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); + /// + /// Get all incoming directed weighted edges to a vertex. + /// + public virtual IEnumerable> IncomingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); - var predicate = new Predicate>((edge) => edge.Destination.IsEqualTo(vertex)); + var predicate = new Predicate>((edge) => edge.Destination.IsEqualTo(vertex)); - foreach(var adjacent in _adjacencyList.Keys) - { - WeightedEdge incomingEdge = null; + foreach(var adjacent in _adjacencyList.Keys) + { + WeightedEdge incomingEdge = null; - if (_adjacencyList[adjacent].TryFindFirst(predicate, out incomingEdge)) - yield return incomingEdge; - }//end-foreach - } + if (_adjacencyList[adjacent].TryFindFirst(predicate, out incomingEdge)) + yield return incomingEdge; + }//end-foreach + } - /// - /// Get all outgoing directed weighted edges from a vertex. - /// - public virtual IEnumerable> OutgoingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); + /// + /// Get all outgoing directed weighted edges from a vertex. + /// + public virtual IEnumerable> OutgoingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); - foreach(var edge in _adjacencyList[vertex]) - yield return edge; - } + foreach(var edge in _adjacencyList[vertex]) + yield return edge; + } - /// - /// Obsolete. Another AddEdge function is implemented with a weight parameter. - /// - [Obsolete("Use the AddEdge method with the weight parameter.")] - public bool AddEdge(T source, T destination) - { - throw new NotImplementedException(); - } + /// + /// Obsolete. Another AddEdge function is implemented with a weight parameter. + /// + [Obsolete("Use the AddEdge method with the weight parameter.")] + public bool AddEdge(T source, T destination) + { + throw new NotImplementedException(); + } - /// - /// Connects two vertices together with a weight, in the direction: first->second. - /// - public bool AddEdge(T source, T destination, long weight) - { - // Check existence of nodes, the validity of the weight value, and the non-existence of edge - if (weight == EMPTY_EDGE_VALUE) - return false; - if (!HasVertex(source) || !HasVertex(destination)) - return false; - if (_doesEdgeExist(source, destination)) - return false; - - // Add edge from source to destination - var edge = new WeightedEdge(source, destination, weight); - _adjacencyList[source].Append(edge); - - // Increment edges count - ++_edgesCount; - - return true; - } + /// + /// Connects two vertices together with a weight, in the direction: first->second. + /// + public bool AddEdge(T source, T destination, long weight) + { + // Check existence of nodes, the validity of the weight value, and the non-existence of edge + if (weight == EMPTY_EDGE_VALUE) + return false; + if (!HasVertex(source) || !HasVertex(destination)) + return false; + if (_doesEdgeExist(source, destination)) + return false; - /// - /// Removes edge, if exists, from source to destination. - /// - public virtual bool RemoveEdge(T source, T destination) - { - // Check existence of nodes and non-existence of edge - if (!HasVertex(source) || !HasVertex(destination)) - return false; + // Add edge from source to destination + var edge = new WeightedEdge(source, destination, weight); + _adjacencyList[source].Append(edge); - // Try get edge - var edge = _tryGetEdge(source, destination); + // Increment edges count + ++_edgesCount; - // Return false if edge doesn't exists - if (edge == null) - return false; + return true; + } - // Remove edge from source to destination - _adjacencyList[source].Remove(edge); + /// + /// Removes edge, if exists, from source to destination. + /// + public virtual bool RemoveEdge(T source, T destination) + { + // Check existence of nodes and non-existence of edge + if (!HasVertex(source) || !HasVertex(destination)) + return false; - // Decrement the edges count - --_edgesCount; + // Try get edge + var edge = _tryGetEdge(source, destination); - return true; - } + // Return false if edge doesn't exists + if (edge == null) + return false; - public bool UpdateEdgeWeight(T source, T destination, long weight) - { - // Check existence of vertices and validity of the weight value - if (weight == EMPTY_EDGE_VALUE) - return false; - if (!HasVertex(source) || !HasVertex(destination)) - return false; + // Remove edge from source to destination + _adjacencyList[source].Remove(edge); - foreach (var edge in _adjacencyList[source]) - { - if (edge.Destination.IsEqualTo(destination)) - { - edge.Weight = weight; - return true; - } - } + // Decrement the edges count + --_edgesCount; + return true; + } + + public bool UpdateEdgeWeight(T source, T destination, long weight) + { + // Check existence of vertices and validity of the weight value + if (weight == EMPTY_EDGE_VALUE) + return false; + if (!HasVertex(source) || !HasVertex(destination)) return false; - } - /// - /// Get edge object from source to destination. - /// - public virtual WeightedEdge GetEdge(T source, T destination) + foreach (var edge in _adjacencyList[source]) { - if (!HasVertex(source) || !HasVertex(destination)) - throw new KeyNotFoundException("Either one of the vertices or both of them don't exist."); + if (edge.Destination.IsEqualTo(destination)) + { + edge.Weight = weight; + return true; + } + } - var edge = _tryGetEdge(source, destination); + return false; + } - // Check the existence of edge - if (edge == null) - throw new Exception("Edge doesn't exist."); + /// + /// Get edge object from source to destination. + /// + public virtual WeightedEdge GetEdge(T source, T destination) + { + if (!HasVertex(source) || !HasVertex(destination)) + throw new KeyNotFoundException("Either one of the vertices or both of them don't exist."); - // Try get edge - return edge; - } + var edge = _tryGetEdge(source, destination); - /// - /// Returns the edge weight from source to destination. - /// - public virtual long GetEdgeWeight(T source, T destination) - { - return GetEdge(source, destination).Weight; - } + // Check the existence of edge + if (edge == null) + throw new Exception("Edge doesn't exist."); - /// - /// Add a collection of vertices to the graph. - /// - public virtual void AddVertices(IList collection) - { - if (collection == null) - throw new ArgumentNullException(); + // Try get edge + return edge; + } - foreach (var vertex in collection) - AddVertex(vertex); - } + /// + /// Returns the edge weight from source to destination. + /// + public virtual long GetEdgeWeight(T source, T destination) + { + return GetEdge(source, destination).Weight; + } - /// - /// Add vertex to the graph - /// - public virtual bool AddVertex(T vertex) - { - if (_adjacencyList.ContainsKey(vertex)) - return false; + /// + /// Add a collection of vertices to the graph. + /// + public virtual void AddVertices(IList collection) + { + if (collection == null) + throw new ArgumentNullException(); - if (_adjacencyList.Count == 0) - _firstInsertedNode = vertex; + foreach (var vertex in collection) + AddVertex(vertex); + } - _adjacencyList.Add(vertex, new DLinkedList>()); + /// + /// Add vertex to the graph + /// + public virtual bool AddVertex(T vertex) + { + if (_adjacencyList.ContainsKey(vertex)) + return false; - return true; - } + if (_adjacencyList.Count == 0) + _firstInsertedNode = vertex; - /// - /// Removes the specified vertex from graph. - /// - public virtual bool RemoveVertex(T vertex) - { - // Check existence of vertex - if (!_adjacencyList.ContainsKey(vertex)) - return false; + _adjacencyList.Add(vertex, new DLinkedList>()); - // Subtract the number of edges for this vertex from the total edges count - _edgesCount = _edgesCount - _adjacencyList[vertex].Count; + return true; + } - // Remove vertex from graph - _adjacencyList.Remove(vertex); + /// + /// Removes the specified vertex from graph. + /// + public virtual bool RemoveVertex(T vertex) + { + // Check existence of vertex + if (!_adjacencyList.ContainsKey(vertex)) + return false; - // Remove destination edges to this vertex - foreach (var adjacent in _adjacencyList) - { - var edge = _tryGetEdge(adjacent.Key, vertex); + // Subtract the number of edges for this vertex from the total edges count + _edgesCount = _edgesCount - _adjacencyList[vertex].Count; - if (edge != null) - { - adjacent.Value.Remove(edge); + // Remove vertex from graph + _adjacencyList.Remove(vertex); - // Decrement the edges count. - --_edgesCount; - } - } + // Remove destination edges to this vertex + foreach (var adjacent in _adjacencyList) + { + var edge = _tryGetEdge(adjacent.Key, vertex); - return true; - } + if (edge != null) + { + adjacent.Value.Remove(edge); - /// - /// Checks whether there is an edge from source to destination. - /// - public virtual bool HasEdge(T source, T destination) - { - return _adjacencyList.ContainsKey(source) && _adjacencyList.ContainsKey(destination) && _doesEdgeExist(source, destination); + // Decrement the edges count. + --_edgesCount; + } } - /// - /// Checks whether a vertex exists in the graph - /// - public virtual bool HasVertex(T vertex) - { - return _adjacencyList.ContainsKey(vertex); - } + return true; + } - /// - /// Returns the neighbours doubly-linked list for the specified vertex. - /// - public virtual DLinkedList Neighbours(T vertex) - { - if (!HasVertex(vertex)) - return null; + /// + /// Checks whether there is an edge from source to destination. + /// + public virtual bool HasEdge(T source, T destination) + { + return _adjacencyList.ContainsKey(source) && _adjacencyList.ContainsKey(destination) && _doesEdgeExist(source, destination); + } - var neighbors = new DLinkedList(); - var adjacents = _adjacencyList[vertex]; + /// + /// Checks whether a vertex exists in the graph + /// + public virtual bool HasVertex(T vertex) + { + return _adjacencyList.ContainsKey(vertex); + } - foreach (var adjacent in adjacents) - neighbors.Append(adjacent.Destination); + /// + /// Returns the neighbours doubly-linked list for the specified vertex. + /// + public virtual DLinkedList Neighbours(T vertex) + { + if (!HasVertex(vertex)) + return null; - return neighbors; - } + var neighbors = new DLinkedList(); + var adjacents = _adjacencyList[vertex]; - /// - /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. - /// - public Dictionary NeighboursMap(T vertex) - { - if (!HasVertex(vertex)) - return null; + foreach (var adjacent in adjacents) + neighbors.Append(adjacent.Destination); - var neighbors = _adjacencyList[vertex]; - var map = new Dictionary(neighbors.Count); + return neighbors; + } - foreach (var adjacent in neighbors) - map.Add(adjacent.Destination, adjacent.Weight); + /// + /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. + /// + public Dictionary NeighboursMap(T vertex) + { + if (!HasVertex(vertex)) + return null; - return map; - } + var neighbors = _adjacencyList[vertex]; + var map = new Dictionary(neighbors.Count); - /// - /// Returns the degree of the specified vertex. - /// - public virtual int Degree(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException(); + foreach (var adjacent in neighbors) + map.Add(adjacent.Destination, adjacent.Weight); - return _adjacencyList[vertex].Count; - } + return map; + } - /// - /// Returns a human-readable string of the graph. - /// - public virtual string ToReadable() - { - string output = string.Empty; + /// + /// Returns the degree of the specified vertex. + /// + public virtual int Degree(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException(); - foreach (var node in _adjacencyList) - { - var adjacents = string.Empty; + return _adjacencyList[vertex].Count; + } - output = String.Format("{0}\r\n{1}: [", output, node.Key); + /// + /// Returns a human-readable string of the graph. + /// + public virtual string ToReadable() + { + string output = string.Empty; - foreach (var adjacentNode in node.Value) - adjacents = String.Format("{0}{1}({2}), ", adjacents, adjacentNode.Destination, adjacentNode.Weight); + foreach (var node in _adjacencyList) + { + var adjacents = string.Empty; - if (adjacents.Length > 0) - adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); + output = String.Format("{0}\r\n{1}: [", output, node.Key); - output = String.Format("{0}{1}]", output, adjacents); - } + foreach (var adjacentNode in node.Value) + adjacents = String.Format("{0}{1}({2}), ", adjacents, adjacentNode.Destination, adjacentNode.Weight); - return output; - } + if (adjacents.Length > 0) + adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); - /// - /// A depth first search traversal of the graph starting from the first inserted node. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable DepthFirstWalk() - { - return DepthFirstWalk(_firstInsertedNode); + output = String.Format("{0}{1}]", output, adjacents); } - /// - /// A depth first search traversal of the graph, starting from a specified vertex. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable DepthFirstWalk(T source) - { - // Check for existence of source - if (VerticesCount == 0) - return new ArrayList(0); - if (!HasVertex(source)) - throw new KeyNotFoundException("The source vertex doesn't exist."); + return output; + } - var visited = new HashSet(); - var stack = new Lists.Stack(); - var listOfNodes = new ArrayList(VerticesCount); + /// + /// A depth first search traversal of the graph starting from the first inserted node. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable DepthFirstWalk() + { + return DepthFirstWalk(_firstInsertedNode); + } - stack.Push(source); + /// + /// A depth first search traversal of the graph, starting from a specified vertex. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable DepthFirstWalk(T source) + { + // Check for existence of source + if (VerticesCount == 0) + return new ArrayList(0); + if (!HasVertex(source)) + throw new KeyNotFoundException("The source vertex doesn't exist."); - while (!stack.IsEmpty) - { - var current = stack.Pop(); + var visited = new HashSet(); + var stack = new Lists.Stack(); + var listOfNodes = new ArrayList(VerticesCount); - if (!visited.Contains(current)) - { - listOfNodes.Add(current); - visited.Add(current); + stack.Push(source); - foreach (var adjacent in Neighbours(current)) - if (!visited.Contains(adjacent)) - stack.Push(adjacent); - } - } + while (!stack.IsEmpty) + { + var current = stack.Pop(); - return listOfNodes; - } + if (!visited.Contains(current)) + { + listOfNodes.Add(current); + visited.Add(current); - /// - /// A breadth first search traversal of the graphstarting from the first inserted node. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable BreadthFirstWalk() - { - return BreadthFirstWalk(_firstInsertedNode); + foreach (var adjacent in Neighbours(current)) + if (!visited.Contains(adjacent)) + stack.Push(adjacent); + } } - /// - /// A breadth first search traversal of the graph, starting from a specified vertex. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable BreadthFirstWalk(T source) - { - // Check for existence of source - if (VerticesCount == 0) - return new ArrayList(0); - if (!HasVertex(source)) - throw new KeyNotFoundException("The source vertex doesn't exist."); + return listOfNodes; + } - var visited = new HashSet(); - var queue = new Lists.Queue(); - var listOfNodes = new ArrayList(VerticesCount); + /// + /// A breadth first search traversal of the graphstarting from the first inserted node. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable BreadthFirstWalk() + { + return BreadthFirstWalk(_firstInsertedNode); + } - listOfNodes.Add(source); - visited.Add(source); + /// + /// A breadth first search traversal of the graph, starting from a specified vertex. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable BreadthFirstWalk(T source) + { + // Check for existence of source + if (VerticesCount == 0) + return new ArrayList(0); + if (!HasVertex(source)) + throw new KeyNotFoundException("The source vertex doesn't exist."); - queue.Enqueue(source); + var visited = new HashSet(); + var queue = new Lists.Queue(); + var listOfNodes = new ArrayList(VerticesCount); - while (!queue.IsEmpty) - { - var current = queue.Dequeue(); - var neighbors = Neighbours(current); + listOfNodes.Add(source); + visited.Add(source); + + queue.Enqueue(source); - foreach (var adjacent in neighbors) + while (!queue.IsEmpty) + { + var current = queue.Dequeue(); + var neighbors = Neighbours(current); + + foreach (var adjacent in neighbors) + { + if (!visited.Contains(adjacent)) { - if (!visited.Contains(adjacent)) - { - listOfNodes.Add(adjacent); - visited.Add(adjacent); - queue.Enqueue(adjacent); - } + listOfNodes.Add(adjacent); + visited.Add(adjacent); + queue.Enqueue(adjacent); } } - - return listOfNodes; } - /// - /// Clear this graph. - /// - public virtual void Clear() - { - _edgesCount = 0; - _adjacencyList.Clear(); - } + return listOfNodes; + } + /// + /// Clear this graph. + /// + public virtual void Clear() + { + _edgesCount = 0; + _adjacencyList.Clear(); } -} +} \ No newline at end of file diff --git a/DataStructures/Graphs/IEdge.cs b/DataStructures/Graphs/IEdge.cs index 35371119..e7b8edbf 100644 --- a/DataStructures/Graphs/IEdge.cs +++ b/DataStructures/Graphs/IEdge.cs @@ -1,36 +1,34 @@ using System; -namespace DataStructures.Graphs +namespace DataStructures.Graphs; + +/// +/// This interface should be implemented by all edges classes. +/// +public interface IEdge : IComparable> where TVertex : IComparable { /// - /// This interface should be implemented by all edges classes. + /// Gets a value indicating whether this edge is weighted. /// - public interface IEdge : IComparable> where TVertex : IComparable - { - /// - /// Gets a value indicating whether this edge is weighted. - /// - /// true if this edge is weighted; otherwise, false. - bool IsWeighted { get; } - - /// - /// Gets or sets the source. - /// - /// The source. - TVertex Source { get; set; } + /// true if this edge is weighted; otherwise, false. + bool IsWeighted { get; } - /// - /// Gets or sets the destination. - /// - /// The destination. - TVertex Destination { get; set; } + /// + /// Gets or sets the source. + /// + /// The source. + TVertex Source { get; set; } - /// - /// Gets or sets the weight of edge. - /// Unwighted edges can be thought of as edges of the same weight - /// - /// The weight. - Int64 Weight { get; set; } - } -} + /// + /// Gets or sets the destination. + /// + /// The destination. + TVertex Destination { get; set; } + /// + /// Gets or sets the weight of edge. + /// Unwighted edges can be thought of as edges of the same weight + /// + /// The weight. + Int64 Weight { get; set; } +} \ No newline at end of file diff --git a/DataStructures/Graphs/IGraph.cs b/DataStructures/Graphs/IGraph.cs index 1ae595cc..40bd56e3 100644 --- a/DataStructures/Graphs/IGraph.cs +++ b/DataStructures/Graphs/IGraph.cs @@ -3,126 +3,124 @@ using DataStructures.Lists; -namespace DataStructures.Graphs -{ - public interface IGraph where T : IComparable - { - /// - /// Returns true, if graph is directed; false otherwise. - /// - bool IsDirected { get; } - - /// - /// Returns true, if graph is weighted; false otherwise. - /// - bool IsWeighted { get; } - - /// - /// Gets the count of vetices. - /// - int VerticesCount { get; } - - /// - /// Gets the count of edges. - /// - int EdgesCount { get; } - - /// - /// Returns the list of Vertices. - /// - IEnumerable Vertices { get; } - - /// - /// An enumerable collection of edges. - /// - IEnumerable> Edges { get; } - - /// - /// Get all incoming edges from vertex - /// - IEnumerable> IncomingEdges(T vertex); - - /// - /// Get all outgoing edges from vertex - /// - IEnumerable> OutgoingEdges(T vertex); - - /// - /// Connects two vertices together. - /// - bool AddEdge(T firstVertex, T secondVertex); - - /// - /// Deletes an edge, if exists, between two vertices. - /// - bool RemoveEdge(T firstVertex, T secondVertex); - - /// - /// Adds a list of vertices to the graph. - /// - void AddVertices(IList collection); - - /// - /// Adds a new vertex to graph. - /// - bool AddVertex(T vertex); - - /// - /// Removes the specified vertex from graph. - /// - bool RemoveVertex(T vertex); - - /// - /// Checks whether two vertices are connected (there is an edge between firstVertex & secondVertex) - /// - bool HasEdge(T firstVertex, T secondVertex); - - /// - /// Determines whether this graph has the specified vertex. - /// - bool HasVertex(T vertex); - - /// - /// Returns the neighbours doubly-linked list for the specified vertex. - /// - DLinkedList Neighbours(T vertex); - - /// - /// Returns the degree of the specified vertex. - /// - int Degree(T vertex); - - /// - /// Returns a human-readable string of the graph. - /// - string ToReadable(); - - /// - /// A depth first search traversal of the graph. Prints nodes as they get visited. - /// It considers the first inserted vertex as the start-vertex for the walk. - /// - IEnumerable DepthFirstWalk(); - - /// - /// A depth first search traversal of the graph, starting from a specified vertex. Prints nodes as they get visited. - /// - IEnumerable DepthFirstWalk(T startingVertex); - - /// - /// A breadth first search traversal of the graph. Prints nodes as they get visited. - /// It considers the first inserted vertex as the start-vertex for the walk. - /// - IEnumerable BreadthFirstWalk(); - - /// - /// A breadth first search traversal of the graph, starting from a specified vertex. Prints nodes as they get visited. - /// - IEnumerable BreadthFirstWalk(T startingVertex); - - /// - /// Clear this graph. - /// - void Clear(); - } -} +namespace DataStructures.Graphs; +public interface IGraph where T : IComparable +{ + /// + /// Returns true, if graph is directed; false otherwise. + /// + bool IsDirected { get; } + + /// + /// Returns true, if graph is weighted; false otherwise. + /// + bool IsWeighted { get; } + + /// + /// Gets the count of vetices. + /// + int VerticesCount { get; } + + /// + /// Gets the count of edges. + /// + int EdgesCount { get; } + + /// + /// Returns the list of Vertices. + /// + IEnumerable Vertices { get; } + + /// + /// An enumerable collection of edges. + /// + IEnumerable> Edges { get; } + + /// + /// Get all incoming edges from vertex + /// + IEnumerable> IncomingEdges(T vertex); + + /// + /// Get all outgoing edges from vertex + /// + IEnumerable> OutgoingEdges(T vertex); + + /// + /// Connects two vertices together. + /// + bool AddEdge(T firstVertex, T secondVertex); + + /// + /// Deletes an edge, if exists, between two vertices. + /// + bool RemoveEdge(T firstVertex, T secondVertex); + + /// + /// Adds a list of vertices to the graph. + /// + void AddVertices(IList collection); + + /// + /// Adds a new vertex to graph. + /// + bool AddVertex(T vertex); + + /// + /// Removes the specified vertex from graph. + /// + bool RemoveVertex(T vertex); + + /// + /// Checks whether two vertices are connected (there is an edge between firstVertex & secondVertex) + /// + bool HasEdge(T firstVertex, T secondVertex); + + /// + /// Determines whether this graph has the specified vertex. + /// + bool HasVertex(T vertex); + + /// + /// Returns the neighbours doubly-linked list for the specified vertex. + /// + DLinkedList Neighbours(T vertex); + + /// + /// Returns the degree of the specified vertex. + /// + int Degree(T vertex); + + /// + /// Returns a human-readable string of the graph. + /// + string ToReadable(); + + /// + /// A depth first search traversal of the graph. Prints nodes as they get visited. + /// It considers the first inserted vertex as the start-vertex for the walk. + /// + IEnumerable DepthFirstWalk(); + + /// + /// A depth first search traversal of the graph, starting from a specified vertex. Prints nodes as they get visited. + /// + IEnumerable DepthFirstWalk(T startingVertex); + + /// + /// A breadth first search traversal of the graph. Prints nodes as they get visited. + /// It considers the first inserted vertex as the start-vertex for the walk. + /// + IEnumerable BreadthFirstWalk(); + + /// + /// A breadth first search traversal of the graph, starting from a specified vertex. Prints nodes as they get visited. + /// + IEnumerable BreadthFirstWalk(T startingVertex); + + /// + /// Clear this graph. + /// + void Clear(); +} \ No newline at end of file diff --git a/DataStructures/Graphs/IWeightedGraph.cs b/DataStructures/Graphs/IWeightedGraph.cs index 66f3a857..5d31648e 100644 --- a/DataStructures/Graphs/IWeightedGraph.cs +++ b/DataStructures/Graphs/IWeightedGraph.cs @@ -1,36 +1,34 @@ using System; -namespace DataStructures.Graphs +namespace DataStructures.Graphs; + +/// +/// This interface should be implemented alongside the IGraph interface. +/// +public interface IWeightedGraph where T : IComparable { /// - /// This interface should be implemented alongside the IGraph interface. + /// Connects two vertices together with a weight, in the direction: first->second. /// - public interface IWeightedGraph where T : IComparable - { - /// - /// Connects two vertices together with a weight, in the direction: first->second. - /// - bool AddEdge(T source, T destination, long weight); - - /// - /// Updates the edge weight from source to destination. - /// - bool UpdateEdgeWeight(T source, T destination, long weight); + bool AddEdge(T source, T destination, long weight); - /// - /// Get edge object from source to destination. - /// - WeightedEdge GetEdge(T source, T destination); + /// + /// Updates the edge weight from source to destination. + /// + bool UpdateEdgeWeight(T source, T destination, long weight); - /// - /// Returns the edge weight from source to destination. - /// - long GetEdgeWeight(T source, T destination); + /// + /// Get edge object from source to destination. + /// + WeightedEdge GetEdge(T source, T destination); - /// - /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. - /// - System.Collections.Generic.Dictionary NeighboursMap(T vertex); - } -} + /// + /// Returns the edge weight from source to destination. + /// + long GetEdgeWeight(T source, T destination); + /// + /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. + /// + System.Collections.Generic.Dictionary NeighboursMap(T vertex); +} \ No newline at end of file diff --git a/DataStructures/Graphs/UndirectedDenseGraph.cs b/DataStructures/Graphs/UndirectedDenseGraph.cs index 1fa19778..1c77cfce 100644 --- a/DataStructures/Graphs/UndirectedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedDenseGraph.cs @@ -13,488 +13,485 @@ using DataStructures.Common; using DataStructures.Lists; -namespace DataStructures.Graphs +namespace DataStructures.Graphs; + +public class UndirectedDenseGraph : IGraph where T : IComparable { - public class UndirectedDenseGraph : IGraph where T : IComparable + /// + /// INSTANCE VARIABLES + /// + protected const object EMPTY_VERTEX_SLOT = (object)null; + + protected virtual int _edgesCount { get; set; } + protected virtual int _verticesCount { get; set; } + protected virtual int _verticesCapacity { get; set; } + protected virtual ArrayList _vertices { get; set; } + protected virtual T _firstInsertedNode { get; set; } + protected virtual bool[,] _adjacencyMatrix { get; set; } + + + /// + /// CONSTRUCTORS + /// + public UndirectedDenseGraph(uint capacity = 10) { - /// - /// INSTANCE VARIABLES - /// - protected const object EMPTY_VERTEX_SLOT = (object)null; - - protected virtual int _edgesCount { get; set; } - protected virtual int _verticesCount { get; set; } - protected virtual int _verticesCapacity { get; set; } - protected virtual ArrayList _vertices { get; set; } - protected virtual T _firstInsertedNode { get; set; } - protected virtual bool[,] _adjacencyMatrix { get; set; } - - - /// - /// CONSTRUCTORS - /// - public UndirectedDenseGraph(uint capacity = 10) - { - _edgesCount = 0; - _verticesCount = 0; - _verticesCapacity = (int)capacity; + _edgesCount = 0; + _verticesCount = 0; + _verticesCapacity = (int)capacity; - _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new bool[_verticesCapacity, _verticesCapacity]; - _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: false); - } + _vertices = new ArrayList(_verticesCapacity); + _adjacencyMatrix = new bool[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: false); + } - /// - /// Helper function. Checks if edge exist in graph. - /// - protected virtual bool _doesEdgeExist(int index1, int index2) - { - return _adjacencyMatrix[index1, index2] || _adjacencyMatrix[index2, index1]; - } + /// + /// Helper function. Checks if edge exist in graph. + /// + protected virtual bool _doesEdgeExist(int index1, int index2) + { + return _adjacencyMatrix[index1, index2] || _adjacencyMatrix[index2, index1]; + } - /// - /// Helper function that checks whether a vertex exist. - /// - protected virtual bool _doesVertexExist(T vertex) - { - return _vertices.Contains(vertex); - } + /// + /// Helper function that checks whether a vertex exist. + /// + protected virtual bool _doesVertexExist(T vertex) + { + return _vertices.Contains(vertex); + } - /// - /// Returns true, if graph is directed; false otherwise. - /// - public virtual bool IsDirected => false; + /// + /// Returns true, if graph is directed; false otherwise. + /// + public virtual bool IsDirected => false; - /// - /// Returns true, if graph is weighted; false otherwise. - /// - public virtual bool IsWeighted => false; + /// + /// Returns true, if graph is weighted; false otherwise. + /// + public virtual bool IsWeighted => false; - /// - /// Gets the count of vetices. - /// - public virtual int VerticesCount => _verticesCount; + /// + /// Gets the count of vetices. + /// + public virtual int VerticesCount => _verticesCount; - /// - /// Gets the count of edges. - /// - public virtual int EdgesCount => _edgesCount; + /// + /// Gets the count of edges. + /// + public virtual int EdgesCount => _edgesCount; - /// - /// Returns the list of Vertices. - /// - public virtual IEnumerable Vertices + /// + /// Returns the list of Vertices. + /// + public virtual IEnumerable Vertices + { + get { - get - { - foreach (var item in _vertices) - if (item != null) - yield return (T)item; - } + foreach (var item in _vertices) + if (item != null) + yield return (T)item; } + } - IEnumerable> IGraph.Edges => Edges; + IEnumerable> IGraph.Edges => Edges; - IEnumerable> IGraph.IncomingEdges(T vertex) - { - return IncomingEdges(vertex); - } + IEnumerable> IGraph.IncomingEdges(T vertex) + { + return IncomingEdges(vertex); + } - IEnumerable> IGraph.OutgoingEdges(T vertex) - { - return OutgoingEdges(vertex); - } + IEnumerable> IGraph.OutgoingEdges(T vertex) + { + return OutgoingEdges(vertex); + } - /// - /// An enumerable collection of edges. - /// - public virtual IEnumerable> Edges + /// + /// An enumerable collection of edges. + /// + public virtual IEnumerable> Edges + { + get { - get + var seen = new HashSet>(); + + foreach (var vertex in _vertices) { - var seen = new HashSet>(); + int source = _vertices.IndexOf(vertex); - foreach (var vertex in _vertices) + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) { - int source = _vertices.IndexOf(vertex); - - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + // Check existence of vertex + if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - // Check existence of vertex - if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) - { - var neighbor = (T)_vertices[adjacent]; + var neighbor = (T)_vertices[adjacent]; - var outgoingEdge = new KeyValuePair((T)vertex, neighbor); - var incomingEdge = new KeyValuePair(neighbor, (T)vertex); + var outgoingEdge = new KeyValuePair((T)vertex, neighbor); + var incomingEdge = new KeyValuePair(neighbor, (T)vertex); - if (seen.Contains(incomingEdge) || seen.Contains(outgoingEdge)) - continue; - seen.Add(outgoingEdge); + if (seen.Contains(incomingEdge) || seen.Contains(outgoingEdge)) + continue; + seen.Add(outgoingEdge); - yield return new UnweightedEdge(outgoingEdge.Key, outgoingEdge.Value); - } + yield return new UnweightedEdge(outgoingEdge.Key, outgoingEdge.Value); } - }//end-foreach - } + } + }//end-foreach } + } - /// - /// Get all incoming edges to a vertex - /// - public IEnumerable> IncomingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); + /// + /// Get all incoming edges to a vertex + /// + public IEnumerable> IncomingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); - int source = _vertices.IndexOf(vertex); + int source = _vertices.IndexOf(vertex); - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + { + if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) - { - yield return new UnweightedEdge( - (T)_vertices[adjacent], // from - vertex // to - ); - } - }//end-for - } + yield return new UnweightedEdge( + (T)_vertices[adjacent], // from + vertex // to + ); + } + }//end-for + } - /// - /// Get all outgoing edges from a vertex. - /// - public IEnumerable> OutgoingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); + /// + /// Get all outgoing edges from a vertex. + /// + public IEnumerable> OutgoingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); - int source = _vertices.IndexOf(vertex); + int source = _vertices.IndexOf(vertex); - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + { + if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) - { - yield return new UnweightedEdge( - vertex, // from - (T)_vertices[adjacent] // to - ); - } - }//end-for - } + yield return new UnweightedEdge( + vertex, // from + (T)_vertices[adjacent] // to + ); + } + }//end-for + } - /// - /// Connects two vertices together. - /// - public virtual bool AddEdge(T firstVertex, T secondVertex) - { - int indexOfFirst = _vertices.IndexOf(firstVertex); - int indexOfSecond = _vertices.IndexOf(secondVertex); + /// + /// Connects two vertices together. + /// + public virtual bool AddEdge(T firstVertex, T secondVertex) + { + int indexOfFirst = _vertices.IndexOf(firstVertex); + int indexOfSecond = _vertices.IndexOf(secondVertex); - if (indexOfFirst == -1 || indexOfSecond == -1) - return false; - if (_doesEdgeExist(indexOfFirst, indexOfSecond)) - return false; + if (indexOfFirst == -1 || indexOfSecond == -1) + return false; + if (_doesEdgeExist(indexOfFirst, indexOfSecond)) + return false; - _adjacencyMatrix[indexOfFirst, indexOfSecond] = true; - _adjacencyMatrix[indexOfSecond, indexOfFirst] = true; + _adjacencyMatrix[indexOfFirst, indexOfSecond] = true; + _adjacencyMatrix[indexOfSecond, indexOfFirst] = true; - // Increment the edges count. - ++_edgesCount; + // Increment the edges count. + ++_edgesCount; - return true; - } + return true; + } - /// - /// Deletes an edge, if exists, between two vertices. - /// - public virtual bool RemoveEdge(T firstVertex, T secondVertex) - { - int indexOfFirst = _vertices.IndexOf(firstVertex); - int indexOfSecond = _vertices.IndexOf(secondVertex); + /// + /// Deletes an edge, if exists, between two vertices. + /// + public virtual bool RemoveEdge(T firstVertex, T secondVertex) + { + int indexOfFirst = _vertices.IndexOf(firstVertex); + int indexOfSecond = _vertices.IndexOf(secondVertex); - if (indexOfFirst == -1 || indexOfSecond == -1) - return false; - if (!_doesEdgeExist(indexOfFirst, indexOfSecond)) - return false; + if (indexOfFirst == -1 || indexOfSecond == -1) + return false; + if (!_doesEdgeExist(indexOfFirst, indexOfSecond)) + return false; - _adjacencyMatrix[indexOfFirst, indexOfSecond] = false; - _adjacencyMatrix[indexOfSecond, indexOfFirst] = false; + _adjacencyMatrix[indexOfFirst, indexOfSecond] = false; + _adjacencyMatrix[indexOfSecond, indexOfFirst] = false; - // Decrement the edges count. - --_edgesCount; + // Decrement the edges count. + --_edgesCount; - return true; - } + return true; + } - /// - /// Adds a list of vertices to the graph. - /// - public virtual void AddVertices(IList collection) - { - if (collection == null) - throw new ArgumentNullException(); + /// + /// Adds a list of vertices to the graph. + /// + public virtual void AddVertices(IList collection) + { + if (collection == null) + throw new ArgumentNullException(); - foreach (var item in collection) - AddVertex(item); - } + foreach (var item in collection) + AddVertex(item); + } - /// - /// Adds a new vertex to graph. - /// - public virtual bool AddVertex(T vertex) - { - // Return if graph reached it's maximum capacity - if (_verticesCount >= _verticesCapacity) - return false; + /// + /// Adds a new vertex to graph. + /// + public virtual bool AddVertex(T vertex) + { + // Return if graph reached it's maximum capacity + if (_verticesCount >= _verticesCapacity) + return false; - // Return if vertex exists - if (_doesVertexExist(vertex)) - return false; + // Return if vertex exists + if (_doesVertexExist(vertex)) + return false; - // Initialize first inserted node - if (_verticesCount == 0) - _firstInsertedNode = vertex; + // Initialize first inserted node + if (_verticesCount == 0) + _firstInsertedNode = vertex; - // Try inserting vertex at previously lazy-deleted slot - int indexOfDeleted = _vertices.IndexOf(EMPTY_VERTEX_SLOT); + // Try inserting vertex at previously lazy-deleted slot + int indexOfDeleted = _vertices.IndexOf(EMPTY_VERTEX_SLOT); - if (indexOfDeleted != -1) - _vertices[indexOfDeleted] = vertex; - else - _vertices.Add(vertex); + if (indexOfDeleted != -1) + _vertices[indexOfDeleted] = vertex; + else + _vertices.Add(vertex); - // Increment the vertices count - ++_verticesCount; + // Increment the vertices count + ++_verticesCount; - return true; - } + return true; + } - /// - /// Removes the specified vertex from graph. - /// - public virtual bool RemoveVertex(T vertex) - { - // Return if graph is empty - if (_verticesCount == 0) - return false; + /// + /// Removes the specified vertex from graph. + /// + public virtual bool RemoveVertex(T vertex) + { + // Return if graph is empty + if (_verticesCount == 0) + return false; - // Get index of vertex - int index = _vertices.IndexOf(vertex); + // Get index of vertex + int index = _vertices.IndexOf(vertex); - // Return if vertex doesn't exists - if (index == -1) - return false; + // Return if vertex doesn't exists + if (index == -1) + return false; - // Lazy-delete the vertex from graph - //_vertices.Remove (vertex); - _vertices[index] = EMPTY_VERTEX_SLOT; + // Lazy-delete the vertex from graph + //_vertices.Remove (vertex); + _vertices[index] = EMPTY_VERTEX_SLOT; - // Decrement the vertices count - --_verticesCount; + // Decrement the vertices count + --_verticesCount; - // Delete the edges - for (int i = 0; i < _verticesCapacity; ++i) + // Delete the edges + for (int i = 0; i < _verticesCapacity; ++i) + { + if (_doesEdgeExist(index, i)) { - if (_doesEdgeExist(index, i)) - { - _adjacencyMatrix[index, i] = false; - _adjacencyMatrix[i, index] = false; + _adjacencyMatrix[index, i] = false; + _adjacencyMatrix[i, index] = false; - // Decrement the edges count - --_edgesCount; - } + // Decrement the edges count + --_edgesCount; } - - return true; } - /// - /// Checks whether two vertices are connected (there is an edge between firstVertex & secondVertex) - /// - public virtual bool HasEdge(T firstVertex, T secondVertex) - { - int indexOfFirst = _vertices.IndexOf(firstVertex); - int indexOfSecond = _vertices.IndexOf(secondVertex); + return true; + } - // Check the existence of vertices and the directed edge - return indexOfFirst != -1 && indexOfSecond != -1 && _doesEdgeExist(indexOfFirst, indexOfSecond) == true; - } + /// + /// Checks whether two vertices are connected (there is an edge between firstVertex & secondVertex) + /// + public virtual bool HasEdge(T firstVertex, T secondVertex) + { + int indexOfFirst = _vertices.IndexOf(firstVertex); + int indexOfSecond = _vertices.IndexOf(secondVertex); - /// - /// Determines whether this graph has the specified vertex. - /// - public virtual bool HasVertex(T vertex) - { - return _vertices.Contains(vertex); - } + // Check the existence of vertices and the directed edge + return indexOfFirst != -1 && indexOfSecond != -1 && _doesEdgeExist(indexOfFirst, indexOfSecond) == true; + } - /// - /// Returns the neighbours doubly-linked list for the specified vertex. - /// - public virtual DLinkedList Neighbours(T vertex) - { - var neighbours = new DLinkedList(); - int source = _vertices.IndexOf(vertex); + /// + /// Determines whether this graph has the specified vertex. + /// + public virtual bool HasVertex(T vertex) + { + return _vertices.Contains(vertex); + } - if (source != -1) - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) - if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) - neighbours.Append((T)_vertices[adjacent]); + /// + /// Returns the neighbours doubly-linked list for the specified vertex. + /// + public virtual DLinkedList Neighbours(T vertex) + { + var neighbours = new DLinkedList(); + int source = _vertices.IndexOf(vertex); - return neighbours; - } + if (source != -1) + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) + neighbours.Append((T)_vertices[adjacent]); - /// - /// Returns the degree of the specified vertex. - /// - public virtual int Degree(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException(); + return neighbours; + } - return Neighbours(vertex).Count; - } + /// + /// Returns the degree of the specified vertex. + /// + public virtual int Degree(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException(); - /// - /// Returns a human-readable string of the graph. - /// - public virtual string ToReadable() - { - string output = string.Empty; + return Neighbours(vertex).Count; + } - for (int i = 0; i < _vertices.Count; ++i) - { - if (_vertices[i] == null) - continue; + /// + /// Returns a human-readable string of the graph. + /// + public virtual string ToReadable() + { + string output = string.Empty; - var node = (T)_vertices[i]; - var adjacents = string.Empty; + for (int i = 0; i < _vertices.Count; ++i) + { + if (_vertices[i] == null) + continue; - output = String.Format("{0}\r\n{1}: [", output, node); + var node = (T)_vertices[i]; + var adjacents = string.Empty; - foreach (var adjacentNode in Neighbours(node)) - adjacents = String.Format("{0}{1},", adjacents, adjacentNode); + output = String.Format("{0}\r\n{1}: [", output, node); - if (adjacents.Length > 0) - adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); + foreach (var adjacentNode in Neighbours(node)) + adjacents = String.Format("{0}{1},", adjacents, adjacentNode); - output = String.Format("{0}{1}]", output, adjacents); - } + if (adjacents.Length > 0) + adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); - return output; + output = String.Format("{0}{1}]", output, adjacents); } - /// - /// A depth first search traversal of the graph starting from the first inserted node. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable DepthFirstWalk() - { - return DepthFirstWalk(_firstInsertedNode); - } + return output; + } - /// - /// A depth first search traversal of the graph, starting from a specified vertex. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable DepthFirstWalk(T source) - { - if (_verticesCount == 0) - return new ArrayList(); - if (!HasVertex(source)) - throw new Exception("The specified starting vertex doesn't exist."); + /// + /// A depth first search traversal of the graph starting from the first inserted node. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable DepthFirstWalk() + { + return DepthFirstWalk(_firstInsertedNode); + } - var stack = new Lists.Stack(_verticesCount); - var visited = new HashSet(); - var listOfNodes = new ArrayList(_verticesCount); + /// + /// A depth first search traversal of the graph, starting from a specified vertex. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable DepthFirstWalk(T source) + { + if (_verticesCount == 0) + return new ArrayList(); + if (!HasVertex(source)) + throw new Exception("The specified starting vertex doesn't exist."); - stack.Push(source); + var stack = new Lists.Stack(_verticesCount); + var visited = new HashSet(); + var listOfNodes = new ArrayList(_verticesCount); - while (!stack.IsEmpty) - { - var current = stack.Pop(); + stack.Push(source); - if (!visited.Contains(current)) - { - listOfNodes.Add(current); - visited.Add(current); + while (!stack.IsEmpty) + { + var current = stack.Pop(); - foreach (var adjacent in Neighbours(current)) - if (!visited.Contains(adjacent)) - stack.Push(adjacent); - } - } + if (!visited.Contains(current)) + { + listOfNodes.Add(current); + visited.Add(current); - return listOfNodes; + foreach (var adjacent in Neighbours(current)) + if (!visited.Contains(adjacent)) + stack.Push(adjacent); + } } - /// - /// A breadth first search traversal of the graphstarting from the first inserted node. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable BreadthFirstWalk() - { - return BreadthFirstWalk(_firstInsertedNode); - } + return listOfNodes; + } - /// - /// A breadth first search traversal of the graph, starting from a specified vertex. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable BreadthFirstWalk(T source) - { - if (_verticesCount == 0) - return new ArrayList(); - if (!HasVertex(source)) - throw new Exception("The specified starting vertex doesn't exist."); + /// + /// A breadth first search traversal of the graphstarting from the first inserted node. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable BreadthFirstWalk() + { + return BreadthFirstWalk(_firstInsertedNode); + } - var visited = new HashSet(); - var queue = new Lists.Queue(VerticesCount); - var listOfNodes = new ArrayList(VerticesCount); + /// + /// A breadth first search traversal of the graph, starting from a specified vertex. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable BreadthFirstWalk(T source) + { + if (_verticesCount == 0) + return new ArrayList(); + if (!HasVertex(source)) + throw new Exception("The specified starting vertex doesn't exist."); - listOfNodes.Add(source); - visited.Add(source); + var visited = new HashSet(); + var queue = new Lists.Queue(VerticesCount); + var listOfNodes = new ArrayList(VerticesCount); - queue.Enqueue(source); + listOfNodes.Add(source); + visited.Add(source); - while (!queue.IsEmpty) - { - var current = queue.Dequeue(); - var neighbors = Neighbours(current); + queue.Enqueue(source); - foreach (var adjacent in neighbors) + while (!queue.IsEmpty) + { + var current = queue.Dequeue(); + var neighbors = Neighbours(current); + + foreach (var adjacent in neighbors) + { + if (!visited.Contains(adjacent)) { - if (!visited.Contains(adjacent)) - { - listOfNodes.Add(adjacent); - visited.Add(adjacent); - queue.Enqueue(adjacent); - } + listOfNodes.Add(adjacent); + visited.Add(adjacent); + queue.Enqueue(adjacent); } } - - return listOfNodes; - } - - /// - /// Clear this graph. - /// - public virtual void Clear() - { - _edgesCount = 0; - _verticesCount = 0; - _vertices.Clear(); - _adjacencyMatrix = new bool[_verticesCapacity, _verticesCapacity]; - _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: false); } + return listOfNodes; } -} + /// + /// Clear this graph. + /// + public virtual void Clear() + { + _edgesCount = 0; + _verticesCount = 0; + _vertices.Clear(); + _adjacencyMatrix = new bool[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: false); + } +} \ No newline at end of file diff --git a/DataStructures/Graphs/UndirectedSparseGraph.cs b/DataStructures/Graphs/UndirectedSparseGraph.cs index 8ae3a999..6e5e3782 100644 --- a/DataStructures/Graphs/UndirectedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedSparseGraph.cs @@ -12,401 +12,398 @@ using DataStructures.Lists; -namespace DataStructures.Graphs +namespace DataStructures.Graphs; + +public class UndirectedSparseGraph : IGraph where T : IComparable { - public class UndirectedSparseGraph : IGraph where T : IComparable - { - /// - /// INSTANCE VARIABLES - /// - protected virtual int _edgesCount { get; set; } - protected virtual T _firstInsertedNode { get; set; } - protected virtual Dictionary> _adjacencyList { get; set; } + /// + /// INSTANCE VARIABLES + /// + protected virtual int _edgesCount { get; set; } + protected virtual T _firstInsertedNode { get; set; } + protected virtual Dictionary> _adjacencyList { get; set; } - /// - /// CONSTRUCTORS - /// - public UndirectedSparseGraph() : this(10) { } + /// + /// CONSTRUCTORS + /// + public UndirectedSparseGraph() : this(10) { } - public UndirectedSparseGraph(uint initialCapacity) - { - _edgesCount = 0; - _adjacencyList = new Dictionary>((int)initialCapacity); - } + public UndirectedSparseGraph(uint initialCapacity) + { + _edgesCount = 0; + _adjacencyList = new Dictionary>((int)initialCapacity); + } - /// - /// Helper function. Checks if edge exist in graph. - /// - protected virtual bool _doesEdgeExist(T vertex1, T vertex2) - { - return _adjacencyList[vertex1].Contains(vertex2) || _adjacencyList[vertex2].Contains(vertex1); - } + /// + /// Helper function. Checks if edge exist in graph. + /// + protected virtual bool _doesEdgeExist(T vertex1, T vertex2) + { + return _adjacencyList[vertex1].Contains(vertex2) || _adjacencyList[vertex2].Contains(vertex1); + } - /// - /// Returns true, if graph is directed; false otherwise. - /// - public virtual bool IsDirected => false; + /// + /// Returns true, if graph is directed; false otherwise. + /// + public virtual bool IsDirected => false; - /// - /// Returns true, if graph is weighted; false otherwise. - /// - public virtual bool IsWeighted => false; + /// + /// Returns true, if graph is weighted; false otherwise. + /// + public virtual bool IsWeighted => false; - /// - /// Gets the count of vetices. - /// - public virtual int VerticesCount => _adjacencyList.Count; + /// + /// Gets the count of vetices. + /// + public virtual int VerticesCount => _adjacencyList.Count; - /// - /// Gets the count of edges. - /// - public virtual int EdgesCount => _edgesCount; + /// + /// Gets the count of edges. + /// + public virtual int EdgesCount => _edgesCount; - /// - /// Returns the list of Vertices. - /// - public virtual IEnumerable Vertices + /// + /// Returns the list of Vertices. + /// + public virtual IEnumerable Vertices + { + get { - get - { - var list = new ArrayList(); - foreach (var vertex in _adjacencyList.Keys) - list.Add(vertex); + var list = new ArrayList(); + foreach (var vertex in _adjacencyList.Keys) + list.Add(vertex); - return list; - } + return list; } + } - IEnumerable> IGraph.Edges => Edges; + IEnumerable> IGraph.Edges => Edges; - IEnumerable> IGraph.IncomingEdges(T vertex) - { - return IncomingEdges(vertex); - } + IEnumerable> IGraph.IncomingEdges(T vertex) + { + return IncomingEdges(vertex); + } - IEnumerable> IGraph.OutgoingEdges(T vertex) - { - return OutgoingEdges(vertex); - } + IEnumerable> IGraph.OutgoingEdges(T vertex) + { + return OutgoingEdges(vertex); + } - /// - /// An enumerable collection of all unweighted edges in Graph. - /// - public virtual IEnumerable> Edges + /// + /// An enumerable collection of all unweighted edges in Graph. + /// + public virtual IEnumerable> Edges + { + get { - get - { - var seen = new HashSet>(); + var seen = new HashSet>(); - foreach (var vertex in _adjacencyList) + foreach (var vertex in _adjacencyList) + { + foreach (var adjacent in vertex.Value) { - foreach (var adjacent in vertex.Value) - { - var incomingEdge = new KeyValuePair(adjacent, vertex.Key); - var outgoingEdge = new KeyValuePair(vertex.Key, adjacent); - - if (seen.Contains(incomingEdge) || seen.Contains(outgoingEdge)) - continue; - seen.Add(outgoingEdge); - - yield return new UnweightedEdge(outgoingEdge.Key, outgoingEdge.Value); - } - }//end-foreach - } - } + var incomingEdge = new KeyValuePair(adjacent, vertex.Key); + var outgoingEdge = new KeyValuePair(vertex.Key, adjacent); - /// - /// Get all incoming unweighted edges to a vertex - /// - public virtual IEnumerable> IncomingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); + if (seen.Contains(incomingEdge) || seen.Contains(outgoingEdge)) + continue; + seen.Add(outgoingEdge); - foreach(var adjacent in _adjacencyList[vertex]) - yield return new UnweightedEdge(adjacent, vertex); + yield return new UnweightedEdge(outgoingEdge.Key, outgoingEdge.Value); + } + }//end-foreach } + } - /// - /// Get all outgoing unweighted edges from a vertex. - /// - public virtual IEnumerable> OutgoingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); + /// + /// Get all incoming unweighted edges to a vertex + /// + public virtual IEnumerable> IncomingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); - foreach(var adjacent in _adjacencyList[vertex]) - yield return new UnweightedEdge(vertex, adjacent); - } + foreach(var adjacent in _adjacencyList[vertex]) + yield return new UnweightedEdge(adjacent, vertex); + } + /// + /// Get all outgoing unweighted edges from a vertex. + /// + public virtual IEnumerable> OutgoingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); - /// - /// Connects two vertices together. - /// - public virtual bool AddEdge(T firstVertex, T secondVertex) - { - if (!_adjacencyList.ContainsKey(firstVertex) || !_adjacencyList.ContainsKey(secondVertex)) - return false; - if (_doesEdgeExist(firstVertex, secondVertex)) - return false; + foreach(var adjacent in _adjacencyList[vertex]) + yield return new UnweightedEdge(vertex, adjacent); + } - _adjacencyList[firstVertex].Append(secondVertex); - _adjacencyList[secondVertex].Append(firstVertex); - // Increment the edges count - ++_edgesCount; + /// + /// Connects two vertices together. + /// + public virtual bool AddEdge(T firstVertex, T secondVertex) + { + if (!_adjacencyList.ContainsKey(firstVertex) || !_adjacencyList.ContainsKey(secondVertex)) + return false; + if (_doesEdgeExist(firstVertex, secondVertex)) + return false; - return true; - } + _adjacencyList[firstVertex].Append(secondVertex); + _adjacencyList[secondVertex].Append(firstVertex); - /// - /// Deletes an edge, if exists, between two vertices. - /// - public virtual bool RemoveEdge(T firstVertex, T secondVertex) - { - if (!_adjacencyList.ContainsKey(firstVertex) || !_adjacencyList.ContainsKey(secondVertex)) - return false; - if (!_doesEdgeExist(firstVertex, secondVertex)) - return false; + // Increment the edges count + ++_edgesCount; - _adjacencyList[firstVertex].Remove(secondVertex); - _adjacencyList[secondVertex].Remove(firstVertex); + return true; + } - // Decrement the edges count - --_edgesCount; + /// + /// Deletes an edge, if exists, between two vertices. + /// + public virtual bool RemoveEdge(T firstVertex, T secondVertex) + { + if (!_adjacencyList.ContainsKey(firstVertex) || !_adjacencyList.ContainsKey(secondVertex)) + return false; + if (!_doesEdgeExist(firstVertex, secondVertex)) + return false; - return true; - } + _adjacencyList[firstVertex].Remove(secondVertex); + _adjacencyList[secondVertex].Remove(firstVertex); - /// - /// Adds a list of vertices to the graph. - /// - public virtual void AddVertices(IList collection) - { - if (collection == null) - throw new ArgumentNullException(); + // Decrement the edges count + --_edgesCount; - foreach (var item in collection) - AddVertex(item); - } + return true; + } - /// - /// Adds a new vertex to graph. - /// - public virtual bool AddVertex(T vertex) - { - // Check existence of vertex - if (_adjacencyList.ContainsKey(vertex)) - return false; + /// + /// Adds a list of vertices to the graph. + /// + public virtual void AddVertices(IList collection) + { + if (collection == null) + throw new ArgumentNullException(); - if (_adjacencyList.Count == 0) - _firstInsertedNode = vertex; + foreach (var item in collection) + AddVertex(item); + } - _adjacencyList.Add(vertex, new DLinkedList()); + /// + /// Adds a new vertex to graph. + /// + public virtual bool AddVertex(T vertex) + { + // Check existence of vertex + if (_adjacencyList.ContainsKey(vertex)) + return false; - return true; - } + if (_adjacencyList.Count == 0) + _firstInsertedNode = vertex; - /// - /// Removes the specified vertex from graph. - /// - public virtual bool RemoveVertex(T vertex) - { - // Check existence of vertex - if (!_adjacencyList.ContainsKey(vertex)) - return false; + _adjacencyList.Add(vertex, new DLinkedList()); + + return true; + } - _adjacencyList.Remove(vertex); + /// + /// Removes the specified vertex from graph. + /// + public virtual bool RemoveVertex(T vertex) + { + // Check existence of vertex + if (!_adjacencyList.ContainsKey(vertex)) + return false; - foreach (var adjacent in _adjacencyList) + _adjacencyList.Remove(vertex); + + foreach (var adjacent in _adjacencyList) + { + if (adjacent.Value.Contains(vertex)) { - if (adjacent.Value.Contains(vertex)) - { - adjacent.Value.Remove(vertex); + adjacent.Value.Remove(vertex); - // Decrement the edges count. - --_edgesCount; - } + // Decrement the edges count. + --_edgesCount; } - - return true; } - /// - /// Checks whether two vertices are connected (there is an edge between firstVertex & secondVertex) - /// - public virtual bool HasEdge(T firstVertex, T secondVertex) - { - // Check existence of vertices - if (!_adjacencyList.ContainsKey(firstVertex) || !_adjacencyList.ContainsKey(secondVertex)) - return false; + return true; + } - return _adjacencyList[firstVertex].Contains(secondVertex) || _adjacencyList[secondVertex].Contains(firstVertex); - } + /// + /// Checks whether two vertices are connected (there is an edge between firstVertex & secondVertex) + /// + public virtual bool HasEdge(T firstVertex, T secondVertex) + { + // Check existence of vertices + if (!_adjacencyList.ContainsKey(firstVertex) || !_adjacencyList.ContainsKey(secondVertex)) + return false; - /// - /// Determines whether this graph has the specified vertex. - /// - public virtual bool HasVertex(T vertex) - { - return _adjacencyList.ContainsKey(vertex); - } + return _adjacencyList[firstVertex].Contains(secondVertex) || _adjacencyList[secondVertex].Contains(firstVertex); + } - /// - /// Returns the neighbours doubly-linked list for the specified vertex. - /// - public virtual DLinkedList Neighbours(T vertex) - { - if (!HasVertex(vertex)) - return null; + /// + /// Determines whether this graph has the specified vertex. + /// + public virtual bool HasVertex(T vertex) + { + return _adjacencyList.ContainsKey(vertex); + } - return _adjacencyList[vertex]; - } + /// + /// Returns the neighbours doubly-linked list for the specified vertex. + /// + public virtual DLinkedList Neighbours(T vertex) + { + if (!HasVertex(vertex)) + return null; - /// - /// Returns the degree of the specified vertex. - /// - public virtual int Degree(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException(); + return _adjacencyList[vertex]; + } - return _adjacencyList[vertex].Count; - } + /// + /// Returns the degree of the specified vertex. + /// + public virtual int Degree(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException(); - /// - /// Returns a human-readable string of the graph. - /// - public virtual string ToReadable() - { - string output = string.Empty; + return _adjacencyList[vertex].Count; + } - foreach (var node in _adjacencyList) - { - var adjacents = string.Empty; + /// + /// Returns a human-readable string of the graph. + /// + public virtual string ToReadable() + { + string output = string.Empty; - output = String.Format("{0}\r\n{1}: [", output, node.Key); + foreach (var node in _adjacencyList) + { + var adjacents = string.Empty; - foreach (var adjacentNode in node.Value) - adjacents = String.Format("{0}{1},", adjacents, adjacentNode); + output = String.Format("{0}\r\n{1}: [", output, node.Key); - if (adjacents.Length > 0) - adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); + foreach (var adjacentNode in node.Value) + adjacents = String.Format("{0}{1},", adjacents, adjacentNode); - output = String.Format("{0}{1}]", output, adjacents); - } + if (adjacents.Length > 0) + adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); - return output; + output = String.Format("{0}{1}]", output, adjacents); } - /// - /// A depth first search traversal of the graph starting from the first inserted node. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable DepthFirstWalk() - { - return DepthFirstWalk(_firstInsertedNode); - } + return output; + } - /// - /// A depth first search traversal of the graph, starting from a specified vertex. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable DepthFirstWalk(T source) - { - if (VerticesCount == 0) - return new ArrayList(); - if (!HasVertex(source)) - throw new Exception("The specified starting vertex doesn't exist."); + /// + /// A depth first search traversal of the graph starting from the first inserted node. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable DepthFirstWalk() + { + return DepthFirstWalk(_firstInsertedNode); + } - var visited = new HashSet(); - var stack = new Lists.Stack(VerticesCount); - var listOfNodes = new ArrayList(VerticesCount); + /// + /// A depth first search traversal of the graph, starting from a specified vertex. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable DepthFirstWalk(T source) + { + if (VerticesCount == 0) + return new ArrayList(); + if (!HasVertex(source)) + throw new Exception("The specified starting vertex doesn't exist."); - stack.Push(source); + var visited = new HashSet(); + var stack = new Lists.Stack(VerticesCount); + var listOfNodes = new ArrayList(VerticesCount); - while (!stack.IsEmpty) - { - var current = stack.Pop(); + stack.Push(source); - if (!visited.Contains(current)) - { - listOfNodes.Add(current); - visited.Add(current); + while (!stack.IsEmpty) + { + var current = stack.Pop(); - foreach (var adjacent in Neighbours(current)) - if (!visited.Contains(adjacent)) - stack.Push(adjacent); - } - } + if (!visited.Contains(current)) + { + listOfNodes.Add(current); + visited.Add(current); - return listOfNodes; + foreach (var adjacent in Neighbours(current)) + if (!visited.Contains(adjacent)) + stack.Push(adjacent); + } } - /// - /// A breadth first search traversal of the graphstarting from the first inserted node. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable BreadthFirstWalk() - { - return BreadthFirstWalk(_firstInsertedNode); - } + return listOfNodes; + } - /// - /// A breadth first search traversal of the graph, starting from a specified vertex. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable BreadthFirstWalk(T source) - { - if (VerticesCount == 0) - return new ArrayList(); - if (!HasVertex(source)) - throw new Exception("The specified starting vertex doesn't exist."); + /// + /// A breadth first search traversal of the graphstarting from the first inserted node. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable BreadthFirstWalk() + { + return BreadthFirstWalk(_firstInsertedNode); + } + /// + /// A breadth first search traversal of the graph, starting from a specified vertex. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable BreadthFirstWalk(T source) + { + if (VerticesCount == 0) + return new ArrayList(); + if (!HasVertex(source)) + throw new Exception("The specified starting vertex doesn't exist."); - var visited = new HashSet(); - var queue = new Lists.Queue(VerticesCount); - var listOfNodes = new ArrayList(VerticesCount); - listOfNodes.Add(source); - visited.Add(source); + var visited = new HashSet(); + var queue = new Lists.Queue(VerticesCount); + var listOfNodes = new ArrayList(VerticesCount); - queue.Enqueue(source); + listOfNodes.Add(source); + visited.Add(source); - while (!queue.IsEmpty) - { - var current = queue.Dequeue(); - var neighbors = Neighbours(current); + queue.Enqueue(source); - foreach (var adjacent in neighbors) + while (!queue.IsEmpty) + { + var current = queue.Dequeue(); + var neighbors = Neighbours(current); + + foreach (var adjacent in neighbors) + { + if (!visited.Contains(adjacent)) { - if (!visited.Contains(adjacent)) - { - listOfNodes.Add(adjacent); - visited.Add(adjacent); - queue.Enqueue(adjacent); - } + listOfNodes.Add(adjacent); + visited.Add(adjacent); + queue.Enqueue(adjacent); } } - - return listOfNodes; - } - - /// - /// Clear this graph. - /// - public virtual void Clear() - { - _edgesCount = 0; - _adjacencyList.Clear(); } + return listOfNodes; } -} + /// + /// Clear this graph. + /// + public virtual void Clear() + { + _edgesCount = 0; + _adjacencyList.Clear(); + } +} \ No newline at end of file diff --git a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs index 61de87af..73fb81c6 100644 --- a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs @@ -15,330 +15,329 @@ using DataStructures.Common; using DataStructures.Lists; -namespace DataStructures.Graphs +namespace DataStructures.Graphs; + +/// +/// This class represents the graph as an adjacency-matrix (two dimensional integer array). +/// +public class UndirectedWeightedDenseGraph : UndirectedDenseGraph, IWeightedGraph where T : IComparable { /// - /// This class represents the graph as an adjacency-matrix (two dimensional integer array). + /// INSTANCE VARIABLES + /// + private const long EMPTY_EDGE_SLOT = 0; + + // Store edges and their weights as integers. + // Any edge with a value of zero means it doesn't exist. Otherwise, it exist with a specific weight value. + // Default value for positive edges is 1. + protected new long[,] _adjacencyMatrix { get; set; } + + /// + /// CONSTRUCTOR /// - public class UndirectedWeightedDenseGraph : UndirectedDenseGraph, IWeightedGraph where T : IComparable + public UndirectedWeightedDenseGraph(uint capacity = 10) { - /// - /// INSTANCE VARIABLES - /// - private const long EMPTY_EDGE_SLOT = 0; - - // Store edges and their weights as integers. - // Any edge with a value of zero means it doesn't exist. Otherwise, it exist with a specific weight value. - // Default value for positive edges is 1. - protected new long[,] _adjacencyMatrix { get; set; } - - /// - /// CONSTRUCTOR - /// - public UndirectedWeightedDenseGraph(uint capacity = 10) - { - _edgesCount = 0; - _verticesCount = 0; - _verticesCapacity = (int)capacity; + _edgesCount = 0; + _verticesCount = 0; + _verticesCapacity = (int)capacity; - _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; - _adjacencyMatrix.Populate(_verticesCapacity, _verticesCapacity, EMPTY_EDGE_SLOT); - } + _vertices = new ArrayList(_verticesCapacity); + _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix.Populate(_verticesCapacity, _verticesCapacity, EMPTY_EDGE_SLOT); + } - /// - /// Helper function. Checks if edge exist in graph. - /// - protected override bool _doesEdgeExist(int source, int destination) - { - return _adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT || _adjacencyMatrix[destination, source] != EMPTY_EDGE_SLOT; - } + /// + /// Helper function. Checks if edge exist in graph. + /// + protected override bool _doesEdgeExist(int source, int destination) + { + return _adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT || _adjacencyMatrix[destination, source] != EMPTY_EDGE_SLOT; + } - /// - /// Helper function. Gets the weight of a undirected edge. - /// - private long _getEdgeWeight(int source, int destination) - { - return _adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT ? _adjacencyMatrix[source, destination] : _adjacencyMatrix[destination, source]; - } + /// + /// Helper function. Gets the weight of a undirected edge. + /// + private long _getEdgeWeight(int source, int destination) + { + return _adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT ? _adjacencyMatrix[source, destination] : _adjacencyMatrix[destination, source]; + } - /// - /// Returns true, if graph is weighted; false otherwise. - /// - public override bool IsWeighted => true; + /// + /// Returns true, if graph is weighted; false otherwise. + /// + public override bool IsWeighted => true; - /// - /// An enumerable collection of edges. - /// - public virtual IEnumerable> Edges + /// + /// An enumerable collection of edges. + /// + public virtual IEnumerable> Edges + { + get { - get + var seen = new HashSet>(); + + foreach (var vertex in _vertices) { - var seen = new HashSet>(); + int source = _vertices.IndexOf(vertex); - foreach (var vertex in _vertices) + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) { - int source = _vertices.IndexOf(vertex); - - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + // Check existence of vertex + if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - // Check existence of vertex - if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) - { - var neighbor = (T)_vertices[adjacent]; - var weight = _getEdgeWeight(source, adjacent); - - var outgoingEdge = new KeyValuePair((T)vertex, neighbor); - var incomingEdge = new KeyValuePair(neighbor, (T)vertex); - - // Undirected edges should be checked once - if (seen.Contains(incomingEdge) || seen.Contains(outgoingEdge)) - continue; - seen.Add(outgoingEdge); - - yield return new WeightedEdge(outgoingEdge.Key, outgoingEdge.Value, weight); - } + var neighbor = (T)_vertices[adjacent]; + var weight = _getEdgeWeight(source, adjacent); + + var outgoingEdge = new KeyValuePair((T)vertex, neighbor); + var incomingEdge = new KeyValuePair(neighbor, (T)vertex); + + // Undirected edges should be checked once + if (seen.Contains(incomingEdge) || seen.Contains(outgoingEdge)) + continue; + seen.Add(outgoingEdge); + + yield return new WeightedEdge(outgoingEdge.Key, outgoingEdge.Value, weight); } - }//end-foreach - } + } + }//end-foreach } + } - /// - /// Get all incoming edges to a vertex - /// - public virtual IEnumerable> IncomingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new ArgumentOutOfRangeException("One of vertex is not part of the graph."); + /// + /// Get all incoming edges to a vertex + /// + public virtual IEnumerable> IncomingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new ArgumentOutOfRangeException("One of vertex is not part of the graph."); - int source = _vertices.IndexOf(vertex); - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + int source = _vertices.IndexOf(vertex); + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + { + if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) - { - yield return new WeightedEdge( - (T)_vertices[adjacent], // from - vertex, // to - _getEdgeWeight(source, adjacent) // weight - ); - } + yield return new WeightedEdge( + (T)_vertices[adjacent], // from + vertex, // to + _getEdgeWeight(source, adjacent) // weight + ); } } + } - /// - /// Get all outgoing weighted edges from vertex - /// - public virtual IEnumerable> OutgoingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new ArgumentOutOfRangeException("One of vertex is not part of the graph."); + /// + /// Get all outgoing weighted edges from vertex + /// + public virtual IEnumerable> OutgoingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new ArgumentOutOfRangeException("One of vertex is not part of the graph."); - int source = _vertices.IndexOf(vertex); - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + int source = _vertices.IndexOf(vertex); + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + { + if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) - { - yield return new WeightedEdge( - vertex, // from - (T)_vertices[adjacent], // to - _getEdgeWeight(source, adjacent) // weight - ); - } + yield return new WeightedEdge( + vertex, // from + (T)_vertices[adjacent], // to + _getEdgeWeight(source, adjacent) // weight + ); } } + } - /// - /// Connects two vertices together with a weight, in the direction: first->second. - /// - public virtual bool AddEdge(T source, T destination, long weight) - { - // Return if the weight is equals to the empty edge value - if (weight == EMPTY_EDGE_SLOT) - return false; + /// + /// Connects two vertices together with a weight, in the direction: first->second. + /// + public virtual bool AddEdge(T source, T destination, long weight) + { + // Return if the weight is equals to the empty edge value + if (weight == EMPTY_EDGE_SLOT) + return false; - // Get indices of vertices - int srcIndex = _vertices.IndexOf(source); - int dstIndex = _vertices.IndexOf(destination); + // Get indices of vertices + int srcIndex = _vertices.IndexOf(source); + int dstIndex = _vertices.IndexOf(destination); - // Check existence of vertices and non-existence of edge - if (srcIndex == -1 || dstIndex == -1) - return false; - if (_doesEdgeExist(srcIndex, dstIndex)) - return false; + // Check existence of vertices and non-existence of edge + if (srcIndex == -1 || dstIndex == -1) + return false; + if (_doesEdgeExist(srcIndex, dstIndex)) + return false; - // Use only one triangle of the matrix - _adjacencyMatrix[srcIndex, dstIndex] = weight; + // Use only one triangle of the matrix + _adjacencyMatrix[srcIndex, dstIndex] = weight; - // Increment edges count - ++_edgesCount; + // Increment edges count + ++_edgesCount; - return true; - } + return true; + } - /// - /// Removes edge, if exists, from source to destination. - /// - public override bool RemoveEdge(T source, T destination) - { - int srcIndex = _vertices.IndexOf(source); - int dstIndex = _vertices.IndexOf(destination); + /// + /// Removes edge, if exists, from source to destination. + /// + public override bool RemoveEdge(T source, T destination) + { + int srcIndex = _vertices.IndexOf(source); + int dstIndex = _vertices.IndexOf(destination); - if (srcIndex == -1 || dstIndex == -1) - throw new ArgumentOutOfRangeException("One of vertex is not part of the graph."); - if (!_doesEdgeExist(srcIndex, dstIndex)) - return false; + if (srcIndex == -1 || dstIndex == -1) + throw new ArgumentOutOfRangeException("One of vertex is not part of the graph."); + if (!_doesEdgeExist(srcIndex, dstIndex)) + return false; - _adjacencyMatrix[srcIndex, dstIndex] = EMPTY_EDGE_SLOT; - _adjacencyMatrix[dstIndex, srcIndex] = EMPTY_EDGE_SLOT; - --_edgesCount; + _adjacencyMatrix[srcIndex, dstIndex] = EMPTY_EDGE_SLOT; + _adjacencyMatrix[dstIndex, srcIndex] = EMPTY_EDGE_SLOT; + --_edgesCount; - return true; - } + return true; + } - /// - /// Updates the edge weight from source to destination. - /// - public virtual bool UpdateEdgeWeight(T source, T destination, long weight) - { - int srcIndex = _vertices.IndexOf(source); - int dstIndex = _vertices.IndexOf(destination); + /// + /// Updates the edge weight from source to destination. + /// + public virtual bool UpdateEdgeWeight(T source, T destination, long weight) + { + int srcIndex = _vertices.IndexOf(source); + int dstIndex = _vertices.IndexOf(destination); - if (srcIndex == -1 || dstIndex == -1) - throw new ArgumentOutOfRangeException("One of vertex is not part of the graph."); - if (!_doesEdgeExist(srcIndex, dstIndex)) - return false; + if (srcIndex == -1 || dstIndex == -1) + throw new ArgumentOutOfRangeException("One of vertex is not part of the graph."); + if (!_doesEdgeExist(srcIndex, dstIndex)) + return false; - if (_adjacencyMatrix[srcIndex, dstIndex] != EMPTY_EDGE_SLOT) - _adjacencyMatrix[srcIndex, dstIndex] = weight; - else - _adjacencyMatrix[dstIndex, srcIndex] = weight; + if (_adjacencyMatrix[srcIndex, dstIndex] != EMPTY_EDGE_SLOT) + _adjacencyMatrix[srcIndex, dstIndex] = weight; + else + _adjacencyMatrix[dstIndex, srcIndex] = weight; - return true; - } + return true; + } - /// - /// Removes the specified vertex from graph. - /// - public override bool RemoveVertex(T vertex) - { - // Return if graph is empty - if (_verticesCount == 0) - return false; + /// + /// Removes the specified vertex from graph. + /// + public override bool RemoveVertex(T vertex) + { + // Return if graph is empty + if (_verticesCount == 0) + return false; - // Get index of vertex - int index = _vertices.IndexOf(vertex); + // Get index of vertex + int index = _vertices.IndexOf(vertex); - // Return if vertex doesn't exists - if (index == -1) - return false; + // Return if vertex doesn't exists + if (index == -1) + return false; - // Lazy-delete the vertex from graph - //_vertices.Remove (vertex); - _vertices[index] = EMPTY_VERTEX_SLOT; + // Lazy-delete the vertex from graph + //_vertices.Remove (vertex); + _vertices[index] = EMPTY_VERTEX_SLOT; - // Decrement the vertices count - --_verticesCount; + // Decrement the vertices count + --_verticesCount; - // Remove all outgoing and incoming edges to this vertex - for (int i = 0; i < _verticesCapacity; ++i) + // Remove all outgoing and incoming edges to this vertex + for (int i = 0; i < _verticesCapacity; ++i) + { + if (_doesEdgeExist(i, index)) { - if (_doesEdgeExist(i, index)) - { - _adjacencyMatrix[index, i] = EMPTY_EDGE_SLOT; - _adjacencyMatrix[i, index] = EMPTY_EDGE_SLOT; + _adjacencyMatrix[index, i] = EMPTY_EDGE_SLOT; + _adjacencyMatrix[i, index] = EMPTY_EDGE_SLOT; - // Decrement the edges count - --_edgesCount; - } + // Decrement the edges count + --_edgesCount; } - - return true; } - /// - /// Get edge object from source to destination. - /// - public virtual WeightedEdge GetEdge(T source, T destination) - { - int srcIndex = _vertices.IndexOf(source); - int dstIndex = _vertices.IndexOf(destination); + return true; + } - if (srcIndex == -1 || dstIndex == -1) - throw new ArgumentOutOfRangeException("One of vertex is not part of the graph."); + /// + /// Get edge object from source to destination. + /// + public virtual WeightedEdge GetEdge(T source, T destination) + { + int srcIndex = _vertices.IndexOf(source); + int dstIndex = _vertices.IndexOf(destination); - if (!_doesEdgeExist(srcIndex, dstIndex)) - return null; + if (srcIndex == -1 || dstIndex == -1) + throw new ArgumentOutOfRangeException("One of vertex is not part of the graph."); - return new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex)); - } + if (!_doesEdgeExist(srcIndex, dstIndex)) + return null; - /// - /// Returns the edge weight from source to destination. - /// - public virtual long GetEdgeWeight(T source, T destination) - { - return GetEdge(source, destination).Weight; - } + return new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex)); + } - /// - /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. - /// - public virtual Dictionary NeighboursMap(T vertex) - { - if (!HasVertex(vertex)) - return null; + /// + /// Returns the edge weight from source to destination. + /// + public virtual long GetEdgeWeight(T source, T destination) + { + return GetEdge(source, destination).Weight; + } - var neighbors = new Dictionary(); - int source = _vertices.IndexOf(vertex); + /// + /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. + /// + public virtual Dictionary NeighboursMap(T vertex) + { + if (!HasVertex(vertex)) + return null; - // Check existence of vertex - if (source != -1) - for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) - if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) - neighbors.Add((T)_vertices[adjacent], _getEdgeWeight(source, adjacent)); + var neighbors = new Dictionary(); + int source = _vertices.IndexOf(vertex); - return neighbors; - } + // Check existence of vertex + if (source != -1) + for (int adjacent = 0; adjacent < _vertices.Count; ++adjacent) + if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) + neighbors.Add((T)_vertices[adjacent], _getEdgeWeight(source, adjacent)); - /// - /// Returns a human-readable string of the graph. - /// - public override string ToReadable() - { - string output = string.Empty; + return neighbors; + } - for (int i = 0; i < _vertices.Count; ++i) - { - if (_vertices[i] == null) - continue; + /// + /// Returns a human-readable string of the graph. + /// + public override string ToReadable() + { + string output = string.Empty; - var node = (T)_vertices[i]; - var adjacents = string.Empty; + for (int i = 0; i < _vertices.Count; ++i) + { + if (_vertices[i] == null) + continue; - output = String.Format("{0}\r\n{1}: [", output, node); + var node = (T)_vertices[i]; + var adjacents = string.Empty; - foreach (var adjacentNode in NeighboursMap(node)) - adjacents = String.Format("{0}{1}({2}), ", adjacents, adjacentNode.Key, adjacentNode.Value); + output = String.Format("{0}\r\n{1}: [", output, node); - if (adjacents.Length > 0) - adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); + foreach (var adjacentNode in NeighboursMap(node)) + adjacents = String.Format("{0}{1}({2}), ", adjacents, adjacentNode.Key, adjacentNode.Value); - output = String.Format("{0}{1}]", output, adjacents); - } + if (adjacents.Length > 0) + adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); - return output; + output = String.Format("{0}{1}]", output, adjacents); } - /// - /// Clear this graph. - /// - public override void Clear() - { - _edgesCount = 0; - _verticesCount = 0; - _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; - _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); - } + return output; + } + + /// + /// Clear this graph. + /// + public override void Clear() + { + _edgesCount = 0; + _verticesCount = 0; + _vertices = new ArrayList(_verticesCapacity); + _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); } -} +} \ No newline at end of file diff --git a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs index d728593a..0cb9fab2 100644 --- a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs @@ -15,542 +15,540 @@ using DataStructures.Common; using DataStructures.Lists; -namespace DataStructures.Graphs +namespace DataStructures.Graphs; + +public class UndirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable { - public class UndirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable - { - /// - /// INSTANCE VARIABLES - /// - private const long EMPTY_EDGE_VALUE = 0; - protected virtual int _edgesCount { get; set; } - protected virtual T _firstInsertedNode { get; set; } - protected virtual Dictionary>> _adjacencyList { get; set; } + /// + /// INSTANCE VARIABLES + /// + private const long EMPTY_EDGE_VALUE = 0; + protected virtual int _edgesCount { get; set; } + protected virtual T _firstInsertedNode { get; set; } + protected virtual Dictionary>> _adjacencyList { get; set; } - /// - /// CONSTRUCTOR - /// - public UndirectedWeightedSparseGraph() : this(10) { } + /// + /// CONSTRUCTOR + /// + public UndirectedWeightedSparseGraph() : this(10) { } - public UndirectedWeightedSparseGraph(uint initialCapacity) - { - _edgesCount = 0; - _adjacencyList = new Dictionary>>((int)initialCapacity); - } + public UndirectedWeightedSparseGraph(uint initialCapacity) + { + _edgesCount = 0; + _adjacencyList = new Dictionary>>((int)initialCapacity); + } - /// - /// Helper function. Returns edge object from source to destination, if exists; otherwise, null. - /// - protected virtual WeightedEdge _tryGetEdge(T source, T destination) - { - var success = false; - WeightedEdge edge = null; + /// + /// Helper function. Returns edge object from source to destination, if exists; otherwise, null. + /// + protected virtual WeightedEdge _tryGetEdge(T source, T destination) + { + var success = false; + WeightedEdge edge = null; - var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); - var destinationToSourcePredicate = new Predicate>((item) => item.Source.IsEqualTo(destination) && item.Destination.IsEqualTo(source)); + var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); + var destinationToSourcePredicate = new Predicate>((item) => item.Source.IsEqualTo(destination) && item.Destination.IsEqualTo(source)); - if(_adjacencyList.ContainsKey(source)) - success = _adjacencyList[source].TryFindFirst(sourceToDestinationPredicate, out edge); + if(_adjacencyList.ContainsKey(source)) + success = _adjacencyList[source].TryFindFirst(sourceToDestinationPredicate, out edge); - if(!success && _adjacencyList.ContainsKey(destination)) - _adjacencyList[destination].TryFindFirst(destinationToSourcePredicate, out edge); + if(!success && _adjacencyList.ContainsKey(destination)) + _adjacencyList[destination].TryFindFirst(destinationToSourcePredicate, out edge); - // Could return a null object. - return edge; - } + // Could return a null object. + return edge; + } - /// - /// Helper function. Checks if edge exist in graph. - /// - protected virtual bool _doesEdgeExist(T source, T destination) - { - return _tryGetEdge(source, destination) != null; - } + /// + /// Helper function. Checks if edge exist in graph. + /// + protected virtual bool _doesEdgeExist(T source, T destination) + { + return _tryGetEdge(source, destination) != null; + } - /// - /// Helper function. Gets the weight of a undirected edge. - /// Presumes edge does already exist. - /// - private long _getEdgeWeight(T source, T destination) - { - return _tryGetEdge(source, destination).Weight; - } + /// + /// Helper function. Gets the weight of a undirected edge. + /// Presumes edge does already exist. + /// + private long _getEdgeWeight(T source, T destination) + { + return _tryGetEdge(source, destination).Weight; + } - /// - /// Returns true, if graph is undirected; false otherwise. - /// - public virtual bool IsDirected => false; + /// + /// Returns true, if graph is undirected; false otherwise. + /// + public virtual bool IsDirected => false; - /// - /// Returns true, if graph is weighted; false otherwise. - /// - public virtual bool IsWeighted => true; + /// + /// Returns true, if graph is weighted; false otherwise. + /// + public virtual bool IsWeighted => true; - /// - /// Gets the count of vetices. - /// - public int EdgesCount => _edgesCount; + /// + /// Gets the count of vetices. + /// + public int EdgesCount => _edgesCount; - /// - /// Gets the count of edges. - /// - public int VerticesCount => _adjacencyList.Count; + /// + /// Gets the count of edges. + /// + public int VerticesCount => _adjacencyList.Count; - /// - /// Returns the list of Vertices. - /// - public IEnumerable Vertices + /// + /// Returns the list of Vertices. + /// + public IEnumerable Vertices + { + get { - get - { - foreach (var vertex in _adjacencyList) - yield return vertex.Key; - } + foreach (var vertex in _adjacencyList) + yield return vertex.Key; } + } - IEnumerable> IGraph.Edges => Edges; + IEnumerable> IGraph.Edges => Edges; - IEnumerable> IGraph.IncomingEdges(T vertex) - { - return IncomingEdges(vertex); - } + IEnumerable> IGraph.IncomingEdges(T vertex) + { + return IncomingEdges(vertex); + } - IEnumerable> IGraph.OutgoingEdges(T vertex) - { - return OutgoingEdges(vertex); - } + IEnumerable> IGraph.OutgoingEdges(T vertex) + { + return OutgoingEdges(vertex); + } - /// - /// An enumerable collection of all weighted edges in Graph. - /// - public virtual IEnumerable> Edges + /// + /// An enumerable collection of all weighted edges in Graph. + /// + public virtual IEnumerable> Edges + { + get { - get - { - var seen = new HashSet>(); + var seen = new HashSet>(); - foreach (var vertex in _adjacencyList) + foreach (var vertex in _adjacencyList) + { + foreach (var edge in vertex.Value) { - foreach (var edge in vertex.Value) - { - var incomingEdge = new KeyValuePair(edge.Destination, edge.Source); - var outgoingEdge = new KeyValuePair(edge.Source, edge.Destination); - - if (seen.Contains(incomingEdge) || seen.Contains(outgoingEdge)) - continue; - seen.Add(outgoingEdge); - - yield return edge; - } - }//end-foreach - } + var incomingEdge = new KeyValuePair(edge.Destination, edge.Source); + var outgoingEdge = new KeyValuePair(edge.Source, edge.Destination); + + if (seen.Contains(incomingEdge) || seen.Contains(outgoingEdge)) + continue; + seen.Add(outgoingEdge); + + yield return edge; + } + }//end-foreach } + } - /// - /// Get all incoming weighted edges to a vertex - /// - public virtual IEnumerable> IncomingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); + /// + /// Get all incoming weighted edges to a vertex + /// + public virtual IEnumerable> IncomingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); - foreach(var edge in _adjacencyList[vertex]) - yield return new WeightedEdge(edge.Destination, edge.Source, edge.Weight); - } + foreach(var edge in _adjacencyList[vertex]) + yield return new WeightedEdge(edge.Destination, edge.Source, edge.Weight); + } - /// - /// Get all outgoing weighted edges from a vertex. - /// - public virtual IEnumerable> OutgoingEdges(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException("Vertex doesn't belong to graph."); + /// + /// Get all outgoing weighted edges from a vertex. + /// + public virtual IEnumerable> OutgoingEdges(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException("Vertex doesn't belong to graph."); - foreach(var edge in _adjacencyList[vertex]) - yield return edge; - } + foreach(var edge in _adjacencyList[vertex]) + yield return edge; + } - /// - /// Obsolete. Another AddEdge function is implemented with a weight parameter. - /// - [Obsolete("Use the AddEdge method with the weight parameter.")] - public bool AddEdge(T source, T destination) - { - throw new NotImplementedException(); - } + /// + /// Obsolete. Another AddEdge function is implemented with a weight parameter. + /// + [Obsolete("Use the AddEdge method with the weight parameter.")] + public bool AddEdge(T source, T destination) + { + throw new NotImplementedException(); + } - /// - /// Connects two vertices together with a weight, in the direction: first->second. - /// - public bool AddEdge(T source, T destination, long weight) - { - // Check existence of nodes, the validity of the weight value, and the non-existence of edge - if (weight == EMPTY_EDGE_VALUE) - return false; - if (!HasVertex(source) || !HasVertex(destination)) - return false; - if (_doesEdgeExist(source, destination)) - return false; + /// + /// Connects two vertices together with a weight, in the direction: first->second. + /// + public bool AddEdge(T source, T destination, long weight) + { + // Check existence of nodes, the validity of the weight value, and the non-existence of edge + if (weight == EMPTY_EDGE_VALUE) + return false; + if (!HasVertex(source) || !HasVertex(destination)) + return false; + if (_doesEdgeExist(source, destination)) + return false; - // Add edge from source to destination - var sourceDdge = new WeightedEdge(source, destination, weight); - var destinationEdge = new WeightedEdge(destination, source, weight); + // Add edge from source to destination + var sourceDdge = new WeightedEdge(source, destination, weight); + var destinationEdge = new WeightedEdge(destination, source, weight); - _adjacencyList[source].Append(sourceDdge); - _adjacencyList[destination].Append(destinationEdge); + _adjacencyList[source].Append(sourceDdge); + _adjacencyList[destination].Append(destinationEdge); - // Increment edges count - ++_edgesCount; + // Increment edges count + ++_edgesCount; - return true; - } + return true; + } - /// - /// Removes edge, if exists, from source to destination. - /// - public virtual bool RemoveEdge(T source, T destination) - { - // Check existence of nodes and non-existence of edge - if (!HasVertex(source) || !HasVertex(destination)) - return false; + /// + /// Removes edge, if exists, from source to destination. + /// + public virtual bool RemoveEdge(T source, T destination) + { + // Check existence of nodes and non-existence of edge + if (!HasVertex(source) || !HasVertex(destination)) + return false; - WeightedEdge edge1, edge2; + WeightedEdge edge1, edge2; - var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); - _adjacencyList[source].TryFindFirst(sourceToDestinationPredicate, out edge1); + var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); + _adjacencyList[source].TryFindFirst(sourceToDestinationPredicate, out edge1); - var destinationToSourcePredicate = new Predicate>((item) => item.Source.IsEqualTo(destination) && item.Destination.IsEqualTo(source)); - _adjacencyList[destination].TryFindFirst(destinationToSourcePredicate, out edge2); + var destinationToSourcePredicate = new Predicate>((item) => item.Source.IsEqualTo(destination) && item.Destination.IsEqualTo(source)); + _adjacencyList[destination].TryFindFirst(destinationToSourcePredicate, out edge2); - // If edge doesn't exist, return false - if (edge1 == null && edge2 == null) - return false; + // If edge doesn't exist, return false + if (edge1 == null && edge2 == null) + return false; - // If edge exists in the source neighbors, remove it - if (edge1 != null) - _adjacencyList[source].Remove(edge1); + // If edge exists in the source neighbors, remove it + if (edge1 != null) + _adjacencyList[source].Remove(edge1); - // If edge exists in the destination neighbors, remove it. - if(edge2 != null) - _adjacencyList[destination].Remove(edge2); + // If edge exists in the destination neighbors, remove it. + if(edge2 != null) + _adjacencyList[destination].Remove(edge2); - // Decrement the edges count - --_edgesCount; + // Decrement the edges count + --_edgesCount; - return true; - } + return true; + } - public bool UpdateEdgeWeight(T source, T destination, long weight) - { - // Check existence of vertices and validity of the weight value - if (weight == EMPTY_EDGE_VALUE) - return false; - if (!HasVertex(source) || !HasVertex(destination)) - return false; + public bool UpdateEdgeWeight(T source, T destination, long weight) + { + // Check existence of vertices and validity of the weight value + if (weight == EMPTY_EDGE_VALUE) + return false; + if (!HasVertex(source) || !HasVertex(destination)) + return false; - // Status flag of updating an edge - var status = false; + // Status flag of updating an edge + var status = false; - // Check the source neighbors - foreach (var edge in _adjacencyList[source]) + // Check the source neighbors + foreach (var edge in _adjacencyList[source]) + { + if (edge.Destination.IsEqualTo(destination)) { - if (edge.Destination.IsEqualTo(destination)) - { - edge.Weight = weight; - status |= true; - break; - } + edge.Weight = weight; + status |= true; + break; } + } - // Check the destination neighbors - foreach (var edge in _adjacencyList[destination]) + // Check the destination neighbors + foreach (var edge in _adjacencyList[destination]) + { + if (edge.Destination.IsEqualTo(source)) { - if (edge.Destination.IsEqualTo(source)) - { - edge.Weight = weight; - status |= true; - break; - } + edge.Weight = weight; + status |= true; + break; } - - return status; } - /// - /// Get edge object from source to destination. - /// - public virtual WeightedEdge GetEdge(T source, T destination) - { - if (!HasVertex(source) || !HasVertex(destination)) - throw new KeyNotFoundException("Either one of the vertices or both of them don't exist."); + return status; + } - var edge = _tryGetEdge(source, destination); + /// + /// Get edge object from source to destination. + /// + public virtual WeightedEdge GetEdge(T source, T destination) + { + if (!HasVertex(source) || !HasVertex(destination)) + throw new KeyNotFoundException("Either one of the vertices or both of them don't exist."); - // Check the existence of edge - if (edge == null) - throw new Exception("Edge doesn't exist."); + var edge = _tryGetEdge(source, destination); - // Try get edge - return edge; - } + // Check the existence of edge + if (edge == null) + throw new Exception("Edge doesn't exist."); - /// - /// Returns the edge weight from source to destination. - /// - public virtual long GetEdgeWeight(T source, T destination) - { - return GetEdge(source, destination).Weight; - } + // Try get edge + return edge; + } - /// - /// Add a collection of vertices to the graph. - /// - public virtual void AddVertices(IList collection) - { - if (collection == null) - throw new ArgumentNullException(); + /// + /// Returns the edge weight from source to destination. + /// + public virtual long GetEdgeWeight(T source, T destination) + { + return GetEdge(source, destination).Weight; + } - foreach (var vertex in collection) - AddVertex(vertex); - } + /// + /// Add a collection of vertices to the graph. + /// + public virtual void AddVertices(IList collection) + { + if (collection == null) + throw new ArgumentNullException(); - /// - /// Add vertex to the graph - /// - public virtual bool AddVertex(T vertex) - { - if (_adjacencyList.ContainsKey(vertex)) - return false; + foreach (var vertex in collection) + AddVertex(vertex); + } - if (_adjacencyList.Count == 0) - _firstInsertedNode = vertex; + /// + /// Add vertex to the graph + /// + public virtual bool AddVertex(T vertex) + { + if (_adjacencyList.ContainsKey(vertex)) + return false; - _adjacencyList.Add(vertex, new DLinkedList>()); + if (_adjacencyList.Count == 0) + _firstInsertedNode = vertex; - return true; - } + _adjacencyList.Add(vertex, new DLinkedList>()); - /// - /// Removes the specified vertex from graph. - /// - public virtual bool RemoveVertex(T vertex) - { - // Check existence of vertex - if (!_adjacencyList.ContainsKey(vertex)) - return false; + return true; + } + + /// + /// Removes the specified vertex from graph. + /// + public virtual bool RemoveVertex(T vertex) + { + // Check existence of vertex + if (!_adjacencyList.ContainsKey(vertex)) + return false; - // Remove vertex from graph - _adjacencyList.Remove(vertex); + // Remove vertex from graph + _adjacencyList.Remove(vertex); - // Remove destination edges to this vertex - foreach (var adjacent in _adjacencyList) - { - var edge = _tryGetEdge(adjacent.Key, vertex); + // Remove destination edges to this vertex + foreach (var adjacent in _adjacencyList) + { + var edge = _tryGetEdge(adjacent.Key, vertex); - if (edge != null) - { - adjacent.Value.Remove(edge); - --_edgesCount; - } + if (edge != null) + { + adjacent.Value.Remove(edge); + --_edgesCount; } - - return true; } - /// - /// Checks whether there is an edge from source to destination. - /// - public virtual bool HasEdge(T source, T destination) - { - return _adjacencyList.ContainsKey(source) && _adjacencyList.ContainsKey(destination) && _doesEdgeExist(source, destination); - } + return true; + } - /// - /// Checks whether a vertex exists in the graph - /// - public virtual bool HasVertex(T vertex) - { - return _adjacencyList.ContainsKey(vertex); - } + /// + /// Checks whether there is an edge from source to destination. + /// + public virtual bool HasEdge(T source, T destination) + { + return _adjacencyList.ContainsKey(source) && _adjacencyList.ContainsKey(destination) && _doesEdgeExist(source, destination); + } - /// - /// Returns the neighbours doubly-linked list for the specified vertex. - /// - public virtual DLinkedList Neighbours(T vertex) - { - if (!HasVertex(vertex)) - return null; + /// + /// Checks whether a vertex exists in the graph + /// + public virtual bool HasVertex(T vertex) + { + return _adjacencyList.ContainsKey(vertex); + } - var neighbors = new DLinkedList(); - var adjacents = _adjacencyList[vertex]; + /// + /// Returns the neighbours doubly-linked list for the specified vertex. + /// + public virtual DLinkedList Neighbours(T vertex) + { + if (!HasVertex(vertex)) + return null; - foreach (var adjacent in adjacents) - neighbors.Append(adjacent.Destination); + var neighbors = new DLinkedList(); + var adjacents = _adjacencyList[vertex]; - return neighbors; - } + foreach (var adjacent in adjacents) + neighbors.Append(adjacent.Destination); - /// - /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. - /// - public Dictionary NeighboursMap(T vertex) - { - if (!HasVertex(vertex)) - return null; + return neighbors; + } - var neighbors = _adjacencyList[vertex]; - var map = new Dictionary(neighbors.Count); + /// + /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. + /// + public Dictionary NeighboursMap(T vertex) + { + if (!HasVertex(vertex)) + return null; - foreach (var adjacent in neighbors) - map.Add(adjacent.Destination, adjacent.Weight); + var neighbors = _adjacencyList[vertex]; + var map = new Dictionary(neighbors.Count); - return map; - } + foreach (var adjacent in neighbors) + map.Add(adjacent.Destination, adjacent.Weight); - /// - /// Returns the degree of the specified vertex. - /// - public virtual int Degree(T vertex) - { - if (!HasVertex(vertex)) - throw new KeyNotFoundException(); + return map; + } - return _adjacencyList[vertex].Count; - } + /// + /// Returns the degree of the specified vertex. + /// + public virtual int Degree(T vertex) + { + if (!HasVertex(vertex)) + throw new KeyNotFoundException(); - /// - /// Returns a human-readable string of the graph. - /// - public virtual string ToReadable() - { - string output = string.Empty; + return _adjacencyList[vertex].Count; + } - foreach (var node in _adjacencyList) - { - var adjacents = string.Empty; + /// + /// Returns a human-readable string of the graph. + /// + public virtual string ToReadable() + { + string output = string.Empty; - output = String.Format("{0}\r\n{1}: [", output, node.Key); + foreach (var node in _adjacencyList) + { + var adjacents = string.Empty; - foreach (var adjacentNode in node.Value) - adjacents = String.Format("{0}{1}({2}), ", adjacents, adjacentNode.Destination, adjacentNode.Weight); + output = String.Format("{0}\r\n{1}: [", output, node.Key); - if (adjacents.Length > 0) - adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); + foreach (var adjacentNode in node.Value) + adjacents = String.Format("{0}{1}({2}), ", adjacents, adjacentNode.Destination, adjacentNode.Weight); - output = String.Format("{0}{1}]", output, adjacents); - } + if (adjacents.Length > 0) + adjacents = adjacents.TrimEnd(new char[] { ',', ' ' }); - return output; + output = String.Format("{0}{1}]", output, adjacents); } - /// - /// A depth first search traversal of the graph starting from the first inserted node. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable DepthFirstWalk() - { - return DepthFirstWalk(_firstInsertedNode); - } + return output; + } - /// - /// A depth first search traversal of the graph, starting from a specified vertex. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable DepthFirstWalk(T source) - { - // Check for existence of source - if (VerticesCount == 0) - return new ArrayList(0); - if (!HasVertex(source)) - throw new KeyNotFoundException("The source vertex doesn't exist."); + /// + /// A depth first search traversal of the graph starting from the first inserted node. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable DepthFirstWalk() + { + return DepthFirstWalk(_firstInsertedNode); + } - var visited = new HashSet(); - var stack = new Lists.Stack(); - var listOfNodes = new ArrayList(VerticesCount); + /// + /// A depth first search traversal of the graph, starting from a specified vertex. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable DepthFirstWalk(T source) + { + // Check for existence of source + if (VerticesCount == 0) + return new ArrayList(0); + if (!HasVertex(source)) + throw new KeyNotFoundException("The source vertex doesn't exist."); - stack.Push(source); + var visited = new HashSet(); + var stack = new Lists.Stack(); + var listOfNodes = new ArrayList(VerticesCount); - while (!stack.IsEmpty) - { - var current = stack.Pop(); + stack.Push(source); - if (!visited.Contains(current)) - { - listOfNodes.Add(current); - visited.Add(current); + while (!stack.IsEmpty) + { + var current = stack.Pop(); - foreach (var adjacent in Neighbours(current)) - if (!visited.Contains(adjacent)) - stack.Push(adjacent); - } - } + if (!visited.Contains(current)) + { + listOfNodes.Add(current); + visited.Add(current); - return listOfNodes; + foreach (var adjacent in Neighbours(current)) + if (!visited.Contains(adjacent)) + stack.Push(adjacent); + } } - /// - /// A breadth first search traversal of the graphstarting from the first inserted node. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable BreadthFirstWalk() - { - return BreadthFirstWalk(_firstInsertedNode); - } + return listOfNodes; + } - /// - /// A breadth first search traversal of the graph, starting from a specified vertex. - /// Returns the visited vertices of the graph. - /// - public virtual IEnumerable BreadthFirstWalk(T source) - { - // Check for existence of source - if (VerticesCount == 0) - return new ArrayList(0); - if (!HasVertex(source)) - throw new KeyNotFoundException("The source vertex doesn't exist."); + /// + /// A breadth first search traversal of the graphstarting from the first inserted node. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable BreadthFirstWalk() + { + return BreadthFirstWalk(_firstInsertedNode); + } - var visited = new HashSet(); - var queue = new Lists.Queue(); - var listOfNodes = new ArrayList(VerticesCount); + /// + /// A breadth first search traversal of the graph, starting from a specified vertex. + /// Returns the visited vertices of the graph. + /// + public virtual IEnumerable BreadthFirstWalk(T source) + { + // Check for existence of source + if (VerticesCount == 0) + return new ArrayList(0); + if (!HasVertex(source)) + throw new KeyNotFoundException("The source vertex doesn't exist."); - listOfNodes.Add(source); - visited.Add(source); + var visited = new HashSet(); + var queue = new Lists.Queue(); + var listOfNodes = new ArrayList(VerticesCount); - queue.Enqueue(source); + listOfNodes.Add(source); + visited.Add(source); - while (!queue.IsEmpty) - { - var current = queue.Dequeue(); - var neighbors = Neighbours(current); + queue.Enqueue(source); - foreach (var adjacent in neighbors) + while (!queue.IsEmpty) + { + var current = queue.Dequeue(); + var neighbors = Neighbours(current); + + foreach (var adjacent in neighbors) + { + if (!visited.Contains(adjacent)) { - if (!visited.Contains(adjacent)) - { - listOfNodes.Add(adjacent); - visited.Add(adjacent); - queue.Enqueue(adjacent); - } + listOfNodes.Add(adjacent); + visited.Add(adjacent); + queue.Enqueue(adjacent); } } - - return listOfNodes; } - /// - /// Clear this graph. - /// - public virtual void Clear() - { - _edgesCount = 0; - _adjacencyList.Clear(); - } + return listOfNodes; } -} + /// + /// Clear this graph. + /// + public virtual void Clear() + { + _edgesCount = 0; + _adjacencyList.Clear(); + } +} \ No newline at end of file diff --git a/DataStructures/Graphs/UnweightedEdge.cs b/DataStructures/Graphs/UnweightedEdge.cs index 83e98f4a..937dc275 100644 --- a/DataStructures/Graphs/UnweightedEdge.cs +++ b/DataStructures/Graphs/UnweightedEdge.cs @@ -2,65 +2,63 @@ using DataStructures.Common; -namespace DataStructures.Graphs +namespace DataStructures.Graphs; + +/// +/// The graph edge class. +/// +public class UnweightedEdge : IEdge where TVertex : IComparable { + private const int _edgeWeight = 0; + /// - /// The graph edge class. + /// Gets or sets the source vertex. /// - public class UnweightedEdge : IEdge where TVertex : IComparable - { - private const int _edgeWeight = 0; + /// The source. + public TVertex Source { get; set; } - /// - /// Gets or sets the source vertex. - /// - /// The source. - public TVertex Source { get; set; } - - /// - /// Gets or sets the destination vertex. - /// - /// The destination. - public TVertex Destination { get; set; } + /// + /// Gets or sets the destination vertex. + /// + /// The destination. + public TVertex Destination { get; set; } - /// - /// [PRIVATE MEMBER] Gets or sets the weight. - /// - /// The weight. - public Int64 Weight - { - get => throw new NotImplementedException("Unweighted edges don't have weights."); - set => throw new NotImplementedException("Unweighted edges can't have weights."); - } + /// + /// [PRIVATE MEMBER] Gets or sets the weight. + /// + /// The weight. + public Int64 Weight + { + get => throw new NotImplementedException("Unweighted edges don't have weights."); + set => throw new NotImplementedException("Unweighted edges can't have weights."); + } - /// - /// Gets a value indicating whether this edge is weighted. - /// - public bool IsWeighted => false; + /// + /// Gets a value indicating whether this edge is weighted. + /// + public bool IsWeighted => false; - /// - /// CONSTRUCTOR - /// - public UnweightedEdge(TVertex src, TVertex dst) - { - Source = src; - Destination = dst; - } + /// + /// CONSTRUCTOR + /// + public UnweightedEdge(TVertex src, TVertex dst) + { + Source = src; + Destination = dst; + } - #region IComparable implementation - public int CompareTo(IEdge other) - { - if (other == null) - return -1; + #region IComparable implementation + public int CompareTo(IEdge other) + { + if (other == null) + return -1; - bool areNodesEqual = Source.IsEqualTo(other.Source) && Destination.IsEqualTo(other.Destination); + bool areNodesEqual = Source.IsEqualTo(other.Source) && Destination.IsEqualTo(other.Destination); - if (!areNodesEqual) - return -1; - return 0; - } - #endregion + if (!areNodesEqual) + return -1; + return 0; } -} - + #endregion +} \ No newline at end of file diff --git a/DataStructures/Graphs/WeightedEdge.cs b/DataStructures/Graphs/WeightedEdge.cs index a249e67d..94c142b6 100644 --- a/DataStructures/Graphs/WeightedEdge.cs +++ b/DataStructures/Graphs/WeightedEdge.cs @@ -2,59 +2,58 @@ using DataStructures.Common; -namespace DataStructures.Graphs +namespace DataStructures.Graphs; + +/// +/// The graph weighted edge class. +/// +public class WeightedEdge : IEdge where TVertex : IComparable { /// - /// The graph weighted edge class. + /// Gets or sets the source. /// - public class WeightedEdge : IEdge where TVertex : IComparable + /// The source. + public TVertex Source { get; set; } + + /// + /// Gets or sets the destination. + /// + /// The destination. + public TVertex Destination { get; set; } + + /// + /// Gets or sets the weight of edge. + /// + /// The weight. + public Int64 Weight { get; set; } + + /// + /// Gets a value indicating whether this edge is weighted. + /// + public bool IsWeighted => true; + + /// + /// CONSTRUCTOR + /// + public WeightedEdge(TVertex src, TVertex dst, Int64 weight) + { + Source = src; + Destination = dst; + Weight = weight; + } + + + #region IComparable implementation + public int CompareTo(IEdge other) { - /// - /// Gets or sets the source. - /// - /// The source. - public TVertex Source { get; set; } - - /// - /// Gets or sets the destination. - /// - /// The destination. - public TVertex Destination { get; set; } - - /// - /// Gets or sets the weight of edge. - /// - /// The weight. - public Int64 Weight { get; set; } - - /// - /// Gets a value indicating whether this edge is weighted. - /// - public bool IsWeighted => true; - - /// - /// CONSTRUCTOR - /// - public WeightedEdge(TVertex src, TVertex dst, Int64 weight) - { - Source = src; - Destination = dst; - Weight = weight; - } - - - #region IComparable implementation - public int CompareTo(IEdge other) - { - if (other == null) - return -1; + if (other == null) + return -1; - bool areNodesEqual = Source.IsEqualTo(other.Source) && Destination.IsEqualTo(other.Destination); + bool areNodesEqual = Source.IsEqualTo(other.Source) && Destination.IsEqualTo(other.Destination); - if (!areNodesEqual) - return -1; - return Weight.CompareTo(other.Weight); - } - #endregion + if (!areNodesEqual) + return -1; + return Weight.CompareTo(other.Weight); } -} + #endregion +} \ No newline at end of file diff --git a/DataStructures/Hashing/PrimeHashingFamily.cs b/DataStructures/Hashing/PrimeHashingFamily.cs index 483776be..f1125795 100644 --- a/DataStructures/Hashing/PrimeHashingFamily.cs +++ b/DataStructures/Hashing/PrimeHashingFamily.cs @@ -9,93 +9,91 @@ using System; using DataStructures.Common; -namespace DataStructures.Hashing +namespace DataStructures.Hashing; + +/// +/// Implements a family of randomized Hash Functions +/// +public class PrimeHashingFamily { + private Random _randomizer { get; set; } + private int _numberOfHashFunctions { get; set; } + private int[] _multipliersVector { get; set; } + private static readonly PrimesList _primes = PrimesList.Instance; + /// - /// Implements a family of randomized Hash Functions + /// Initializes the family with a specified number of hash functions. /// - public class PrimeHashingFamily + public PrimeHashingFamily(int numberOfHashFunctions) { - private Random _randomizer { get; set; } - private int _numberOfHashFunctions { get; set; } - private int[] _multipliersVector { get; set; } - private static readonly PrimesList _primes = PrimesList.Instance; - - /// - /// Initializes the family with a specified number of hash functions. - /// - public PrimeHashingFamily(int numberOfHashFunctions) - { - if (numberOfHashFunctions <= 0) - throw new ArgumentOutOfRangeException("Number of hash functions should be greater than zero."); + if (numberOfHashFunctions <= 0) + throw new ArgumentOutOfRangeException("Number of hash functions should be greater than zero."); - _randomizer = new Random(); - _numberOfHashFunctions = numberOfHashFunctions; - _multipliersVector = new int[_numberOfHashFunctions]; + _randomizer = new Random(); + _numberOfHashFunctions = numberOfHashFunctions; + _multipliersVector = new int[_numberOfHashFunctions]; - GenerateNewFunctions(); - } + GenerateNewFunctions(); + } - /// - /// Returns number of member hash functions. - /// - public int NumberOfFunctions => _numberOfHashFunctions; + /// + /// Returns number of member hash functions. + /// + public int NumberOfFunctions => _numberOfHashFunctions; - /// - /// Generates new hash functions with new randomized multipliers. - /// - public void GenerateNewFunctions() - { - // Clear the multipliers vectors - Array.Clear(_multipliersVector, 0, _multipliersVector.Length); - - for (int i = 0; i < _numberOfHashFunctions; i++) - { - var randomIndex = _randomizer.Next(0, _primes.Count - 1); - _multipliersVector[i] = _primes[randomIndex]; - } - } + /// + /// Generates new hash functions with new randomized multipliers. + /// + public void GenerateNewFunctions() + { + // Clear the multipliers vectors + Array.Clear(_multipliersVector, 0, _multipliersVector.Length); - /// - /// Returns hash value of an integer prehash key, given the specified number of the hash function to use. - /// - /// Int pre-hash code of an object. - /// Non-zero, non-negative integer that specified the number of the hash function to use. - /// - public int Hash(int preHashedKey, int whichHashFunction) + for (int i = 0; i < _numberOfHashFunctions; i++) { - if (whichHashFunction <= 0 || whichHashFunction > _numberOfHashFunctions) - throw new ArgumentOutOfRangeException("WhichHashFunction parameter should be greater than zero or equal to the number of Hash Functions."); + var randomIndex = _randomizer.Next(0, _primes.Count - 1); + _multipliersVector[i] = _primes[randomIndex]; + } + } - int preHashValue = 0; - int multiplier = _multipliersVector[whichHashFunction - 1]; - var characters = preHashedKey.ToString().ToCharArray(); + /// + /// Returns hash value of an integer prehash key, given the specified number of the hash function to use. + /// + /// Int pre-hash code of an object. + /// Non-zero, non-negative integer that specified the number of the hash function to use. + /// + public int Hash(int preHashedKey, int whichHashFunction) + { + if (whichHashFunction <= 0 || whichHashFunction > _numberOfHashFunctions) + throw new ArgumentOutOfRangeException("WhichHashFunction parameter should be greater than zero or equal to the number of Hash Functions."); - return multiplier * preHashValue; - } + int preHashValue = 0; + int multiplier = _multipliersVector[whichHashFunction - 1]; + var characters = preHashedKey.ToString().ToCharArray(); - /// - /// Returns hash value of a string, given the specified number of the hash function to use. - /// - /// string key. - /// Non-zero, non-negative integer that specified the number of the hash function to use. - /// - public int Hash(string key, int whichHashFunction) - { - if (string.IsNullOrEmpty(key)) - throw new ArgumentException("Key is either an empty string or null."); + return multiplier * preHashValue; + } - int preHashValue = 0; - var characters = key.ToCharArray(); + /// + /// Returns hash value of a string, given the specified number of the hash function to use. + /// + /// string key. + /// Non-zero, non-negative integer that specified the number of the hash function to use. + /// + public int Hash(string key, int whichHashFunction) + { + if (string.IsNullOrEmpty(key)) + throw new ArgumentException("Key is either an empty string or null."); - foreach (var character in characters) - { - preHashValue += Convert.ToInt32(Char.GetNumericValue(character)); - } + int preHashValue = 0; + var characters = key.ToCharArray(); - return Hash(preHashValue, whichHashFunction); + foreach (var character in characters) + { + preHashValue += Convert.ToInt32(Char.GetNumericValue(character)); } + return Hash(preHashValue, whichHashFunction); } -} +} \ No newline at end of file diff --git a/DataStructures/Hashing/UniversalHashingFamily.cs b/DataStructures/Hashing/UniversalHashingFamily.cs index 07876589..3039838f 100644 --- a/DataStructures/Hashing/UniversalHashingFamily.cs +++ b/DataStructures/Hashing/UniversalHashingFamily.cs @@ -11,113 +11,112 @@ using System; using DataStructures.Common; -namespace DataStructures.Hashing +namespace DataStructures.Hashing; + +/// +/// Implements a family of Universal Hash Functions +/// +public class UniversalHashingFamily { + // A large prime, arbitrarily chosen + // In decimal = 2,146,435,069; + private const int BIG_PRIME = 0x7FEFFFFD; + + private Random _randomizer { get; set; } + private int _numberOfHashFunctions { get; set; } + private int[] _firstMultipliersVector { get; set; } + private int[] _secondMultipliersVector { get; set; } + private static readonly PrimesList _primes = PrimesList.Instance; + /// - /// Implements a family of Universal Hash Functions + /// Initializes the family with a specified number of hash functions. /// - public class UniversalHashingFamily + public UniversalHashingFamily(int numberOfHashFunctions) { - // A large prime, arbitrarily chosen - // In decimal = 2,146,435,069; - private const int BIG_PRIME = 0x7FEFFFFD; - - private Random _randomizer { get; set; } - private int _numberOfHashFunctions { get; set; } - private int[] _firstMultipliersVector { get; set; } - private int[] _secondMultipliersVector { get; set; } - private static readonly PrimesList _primes = PrimesList.Instance; - - /// - /// Initializes the family with a specified number of hash functions. - /// - public UniversalHashingFamily(int numberOfHashFunctions) - { - if (numberOfHashFunctions <= 0) - throw new ArgumentOutOfRangeException("Number of hash functions should be greater than zero."); + if (numberOfHashFunctions <= 0) + throw new ArgumentOutOfRangeException("Number of hash functions should be greater than zero."); - _randomizer = new Random(); - _numberOfHashFunctions = numberOfHashFunctions; - _firstMultipliersVector = new int[_numberOfHashFunctions]; - _secondMultipliersVector = new int[_numberOfHashFunctions]; + _randomizer = new Random(); + _numberOfHashFunctions = numberOfHashFunctions; + _firstMultipliersVector = new int[_numberOfHashFunctions]; + _secondMultipliersVector = new int[_numberOfHashFunctions]; - GenerateNewFunctions(); - } + GenerateNewFunctions(); + } - /// - /// Returns number of member hash functions. - /// - public int NumberOfFunctions => _numberOfHashFunctions; + /// + /// Returns number of member hash functions. + /// + public int NumberOfFunctions => _numberOfHashFunctions; - /// - /// Generates new hash functions with new randomized multipliers. - /// - public void GenerateNewFunctions() - { - // Clear the multipliers vectors - Array.Clear(_firstMultipliersVector, 0, _firstMultipliersVector.Length); - Array.Clear(_secondMultipliersVector, 0, _secondMultipliersVector.Length); + /// + /// Generates new hash functions with new randomized multipliers. + /// + public void GenerateNewFunctions() + { + // Clear the multipliers vectors + Array.Clear(_firstMultipliersVector, 0, _firstMultipliersVector.Length); + Array.Clear(_secondMultipliersVector, 0, _secondMultipliersVector.Length); - int randomMin = 0; - int randomMax = _primes.Count - 1; + int randomMin = 0; + int randomMax = _primes.Count - 1; - for (int i = 0; i < _numberOfHashFunctions; i++) - { - // Get only the primes that are smaller than the biggest-chosen prime. - int randomIndex = _randomizer.Next(randomMin, randomMax); + for (int i = 0; i < _numberOfHashFunctions; i++) + { + // Get only the primes that are smaller than the biggest-chosen prime. + int randomIndex = _randomizer.Next(randomMin, randomMax); - while (_primes[randomIndex] >= BIG_PRIME) - randomIndex = _randomizer.Next(randomMin, randomMax); + while (_primes[randomIndex] >= BIG_PRIME) + randomIndex = _randomizer.Next(randomMin, randomMax); - _firstMultipliersVector[i] = _primes[randomIndex]; + _firstMultipliersVector[i] = _primes[randomIndex]; - // make sure the next prime we choose is different than the first one and less than the biggest-prime. - randomIndex = _randomizer.Next(randomMin, randomMax); + // make sure the next prime we choose is different than the first one and less than the biggest-prime. + randomIndex = _randomizer.Next(randomMin, randomMax); - while (_primes[randomIndex] >= BIG_PRIME || _primes[randomIndex] == _firstMultipliersVector[i]) - randomIndex = _randomizer.Next(randomMin, randomMax); + while (_primes[randomIndex] >= BIG_PRIME || _primes[randomIndex] == _firstMultipliersVector[i]) + randomIndex = _randomizer.Next(randomMin, randomMax); - _secondMultipliersVector[i] = _primes[randomIndex]; - } + _secondMultipliersVector[i] = _primes[randomIndex]; } + } - /// - /// Returns hash value of a string, given the specified number of the hash function to use. - /// - /// Int pre-hash code of an object. - /// Non-zero, non-negative integer that specified the number of the hash function to use. - /// - public int UniversalHash(int preHashedKey, int whichHashFunction) - { - if (whichHashFunction <= 0 || whichHashFunction > _numberOfHashFunctions) - throw new ArgumentOutOfRangeException("WhichHashFunction parameter should be greater than zero or equal to the number of Hash Functions."); - - int a = _firstMultipliersVector[whichHashFunction - 1]; - int b = _secondMultipliersVector[whichHashFunction - 1]; + /// + /// Returns hash value of a string, given the specified number of the hash function to use. + /// + /// Int pre-hash code of an object. + /// Non-zero, non-negative integer that specified the number of the hash function to use. + /// + public int UniversalHash(int preHashedKey, int whichHashFunction) + { + if (whichHashFunction <= 0 || whichHashFunction > _numberOfHashFunctions) + throw new ArgumentOutOfRangeException("WhichHashFunction parameter should be greater than zero or equal to the number of Hash Functions."); - return (a * preHashedKey + b) % BIG_PRIME; - } + int a = _firstMultipliersVector[whichHashFunction - 1]; + int b = _secondMultipliersVector[whichHashFunction - 1]; - /// - /// Returns hash value of a string, given the specified number of the hash function to use. - /// - /// string key. - /// Non-zero, non-negative integer that specified the number of the hash function to use. - public int UniversalHash(string key, int whichHashFunction) - { - if (string.IsNullOrEmpty(key)) - throw new ArgumentException("Key is either an empty string or null."); + return (a * preHashedKey + b) % BIG_PRIME; + } - int prehash = 0; - var characters = key.ToCharArray(); - int n = characters.Length; + /// + /// Returns hash value of a string, given the specified number of the hash function to use. + /// + /// string key. + /// Non-zero, non-negative integer that specified the number of the hash function to use. + public int UniversalHash(string key, int whichHashFunction) + { + if (string.IsNullOrEmpty(key)) + throw new ArgumentException("Key is either an empty string or null."); - for (int i = 0; i < n; ++i) - { - prehash = prehash + (characters[i] ^ (n - 1)); - } + int prehash = 0; + var characters = key.ToCharArray(); + int n = characters.Length; - return UniversalHash(prehash, whichHashFunction); + for (int i = 0; i < n; ++i) + { + prehash = prehash + (characters[i] ^ (n - 1)); } + + return UniversalHash(prehash, whichHashFunction); } -} +} \ No newline at end of file diff --git a/DataStructures/Heaps/BinaryMaxHeap.cs b/DataStructures/Heaps/BinaryMaxHeap.cs index a98798a7..f742071d 100644 --- a/DataStructures/Heaps/BinaryMaxHeap.cs +++ b/DataStructures/Heaps/BinaryMaxHeap.cs @@ -4,277 +4,274 @@ using DataStructures.Common; using DataStructures.Lists; -namespace DataStructures.Heaps +namespace DataStructures.Heaps; + +/// +/// Maximum Heap Data Structure. +/// +public class BinaryMaxHeap : IMaxHeap where T : IComparable { /// - /// Maximum Heap Data Structure. + /// Instance Variables. + /// _collection: The list of elements. Implemented as an array-based list with auto-resizing. + /// + private ArrayList _collection { get; set; } + private Comparer _heapComparer = Comparer.Default; + + + /// + /// CONSTRUCTORS /// - public class BinaryMaxHeap : IMaxHeap where T : IComparable + public BinaryMaxHeap() : this(0, null) { } + public BinaryMaxHeap(Comparer comparer) : this(0, comparer) { } + public BinaryMaxHeap(int capacity, Comparer comparer) { - /// - /// Instance Variables. - /// _collection: The list of elements. Implemented as an array-based list with auto-resizing. - /// - private ArrayList _collection { get; set; } - private Comparer _heapComparer = Comparer.Default; - - - /// - /// CONSTRUCTORS - /// - public BinaryMaxHeap() : this(0, null) { } - public BinaryMaxHeap(Comparer comparer) : this(0, comparer) { } - public BinaryMaxHeap(int capacity, Comparer comparer) - { - _collection = new ArrayList(capacity); - _heapComparer = comparer ?? Comparer.Default; - } + _collection = new ArrayList(capacity); + _heapComparer = comparer ?? Comparer.Default; + } - /// - /// Private Method. Builds a max heap from the inner array-list _collection. - /// - private void _buildMaxHeap() - { - int lastIndex = _collection.Count - 1; - int lastNodeWithChildren = lastIndex / 2; + /// + /// Private Method. Builds a max heap from the inner array-list _collection. + /// + private void _buildMaxHeap() + { + int lastIndex = _collection.Count - 1; + int lastNodeWithChildren = lastIndex / 2; - for (int node = lastNodeWithChildren; node >= 0; node--) - { - _maxHeapify(node, lastIndex); - } + for (int node = lastNodeWithChildren; node >= 0; node--) + { + _maxHeapify(node, lastIndex); } + } - /// - /// Private Method. Used to restore heap condition after insertion - /// - private void _siftUp(int nodeIndex) + /// + /// Private Method. Used to restore heap condition after insertion + /// + private void _siftUp(int nodeIndex) + { + int parent = (nodeIndex - 1) / 2; + while (_heapComparer.Compare(_collection[nodeIndex], _collection[parent]) > 0) { - int parent = (nodeIndex - 1) / 2; - while (_heapComparer.Compare(_collection[nodeIndex], _collection[parent]) > 0) - { - _collection.Swap(parent, nodeIndex); - nodeIndex = parent; - parent = (nodeIndex - 1) / 2; - } + _collection.Swap(parent, nodeIndex); + nodeIndex = parent; + parent = (nodeIndex - 1) / 2; } + } - /// - /// Private Method. Used in Building a Max Heap. - /// - private void _maxHeapify(int nodeIndex, int lastIndex) - { - // assume that the subtrees left(node) and right(node) are max-heaps - int left = nodeIndex * 2 + 1; - int right = left + 1; - int largest = nodeIndex; + /// + /// Private Method. Used in Building a Max Heap. + /// + private void _maxHeapify(int nodeIndex, int lastIndex) + { + // assume that the subtrees left(node) and right(node) are max-heaps + int left = nodeIndex * 2 + 1; + int right = left + 1; + int largest = nodeIndex; - // If collection[left] > collection[nodeIndex] - if (left <= lastIndex && _heapComparer.Compare(_collection[left], _collection[nodeIndex]) > 0) - largest = left; + // If collection[left] > collection[nodeIndex] + if (left <= lastIndex && _heapComparer.Compare(_collection[left], _collection[nodeIndex]) > 0) + largest = left; - // If collection[right] > collection[largest] - if (right <= lastIndex && _heapComparer.Compare(_collection[right], _collection[largest]) > 0) - largest = right; + // If collection[right] > collection[largest] + if (right <= lastIndex && _heapComparer.Compare(_collection[right], _collection[largest]) > 0) + largest = right; - // Swap and heapify - if (largest != nodeIndex) - { - _collection.Swap(nodeIndex, largest); - _maxHeapify(largest, lastIndex); - } + // Swap and heapify + if (largest != nodeIndex) + { + _collection.Swap(nodeIndex, largest); + _maxHeapify(largest, lastIndex); } + } - /// - /// Returns the number of elements in heap - /// - public int Count => _collection.Count; + /// + /// Returns the number of elements in heap + /// + public int Count => _collection.Count; - /// - /// Checks whether this heap is empty - /// - public bool IsEmpty => _collection.Count == 0; + /// + /// Checks whether this heap is empty + /// + public bool IsEmpty => _collection.Count == 0; - /// - /// Gets or sets the at the specified index. - /// - public T this[int index] + /// + /// Gets or sets the at the specified index. + /// + public T this[int index] + { + get { - get + if (index < 0 || index > Count || Count == 0) { - if (index < 0 || index > Count || Count == 0) - { - throw new IndexOutOfRangeException(); - } - - return _collection[index]; + throw new IndexOutOfRangeException(); } - set - { - if (index < 0 || index >= Count) - { - throw new IndexOutOfRangeException(); - } - _collection[index] = value; - - if (index != 0 && _heapComparer.Compare(_collection[index], _collection[(index - 1) / 2]) > 0) // greater than or equal to max - _siftUp(index); - else - _maxHeapify(index, _collection.Count - 1); - } + return _collection[index]; } - - /// - /// Heapifies the specified newCollection. Overrides the current heap. - /// - public void Initialize(IList newCollection) + set { - if (newCollection.Count > 0) + if (index < 0 || index >= Count) { - // Reset and reserve the size of the newCollection - _collection = new ArrayList(newCollection.Count); + throw new IndexOutOfRangeException(); + } - // Copy the elements from the newCollection to the inner collection - for (int i = 0; i < newCollection.Count; ++i) - { - _collection.InsertAt(newCollection[i], i); - } + _collection[index] = value; - // Build the heap - _buildMaxHeap(); - } + if (index != 0 && _heapComparer.Compare(_collection[index], _collection[(index - 1) / 2]) > 0) // greater than or equal to max + _siftUp(index); + else + _maxHeapify(index, _collection.Count - 1); } + } - /// - /// Adding a new key to the heap. - /// - public void Add(T heapKey) + /// + /// Heapifies the specified newCollection. Overrides the current heap. + /// + public void Initialize(IList newCollection) + { + if (newCollection.Count > 0) { - _collection.Add(heapKey); - if (!IsEmpty) - { - _siftUp(_collection.Count - 1); - } - } + // Reset and reserve the size of the newCollection + _collection = new ArrayList(newCollection.Count); - /// - /// Find the maximum node of a max heap. - /// - public T Peek() - { - if (IsEmpty) + // Copy the elements from the newCollection to the inner collection + for (int i = 0; i < newCollection.Count; ++i) { - throw new Exception("Heap is empty."); + _collection.InsertAt(newCollection[i], i); } - return _collection.First; + // Build the heap + _buildMaxHeap(); } + } - /// - /// Removes the node of minimum value from a min heap. - /// - public void RemoveMax() + /// + /// Adding a new key to the heap. + /// + public void Add(T heapKey) + { + _collection.Add(heapKey); + if (!IsEmpty) { - if (IsEmpty) - { - throw new Exception("Heap is empty."); - } - - int max = 0; - int last = _collection.Count - 1; - _collection.Swap(max, last); - - _collection.RemoveAt(last); - last--; - - _maxHeapify(0, last); + _siftUp(_collection.Count - 1); } + } - /// - /// Returns the node of maximum value from a max heap after removing it from the heap. - /// - public T ExtractMax() + /// + /// Find the maximum node of a max heap. + /// + public T Peek() + { + if (IsEmpty) { - var max = Peek(); - RemoveMax(); - return max; + throw new Exception("Heap is empty."); } - /// - /// Clear this heap. - /// - public void Clear() - { - if (IsEmpty) - { - throw new Exception("Heap is empty."); - } - - _collection.Clear(); - } + return _collection.First; + } - /// - /// Rebuilds the heap. - /// - public void RebuildHeap() + /// + /// Removes the node of minimum value from a min heap. + /// + public void RemoveMax() + { + if (IsEmpty) { - _buildMaxHeap(); + throw new Exception("Heap is empty."); } - /// - /// Returns an array version of this heap. - /// - public T[] ToArray() - { - return _collection.ToArray(); - } + int max = 0; + int last = _collection.Count - 1; + _collection.Swap(max, last); + + _collection.RemoveAt(last); + last--; + + _maxHeapify(0, last); + } - /// - /// Returns a list version of this heap. - /// - public List ToList() + /// + /// Returns the node of maximum value from a max heap after removing it from the heap. + /// + public T ExtractMax() + { + var max = Peek(); + RemoveMax(); + return max; + } + + /// + /// Clear this heap. + /// + public void Clear() + { + if (IsEmpty) { - return _collection.ToList(); + throw new Exception("Heap is empty."); } - /// - /// Union two heaps together, returns a new min-heap of both heaps' elements, - /// ... and then destroys the original ones. - /// - public BinaryMaxHeap Union(ref BinaryMaxHeap firstMaxHeap, ref BinaryMaxHeap secondMaxHeap) - { - if (firstMaxHeap == null || secondMaxHeap == null) - throw new ArgumentNullException("Null heaps are not allowed."); + _collection.Clear(); + } + + /// + /// Rebuilds the heap. + /// + public void RebuildHeap() + { + _buildMaxHeap(); + } + + /// + /// Returns an array version of this heap. + /// + public T[] ToArray() + { + return _collection.ToArray(); + } - // Create a new heap with reserved size. - int size = firstMaxHeap.Count + secondMaxHeap.Count; - var newHeap = new BinaryMaxHeap(size, Comparer.Default); + /// + /// Returns a list version of this heap. + /// + public List ToList() + { + return _collection.ToList(); + } - // Insert into the new heap. - while (firstMaxHeap.IsEmpty == false) - newHeap.Add(firstMaxHeap.ExtractMax()); + /// + /// Union two heaps together, returns a new min-heap of both heaps' elements, + /// ... and then destroys the original ones. + /// + public BinaryMaxHeap Union(ref BinaryMaxHeap firstMaxHeap, ref BinaryMaxHeap secondMaxHeap) + { + if (firstMaxHeap == null || secondMaxHeap == null) + throw new ArgumentNullException("Null heaps are not allowed."); - while (secondMaxHeap.IsEmpty == false) - newHeap.Add(secondMaxHeap.ExtractMax()); + // Create a new heap with reserved size. + int size = firstMaxHeap.Count + secondMaxHeap.Count; + var newHeap = new BinaryMaxHeap(size, Comparer.Default); - // Destroy the two heaps. - firstMaxHeap = secondMaxHeap = null; + // Insert into the new heap. + while (firstMaxHeap.IsEmpty == false) + newHeap.Add(firstMaxHeap.ExtractMax()); - return newHeap; - } + while (secondMaxHeap.IsEmpty == false) + newHeap.Add(secondMaxHeap.ExtractMax()); - /// - /// Returns a new min heap that contains all elements of this heap. - /// - public IMinHeap ToMinHeap() - { - BinaryMinHeap newMinHeap = new BinaryMinHeap(Count, _heapComparer); - newMinHeap.Initialize(_collection.ToArray()); - return newMinHeap; - } + // Destroy the two heaps. + firstMaxHeap = secondMaxHeap = null; + return newHeap; } -} + /// + /// Returns a new min heap that contains all elements of this heap. + /// + public IMinHeap ToMinHeap() + { + BinaryMinHeap newMinHeap = new BinaryMinHeap(Count, _heapComparer); + newMinHeap.Initialize(_collection.ToArray()); + return newMinHeap; + } +} \ No newline at end of file diff --git a/DataStructures/Heaps/BinaryMinHeap.cs b/DataStructures/Heaps/BinaryMinHeap.cs index 0679b401..550de4a7 100644 --- a/DataStructures/Heaps/BinaryMinHeap.cs +++ b/DataStructures/Heaps/BinaryMinHeap.cs @@ -4,285 +4,283 @@ using DataStructures.Common; using DataStructures.Lists; -namespace DataStructures.Heaps +namespace DataStructures.Heaps; + +/// +/// Minimum Heap Data Structure. +/// +public class BinaryMinHeap : IMinHeap where T : IComparable { /// - /// Minimum Heap Data Structure. + /// Instance Variables. + /// _collection: The list of elements. Implemented as an array-based list with auto-resizing. + /// + private ArrayList _collection { get; set; } + private Comparer _heapComparer = Comparer.Default; + + + /// + /// CONSTRUCTORS /// - public class BinaryMinHeap : IMinHeap where T : IComparable + public BinaryMinHeap() : this(0, null) { } + public BinaryMinHeap(Comparer comparer) : this(0, comparer) { } + public BinaryMinHeap(int capacity, Comparer comparer) { - /// - /// Instance Variables. - /// _collection: The list of elements. Implemented as an array-based list with auto-resizing. - /// - private ArrayList _collection { get; set; } - private Comparer _heapComparer = Comparer.Default; - - - /// - /// CONSTRUCTORS - /// - public BinaryMinHeap() : this(0, null) { } - public BinaryMinHeap(Comparer comparer) : this(0, comparer) { } - public BinaryMinHeap(int capacity, Comparer comparer) - { - _collection = new ArrayList(capacity); - _heapComparer = comparer ?? Comparer.Default; - } + _collection = new ArrayList(capacity); + _heapComparer = comparer ?? Comparer.Default; + } - /// - /// Builds a min heap from the inner array-list _collection. - /// - private void _buildMinHeap() - { - int lastIndex = _collection.Count - 1; - int lastNodeWithChildren = lastIndex / 2; + /// + /// Builds a min heap from the inner array-list _collection. + /// + private void _buildMinHeap() + { + int lastIndex = _collection.Count - 1; + int lastNodeWithChildren = lastIndex / 2; - for (int node = lastNodeWithChildren; node >= 0; node--) - { - _minHeapify(node, lastIndex); - } + for (int node = lastNodeWithChildren; node >= 0; node--) + { + _minHeapify(node, lastIndex); } + } - /// - /// Private Method. Used to restore heap condition after insertion - /// - private void _siftUp(int nodeIndex) + /// + /// Private Method. Used to restore heap condition after insertion + /// + private void _siftUp(int nodeIndex) + { + int parent = (nodeIndex - 1) / 2; + while (_heapComparer.Compare(_collection[nodeIndex], _collection[parent]) < 0) { - int parent = (nodeIndex - 1) / 2; - while (_heapComparer.Compare(_collection[nodeIndex], _collection[parent]) < 0) - { - _collection.Swap(parent, nodeIndex); - nodeIndex = parent; - parent = (nodeIndex - 1) / 2; - } + _collection.Swap(parent, nodeIndex); + nodeIndex = parent; + parent = (nodeIndex - 1) / 2; } + } - /// - /// Private Method. Used in Building a Min Heap. - /// - /// Type of Heap elements - /// The node index to heapify at. - /// The last index of collection to stop at. - private void _minHeapify(int nodeIndex, int lastIndex) - { - // assume that the subtrees left(node) and right(node) are max-heaps - int left = nodeIndex * 2 + 1; - int right = left + 1; - int smallest = nodeIndex; + /// + /// Private Method. Used in Building a Min Heap. + /// + /// Type of Heap elements + /// The node index to heapify at. + /// The last index of collection to stop at. + private void _minHeapify(int nodeIndex, int lastIndex) + { + // assume that the subtrees left(node) and right(node) are max-heaps + int left = nodeIndex * 2 + 1; + int right = left + 1; + int smallest = nodeIndex; - // If collection[left] < collection[nodeIndex] - if (left <= lastIndex && _heapComparer.Compare(_collection[left], _collection[nodeIndex]) < 0) - smallest = left; + // If collection[left] < collection[nodeIndex] + if (left <= lastIndex && _heapComparer.Compare(_collection[left], _collection[nodeIndex]) < 0) + smallest = left; - // If collection[right] < collection[smallest] - if (right <= lastIndex && _heapComparer.Compare(_collection[right], _collection[smallest]) < 0) - smallest = right; + // If collection[right] < collection[smallest] + if (right <= lastIndex && _heapComparer.Compare(_collection[right], _collection[smallest]) < 0) + smallest = right; - // Swap and heapify - if (smallest != nodeIndex) - { - _collection.Swap(nodeIndex, smallest); - _minHeapify(smallest, lastIndex); - } + // Swap and heapify + if (smallest != nodeIndex) + { + _collection.Swap(nodeIndex, smallest); + _minHeapify(smallest, lastIndex); } + } - /// - /// Returns the number of elements in heap - /// - public int Count => _collection.Count; + /// + /// Returns the number of elements in heap + /// + public int Count => _collection.Count; - /// - /// Checks whether this heap is empty - /// - public bool IsEmpty => _collection.Count == 0; + /// + /// Checks whether this heap is empty + /// + public bool IsEmpty => _collection.Count == 0; - /// - /// Gets or sets the at the specified index. - /// - /// Index. - public T this[int index] + /// + /// Gets or sets the at the specified index. + /// + /// Index. + public T this[int index] + { + get { - get + if (index < 0 || index > Count || Count == 0) { - if (index < 0 || index > Count || Count == 0) - { - throw new IndexOutOfRangeException(); - } - - return _collection[index]; + throw new IndexOutOfRangeException(); } - set - { - if (index < 0 || index >= Count) - { - throw new IndexOutOfRangeException(); - } - _collection[index] = value; - - if (index != 0 && _heapComparer.Compare(_collection[index], _collection[(index - 1) / 2]) < 0) // less than or equal to min - _siftUp(index); - else - _minHeapify(index, _collection.Count - 1); - } + return _collection[index]; } - - /// - /// Heapifies the specified newCollection. Overrides the current heap. - /// - /// New collection. - public void Initialize(IList newCollection) + set { - if (newCollection.Count > 0) + if (index < 0 || index >= Count) { - // Reset and reserve the size of the newCollection - _collection = new ArrayList(newCollection.Count); + throw new IndexOutOfRangeException(); + } - // Copy the elements from the newCollection to the inner collection - for (int i = 0; i < newCollection.Count; ++i) - { - _collection.InsertAt(newCollection[i], i); - } + _collection[index] = value; - // Build the heap - _buildMinHeap(); - } + if (index != 0 && _heapComparer.Compare(_collection[index], _collection[(index - 1) / 2]) < 0) // less than or equal to min + _siftUp(index); + else + _minHeapify(index, _collection.Count - 1); } + } - /// - /// Adding a new key to the heap. - /// - /// Heap key. - public void Add(T heapKey) + /// + /// Heapifies the specified newCollection. Overrides the current heap. + /// + /// New collection. + public void Initialize(IList newCollection) + { + if (newCollection.Count > 0) { - _collection.Add(heapKey); - if (!IsEmpty) - { - _siftUp(_collection.Count - 1); - } - } + // Reset and reserve the size of the newCollection + _collection = new ArrayList(newCollection.Count); - /// - /// Find the minimum node of a min heap. - /// - /// The minimum. - public T Peek() - { - if (IsEmpty) + // Copy the elements from the newCollection to the inner collection + for (int i = 0; i < newCollection.Count; ++i) { - throw new Exception("Heap is empty."); + _collection.InsertAt(newCollection[i], i); } - return _collection.First; + // Build the heap + _buildMinHeap(); } + } - /// - /// Removes the node of minimum value from a min heap. - /// - public void RemoveMin() + /// + /// Adding a new key to the heap. + /// + /// Heap key. + public void Add(T heapKey) + { + _collection.Add(heapKey); + if (!IsEmpty) { - if (IsEmpty) - { - throw new Exception("Heap is empty."); - } - - int min = 0; - int last = _collection.Count - 1; - _collection.Swap(min, last); - - _collection.RemoveAt(last); - last--; - - _minHeapify(0, last); + _siftUp(_collection.Count - 1); } + } - /// - /// Returns the node of minimum value from a min heap after removing it from the heap. - /// - /// The min. - public T ExtractMin() + /// + /// Find the minimum node of a min heap. + /// + /// The minimum. + public T Peek() + { + if (IsEmpty) { - var min = Peek(); - RemoveMin(); - return min; + throw new Exception("Heap is empty."); } - /// - /// Clear this heap. - /// - public void Clear() - { - if (IsEmpty) - { - throw new Exception("Heap is empty."); - } - - _collection.Clear(); - } + return _collection.First; + } - /// - /// Rebuilds the heap. - /// - public void RebuildHeap() + /// + /// Removes the node of minimum value from a min heap. + /// + public void RemoveMin() + { + if (IsEmpty) { - _buildMinHeap(); + throw new Exception("Heap is empty."); } - /// - /// Returns an array version of this heap. - /// - public T[] ToArray() - { - return _collection.ToArray(); - } + int min = 0; + int last = _collection.Count - 1; + _collection.Swap(min, last); + + _collection.RemoveAt(last); + last--; + + _minHeapify(0, last); + } - /// - /// Returns a list version of this heap. - /// - public List ToList() + /// + /// Returns the node of minimum value from a min heap after removing it from the heap. + /// + /// The min. + public T ExtractMin() + { + var min = Peek(); + RemoveMin(); + return min; + } + + /// + /// Clear this heap. + /// + public void Clear() + { + if (IsEmpty) { - return _collection.ToList(); + throw new Exception("Heap is empty."); } - /// - /// Union two heaps together, returns a new min-heap of both heaps' elements, - /// ... and then destroys the original ones. - /// - public BinaryMinHeap Union(ref BinaryMinHeap firstMinHeap, ref BinaryMinHeap secondMinHeap) - { - if (firstMinHeap == null || secondMinHeap == null) - throw new ArgumentNullException("Null heaps are not allowed."); + _collection.Clear(); + } - // Create a new heap with reserved size. - int size = firstMinHeap.Count + secondMinHeap.Count; - var newHeap = new BinaryMinHeap(size, Comparer.Default); + /// + /// Rebuilds the heap. + /// + public void RebuildHeap() + { + _buildMinHeap(); + } - // Insert into the new heap. - while (firstMinHeap.IsEmpty == false) - newHeap.Add(firstMinHeap.ExtractMin()); + /// + /// Returns an array version of this heap. + /// + public T[] ToArray() + { + return _collection.ToArray(); + } - while (secondMinHeap.IsEmpty == false) - newHeap.Add(secondMinHeap.ExtractMin()); + /// + /// Returns a list version of this heap. + /// + public List ToList() + { + return _collection.ToList(); + } - // Destroy the two heaps. - firstMinHeap = secondMinHeap = null; + /// + /// Union two heaps together, returns a new min-heap of both heaps' elements, + /// ... and then destroys the original ones. + /// + public BinaryMinHeap Union(ref BinaryMinHeap firstMinHeap, ref BinaryMinHeap secondMinHeap) + { + if (firstMinHeap == null || secondMinHeap == null) + throw new ArgumentNullException("Null heaps are not allowed."); - return newHeap; - } + // Create a new heap with reserved size. + int size = firstMinHeap.Count + secondMinHeap.Count; + var newHeap = new BinaryMinHeap(size, Comparer.Default); - /// - /// Returns a new max heap that contains all elements of this heap. - /// - public IMaxHeap ToMaxHeap() - { - BinaryMaxHeap newMaxHeap = new BinaryMaxHeap(Count, _heapComparer); - newMaxHeap.Initialize(_collection.ToArray()); - return newMaxHeap; - } + // Insert into the new heap. + while (firstMinHeap.IsEmpty == false) + newHeap.Add(firstMinHeap.ExtractMin()); + while (secondMinHeap.IsEmpty == false) + newHeap.Add(secondMinHeap.ExtractMin()); + + // Destroy the two heaps. + firstMinHeap = secondMinHeap = null; + + return newHeap; + } + + /// + /// Returns a new max heap that contains all elements of this heap. + /// + public IMaxHeap ToMaxHeap() + { + BinaryMaxHeap newMaxHeap = new BinaryMaxHeap(Count, _heapComparer); + newMaxHeap.Initialize(_collection.ToArray()); + return newMaxHeap; } -} +} \ No newline at end of file diff --git a/DataStructures/Heaps/BinomialMinHeap.cs b/DataStructures/Heaps/BinomialMinHeap.cs index d3ad7b4e..858968c8 100644 --- a/DataStructures/Heaps/BinomialMinHeap.cs +++ b/DataStructures/Heaps/BinomialMinHeap.cs @@ -4,361 +4,359 @@ using DataStructures.Common; using DataStructures.Lists; -namespace DataStructures.Heaps +namespace DataStructures.Heaps; + +/// +/// BINOMIAL MIN HEAP Data Structure +/// +public class BinomialMinHeap : IMinHeap where T : IComparable { /// - /// BINOMIAL MIN HEAP Data Structure + /// The Heap Node class. /// - public class BinomialMinHeap : IMinHeap where T : IComparable + private class BinomialNode where T : IComparable { - /// - /// The Heap Node class. - /// - private class BinomialNode where T : IComparable + public T Value { get; set; } + public BinomialNode Parent { get; set; } + public BinomialNode Sibling { get; set; } // Right-Sibling + public BinomialNode Child { get; set; } // Left-Child + + // Constructors + public BinomialNode() : this(default, null, null, null) { } + public BinomialNode(T value) : this(value, null, null, null) { } + public BinomialNode(T value, BinomialNode parent, BinomialNode sibling, BinomialNode child) { - public T Value { get; set; } - public BinomialNode Parent { get; set; } - public BinomialNode Sibling { get; set; } // Right-Sibling - public BinomialNode Child { get; set; } // Left-Child - - // Constructors - public BinomialNode() : this(default, null, null, null) { } - public BinomialNode(T value) : this(value, null, null, null) { } - public BinomialNode(T value, BinomialNode parent, BinomialNode sibling, BinomialNode child) - { - Value = value; - Parent = parent; - Sibling = sibling; - Child = child; - } - - // Helper boolean flags - public bool HasSiblings => Sibling != null; - - public bool HasChildren => Child != null; + Value = value; + Parent = parent; + Sibling = sibling; + Child = child; } + // Helper boolean flags + public bool HasSiblings => Sibling != null; - /// - /// INSTANCE VARIABLES - /// - private int _size { get; set; } - private const int _defaultCapacity = 8; - private ArrayList> _forest { get; set; } - + public bool HasChildren => Child != null; + } - /// - /// CONSTRUCTORS - /// - public BinomialMinHeap() - : this(8) - { - // Empty constructor - } - public BinomialMinHeap(int capacity) - { - if (capacity <= 0) - throw new ArgumentOutOfRangeException(); + /// + /// INSTANCE VARIABLES + /// + private int _size { get; set; } + private const int _defaultCapacity = 8; + private ArrayList> _forest { get; set; } - capacity = capacity < _defaultCapacity ? _defaultCapacity : capacity; - _size = 0; - _forest = new ArrayList>(capacity); - } + /// + /// CONSTRUCTORS + /// + public BinomialMinHeap() + : this(8) + { + // Empty constructor + } + public BinomialMinHeap(int capacity) + { + if (capacity <= 0) + throw new ArgumentOutOfRangeException(); - /************************************************************************************************/ - /** PRIVATE HELPER FUNCTIONS */ + capacity = capacity < _defaultCapacity ? _defaultCapacity : capacity; + _size = 0; + _forest = new ArrayList>(capacity); + } - /// - /// Removes root of tree at he specified index. - /// - private void _removeAtIndex(int minIndex) - { - // Get the deletedTree - // The min-root lies at _forest[minIndex] - BinomialNode deletedTreeRoot = _forest[minIndex].Child; - // Exit if there was no children under old-min-root - if (deletedTreeRoot == null) - return; + /************************************************************************************************/ + /** PRIVATE HELPER FUNCTIONS */ - // CONSTRUCT H'' (double-prime) - BinomialMinHeap deletedForest = new BinomialMinHeap(); - deletedForest._forest.Resize(minIndex + 1); - deletedForest._size = (1 << minIndex) - 1; - for (int i = minIndex - 1; i >= 0; --i) - { - deletedForest._forest[i] = deletedTreeRoot; - deletedTreeRoot = deletedTreeRoot.Sibling; - deletedForest._forest[i].Sibling = null; - } + /// + /// Removes root of tree at he specified index. + /// + private void _removeAtIndex(int minIndex) + { + // Get the deletedTree + // The min-root lies at _forest[minIndex] + BinomialNode deletedTreeRoot = _forest[minIndex].Child; - // CONSTRUCT H' (single-prime) - _forest[minIndex] = null; - _size = deletedForest._size + 1; + // Exit if there was no children under old-min-root + if (deletedTreeRoot == null) + return; - Merge(deletedForest); + // CONSTRUCT H'' (double-prime) + BinomialMinHeap deletedForest = new BinomialMinHeap(); + deletedForest._forest.Resize(minIndex + 1); + deletedForest._size = (1 << minIndex) - 1; - // Decrease the size - --_size; + for (int i = minIndex - 1; i >= 0; --i) + { + deletedForest._forest[i] = deletedTreeRoot; + deletedTreeRoot = deletedTreeRoot.Sibling; + deletedForest._forest[i].Sibling = null; } - /// - /// Returns index of the tree with the minimum root's value. - /// - private int _findMinIndex() - { - int i, minIndex; + // CONSTRUCT H' (single-prime) + _forest[minIndex] = null; + _size = deletedForest._size + 1; - // Loop until you reach a slot in the _forest that is not null. - // The final value of "i" will be pointing to the non-null _forest slot. - for (i = 0; i < _forest.Count && _forest[i] == null; ++i) ; + Merge(deletedForest); - // Loop over the trees in forest, and return the index of the slot that has the tree with the min-valued root - for (minIndex = i; i < _forest.Count; ++i) - if (_forest[i] != null && _forest[i].Value.IsLessThan(_forest[minIndex].Value)) - minIndex = i; + // Decrease the size + --_size; + } - return minIndex; - } + /// + /// Returns index of the tree with the minimum root's value. + /// + private int _findMinIndex() + { + int i, minIndex; - /// - /// Combines two trees and returns the new tree root node. - /// - private BinomialNode _combineTrees(BinomialNode firstTreeRoot, BinomialNode secondTreeRoot) - { - if (firstTreeRoot == null || secondTreeRoot == null) - throw new ArgumentNullException("Either one of the nodes or both are null."); + // Loop until you reach a slot in the _forest that is not null. + // The final value of "i" will be pointing to the non-null _forest slot. + for (i = 0; i < _forest.Count && _forest[i] == null; ++i) ; - if (secondTreeRoot.Value.IsLessThan(firstTreeRoot.Value)) - return _combineTrees(secondTreeRoot, firstTreeRoot); + // Loop over the trees in forest, and return the index of the slot that has the tree with the min-valued root + for (minIndex = i; i < _forest.Count; ++i) + if (_forest[i] != null && _forest[i].Value.IsLessThan(_forest[minIndex].Value)) + minIndex = i; - secondTreeRoot.Sibling = firstTreeRoot.Child; - firstTreeRoot.Child = secondTreeRoot; - secondTreeRoot.Parent = firstTreeRoot; + return minIndex; + } - return firstTreeRoot; - } + /// + /// Combines two trees and returns the new tree root node. + /// + private BinomialNode _combineTrees(BinomialNode firstTreeRoot, BinomialNode secondTreeRoot) + { + if (firstTreeRoot == null || secondTreeRoot == null) + throw new ArgumentNullException("Either one of the nodes or both are null."); - /// - /// Clones a tree, given it's root node. - /// - private BinomialNode _cloneTree(BinomialNode treeRoot) - { - if (treeRoot == null) - return null; - return new BinomialNode() { Value = treeRoot.Value, Child = _cloneTree(treeRoot.Child), Sibling = _cloneTree(treeRoot.Sibling) }; - } + if (secondTreeRoot.Value.IsLessThan(firstTreeRoot.Value)) + return _combineTrees(secondTreeRoot, firstTreeRoot); + secondTreeRoot.Sibling = firstTreeRoot.Child; + firstTreeRoot.Child = secondTreeRoot; + secondTreeRoot.Parent = firstTreeRoot; - /************************************************************************************************/ - /** PUBLIC API FUNCTIONS */ + return firstTreeRoot; + } + /// + /// Clones a tree, given it's root node. + /// + private BinomialNode _cloneTree(BinomialNode treeRoot) + { + if (treeRoot == null) + return null; + return new BinomialNode() { Value = treeRoot.Value, Child = _cloneTree(treeRoot.Child), Sibling = _cloneTree(treeRoot.Sibling) }; + } - /// - /// Returns count of elements in heap. - /// - public int Count => _size; - /// - /// Checks if heap is empty - /// - /// - public bool IsEmpty => _size == 0; + /************************************************************************************************/ + /** PUBLIC API FUNCTIONS */ - /// - /// Initializes this heap with a collection of elements. - /// - public void Initialize(IList newCollection) - { - if (newCollection == null) - throw new ArgumentNullException(); - if (newCollection.Count > ArrayList.MAXIMUM_ARRAY_LENGTH_x64) - throw new OverflowException(); + /// + /// Returns count of elements in heap. + /// + public int Count => _size; - _forest = new ArrayList>(newCollection.Count + 1); + /// + /// Checks if heap is empty + /// + /// + public bool IsEmpty => _size == 0; - for (int i = 0; i < newCollection.Count; ++i) - Add(newCollection[i]); - } + /// + /// Initializes this heap with a collection of elements. + /// + public void Initialize(IList newCollection) + { + if (newCollection == null) + throw new ArgumentNullException(); - /// - /// Inserts a new item to heap. - /// - public void Add(T heapKey) - { - var tempHeap = new BinomialMinHeap(); - tempHeap._forest.Add(new BinomialNode(heapKey)); - tempHeap._size = 1; + if (newCollection.Count > ArrayList.MAXIMUM_ARRAY_LENGTH_x64) + throw new OverflowException(); - // Merge this with tempHeap - Merge(tempHeap); + _forest = new ArrayList>(newCollection.Count + 1); - // Increase the _size - ++_size; - } + for (int i = 0; i < newCollection.Count; ++i) + Add(newCollection[i]); + } - /// - /// Return the min element. - /// - public T Peek() - { - if (IsEmpty) - throw new Exception("Heap is empty."); + /// + /// Inserts a new item to heap. + /// + public void Add(T heapKey) + { + var tempHeap = new BinomialMinHeap(); + tempHeap._forest.Add(new BinomialNode(heapKey)); + tempHeap._size = 1; - int minIndex = _findMinIndex(); - var minValue = _forest[minIndex].Value; + // Merge this with tempHeap + Merge(tempHeap); - return minValue; - } + // Increase the _size + ++_size; + } - /// - /// Remove the min element from heap. - /// - public void RemoveMin() - { - if (IsEmpty) - throw new Exception("Heap is empty."); + /// + /// Return the min element. + /// + public T Peek() + { + if (IsEmpty) + throw new Exception("Heap is empty."); - _removeAtIndex(_findMinIndex()); - } + int minIndex = _findMinIndex(); + var minValue = _forest[minIndex].Value; - /// - /// Return the min element and then remove it from heap. - /// - public T ExtractMin() - { - if (IsEmpty) - throw new Exception("Heap is empty."); + return minValue; + } - // Get the min-node index - int minIndex = _findMinIndex(); - var minValue = _forest[minIndex].Value; + /// + /// Remove the min element from heap. + /// + public void RemoveMin() + { + if (IsEmpty) + throw new Exception("Heap is empty."); - // Remove min from heap - _removeAtIndex(minIndex); + _removeAtIndex(_findMinIndex()); + } - return minValue; - } + /// + /// Return the min element and then remove it from heap. + /// + public T ExtractMin() + { + if (IsEmpty) + throw new Exception("Heap is empty."); - /// - /// Merges the elements of another heap with this heap. - /// - public void Merge(BinomialMinHeap otherHeap) - { - // Avoid aliasing problems - if (this == otherHeap) - return; + // Get the min-node index + int minIndex = _findMinIndex(); + var minValue = _forest[minIndex].Value; - // Avoid null or empty cases - if (otherHeap == null || otherHeap.IsEmpty) - return; + // Remove min from heap + _removeAtIndex(minIndex); - BinomialNode carryNode = null; - _size = _size + otherHeap._size; + return minValue; + } - // One capacity-change step - if (_size > _forest.Count) - { - int newSize = Math.Max(_forest.Count, otherHeap._forest.Count) + 1; - _forest.Resize(newSize); - } + /// + /// Merges the elements of another heap with this heap. + /// + public void Merge(BinomialMinHeap otherHeap) + { + // Avoid aliasing problems + if (this == otherHeap) + return; - for (int i = 0, j = 1; j <= _size; i++, j *= 2) - { - BinomialNode treeRoot1 = _forest.IsEmpty == true ? null : _forest[i]; - BinomialNode treeRoot2 = i < otherHeap._forest.Count ? otherHeap._forest[i] : null; - - int whichCase = treeRoot1 == null ? 0 : 1; - whichCase += treeRoot2 == null ? 0 : 2; - whichCase += carryNode == null ? 0 : 4; - - switch (whichCase) - { - /*** SINGLE CASES ***/ - case 0: /* No trees */ - case 1: /* Only this */ - break; - case 2: /* Only otherHeap */ - _forest[i] = treeRoot2; - otherHeap._forest[i] = null; - break; - case 4: /* Only carryNode */ - _forest[i] = carryNode; - carryNode = null; - break; - - /*** BINARY CASES ***/ - case 3: /* this and otherHeap */ - carryNode = _combineTrees(treeRoot1, treeRoot2); - _forest[i] = otherHeap._forest[i] = null; - break; - case 5: /* this and carryNode */ - carryNode = _combineTrees(treeRoot1, carryNode); - _forest[i] = null; - break; - case 6: /* otherHeap and carryNode */ - carryNode = _combineTrees(treeRoot2, carryNode); - otherHeap._forest[i] = null; - break; - case 7: /* all the nodes */ - _forest[i] = carryNode; - carryNode = _combineTrees(treeRoot1, treeRoot2); - otherHeap._forest[i] = null; - break; - }//end-switch - }//end-for - - // Clear otherHeap - otherHeap.Clear(); - } + // Avoid null or empty cases + if (otherHeap == null || otherHeap.IsEmpty) + return; - /// - /// Returns an array copy of heap. - /// - public T[] ToArray() - { - throw new NotImplementedException(); - } + BinomialNode carryNode = null; + _size = _size + otherHeap._size; - /// - /// Rebuilds the heap. - /// - public void RebuildHeap() + // One capacity-change step + if (_size > _forest.Count) { - throw new NotImplementedException(); + int newSize = Math.Max(_forest.Count, otherHeap._forest.Count) + 1; + _forest.Resize(newSize); } - /// - /// Returns a list copy of heap. - /// - public List ToList() + for (int i = 0, j = 1; j <= _size; i++, j *= 2) { - throw new NotImplementedException(); - } + BinomialNode treeRoot1 = _forest.IsEmpty == true ? null : _forest[i]; + BinomialNode treeRoot2 = i < otherHeap._forest.Count ? otherHeap._forest[i] : null; - /// - /// Returns a binomial max-heap copy of this instance. - /// - public IMaxHeap ToMaxHeap() - { - throw new NotImplementedException(); - } + int whichCase = treeRoot1 == null ? 0 : 1; + whichCase += treeRoot2 == null ? 0 : 2; + whichCase += carryNode == null ? 0 : 4; - /// - /// Clear this instance. - /// - public void Clear() - { - _size = 0; - _forest.Clear(); - } + switch (whichCase) + { + /*** SINGLE CASES ***/ + case 0: /* No trees */ + case 1: /* Only this */ + break; + case 2: /* Only otherHeap */ + _forest[i] = treeRoot2; + otherHeap._forest[i] = null; + break; + case 4: /* Only carryNode */ + _forest[i] = carryNode; + carryNode = null; + break; + + /*** BINARY CASES ***/ + case 3: /* this and otherHeap */ + carryNode = _combineTrees(treeRoot1, treeRoot2); + _forest[i] = otherHeap._forest[i] = null; + break; + case 5: /* this and carryNode */ + carryNode = _combineTrees(treeRoot1, carryNode); + _forest[i] = null; + break; + case 6: /* otherHeap and carryNode */ + carryNode = _combineTrees(treeRoot2, carryNode); + otherHeap._forest[i] = null; + break; + case 7: /* all the nodes */ + _forest[i] = carryNode; + carryNode = _combineTrees(treeRoot1, treeRoot2); + otherHeap._forest[i] = null; + break; + }//end-switch + }//end-for + + // Clear otherHeap + otherHeap.Clear(); + } + /// + /// Returns an array copy of heap. + /// + public T[] ToArray() + { + throw new NotImplementedException(); + } + + /// + /// Rebuilds the heap. + /// + public void RebuildHeap() + { + throw new NotImplementedException(); + } + + /// + /// Returns a list copy of heap. + /// + public List ToList() + { + throw new NotImplementedException(); + } + + /// + /// Returns a binomial max-heap copy of this instance. + /// + public IMaxHeap ToMaxHeap() + { + throw new NotImplementedException(); + } + + /// + /// Clear this instance. + /// + public void Clear() + { + _size = 0; + _forest.Clear(); } -} +} \ No newline at end of file diff --git a/DataStructures/Heaps/IMaxHeap.cs b/DataStructures/Heaps/IMaxHeap.cs index 4b829772..53272702 100644 --- a/DataStructures/Heaps/IMaxHeap.cs +++ b/DataStructures/Heaps/IMaxHeap.cs @@ -1,73 +1,72 @@  -namespace DataStructures.Heaps +namespace DataStructures.Heaps; + +public interface IMaxHeap where T : System.IComparable { - public interface IMaxHeap where T : System.IComparable - { - /// - /// Returns the number of elements in heap - /// - int Count { get; } + /// + /// Returns the number of elements in heap + /// + int Count { get; } - /// - /// Checks whether this heap is empty - /// - bool IsEmpty { get; } + /// + /// Checks whether this heap is empty + /// + bool IsEmpty { get; } - /// - /// Heapifies the specified newCollection. Overrides the current heap. - /// - /// New collection. - void Initialize(System.Collections.Generic.IList newCollection); + /// + /// Heapifies the specified newCollection. Overrides the current heap. + /// + /// New collection. + void Initialize(System.Collections.Generic.IList newCollection); - /// - /// Adding a new key to the heap. - /// - /// Heap key. - void Add(T heapKey); + /// + /// Adding a new key to the heap. + /// + /// Heap key. + void Add(T heapKey); - /// - /// Find the maximum node of a max heap. - /// - /// The maximum. - T Peek(); + /// + /// Find the maximum node of a max heap. + /// + /// The maximum. + T Peek(); - /// - /// Removes the node of maximum value from a max heap. - /// - void RemoveMax(); + /// + /// Removes the node of maximum value from a max heap. + /// + void RemoveMax(); - /// - /// Returns the node of maximum value from a max heap after removing it from the heap. - /// - /// The max. - T ExtractMax(); + /// + /// Returns the node of maximum value from a max heap after removing it from the heap. + /// + /// The max. + T ExtractMax(); - /// - /// Clear this heap. - /// - void Clear(); + /// + /// Clear this heap. + /// + void Clear(); - /// - /// Rebuilds the heap. - /// - void RebuildHeap(); + /// + /// Rebuilds the heap. + /// + void RebuildHeap(); - /// - /// Returns an array version of this heap. - /// - /// The array. - T[] ToArray(); + /// + /// Returns an array version of this heap. + /// + /// The array. + T[] ToArray(); - /// - /// Returns a list version of this heap. - /// - /// The list. - System.Collections.Generic.List ToList(); + /// + /// Returns a list version of this heap. + /// + /// The list. + System.Collections.Generic.List ToList(); - /// - /// Returns a new max heap that contains all elements of this heap. - /// - /// The max heap. - IMinHeap ToMinHeap(); - } -} + /// + /// Returns a new max heap that contains all elements of this heap. + /// + /// The max heap. + IMinHeap ToMinHeap(); +} \ No newline at end of file diff --git a/DataStructures/Heaps/IMinHeap.cs b/DataStructures/Heaps/IMinHeap.cs index 998c5257..a8781269 100644 --- a/DataStructures/Heaps/IMinHeap.cs +++ b/DataStructures/Heaps/IMinHeap.cs @@ -1,73 +1,72 @@  -namespace DataStructures.Heaps +namespace DataStructures.Heaps; + +public interface IMinHeap where T : System.IComparable { - public interface IMinHeap where T : System.IComparable - { - /// - /// Returns the number of elements in heap - /// - int Count { get; } + /// + /// Returns the number of elements in heap + /// + int Count { get; } - /// - /// Checks whether this heap is empty - /// - bool IsEmpty { get; } + /// + /// Checks whether this heap is empty + /// + bool IsEmpty { get; } - /// - /// Heapifies the specified newCollection. Overrides the current heap. - /// - /// New collection. - void Initialize(System.Collections.Generic.IList newCollection); + /// + /// Heapifies the specified newCollection. Overrides the current heap. + /// + /// New collection. + void Initialize(System.Collections.Generic.IList newCollection); - /// - /// Adding a new key to the heap. - /// - /// Heap key. - void Add(T heapKey); + /// + /// Adding a new key to the heap. + /// + /// Heap key. + void Add(T heapKey); - /// - /// Find the minimum node of a min heap. - /// - /// The minimum. - T Peek(); + /// + /// Find the minimum node of a min heap. + /// + /// The minimum. + T Peek(); - /// - /// Removes the node of minimum value from a min heap. - /// - void RemoveMin(); + /// + /// Removes the node of minimum value from a min heap. + /// + void RemoveMin(); - /// - /// Returns the node of minimum value from a min heap after removing it from the heap. - /// - /// The min. - T ExtractMin(); + /// + /// Returns the node of minimum value from a min heap after removing it from the heap. + /// + /// The min. + T ExtractMin(); - /// - /// Clear this heap. - /// - void Clear(); + /// + /// Clear this heap. + /// + void Clear(); - /// - /// Rebuilds the heap. - /// - void RebuildHeap(); + /// + /// Rebuilds the heap. + /// + void RebuildHeap(); - /// - /// Returns an array version of this heap. - /// - /// The array. - T[] ToArray(); + /// + /// Returns an array version of this heap. + /// + /// The array. + T[] ToArray(); - /// - /// Returns a list version of this heap. - /// - /// The list. - System.Collections.Generic.List ToList(); + /// + /// Returns a list version of this heap. + /// + /// The list. + System.Collections.Generic.List ToList(); - /// - /// Returns a new min heap that contains all elements of this heap. - /// - /// The min heap. - IMaxHeap ToMaxHeap(); - } -} + /// + /// Returns a new min heap that contains all elements of this heap. + /// + /// The min heap. + IMaxHeap ToMaxHeap(); +} \ No newline at end of file diff --git a/DataStructures/Heaps/KeyedPriorityQueue.cs b/DataStructures/Heaps/KeyedPriorityQueue.cs index de97035f..86f38b3e 100644 --- a/DataStructures/Heaps/KeyedPriorityQueue.cs +++ b/DataStructures/Heaps/KeyedPriorityQueue.cs @@ -1,290 +1,288 @@ using System; using System.Collections.Generic; -namespace DataStructures.Heaps +namespace DataStructures.Heaps; + +/// +/// Implements the Keyed Priority Queue Data Structure. +/// All nodes have: a Key, a Value, a Priority +/// Node's Key type +/// Node's Value type +/// Node's Priority type +/// +public class PriorityQueue where P : IComparable

{ ///

- /// Implements the Keyed Priority Queue Data Structure. - /// All nodes have: a Key, a Value, a Priority - /// Node's Key type - /// Node's Value type - /// Node's Priority type + /// Instance variables /// - public class PriorityQueue where P : IComparable

+ private BinaryMaxHeap> _heap { get; set; } + private Comparer> _priorityComparer { get; set; } + private Dictionary _keysMap { get; set; } + + + ///

+ /// CONSTRUCTOR + /// + public PriorityQueue() : this(0, null) { } + + /// + /// CONSTRUCTOR + /// + /// Capacity of priority queue. + public PriorityQueue(int capacity) : this(capacity, null) { } + + /// + /// CONSTRUCTOR + /// + /// Capacity of priority queue. + /// The node's priority comparer. + public PriorityQueue(int capacity, Comparer> priorityComparer) { - /// - /// Instance variables - /// - private BinaryMaxHeap> _heap { get; set; } - private Comparer> _priorityComparer { get; set; } - private Dictionary _keysMap { get; set; } - - - /// - /// CONSTRUCTOR - /// - public PriorityQueue() : this(0, null) { } - - /// - /// CONSTRUCTOR - /// - /// Capacity of priority queue. - public PriorityQueue(int capacity) : this(capacity, null) { } - - /// - /// CONSTRUCTOR - /// - /// Capacity of priority queue. - /// The node's priority comparer. - public PriorityQueue(int capacity, Comparer> priorityComparer) + if (capacity >= 0) { - if (capacity >= 0) + if (priorityComparer == null) { - if (priorityComparer == null) - { - _priorityComparer = Comparer>.Default; - } - else - { - _priorityComparer = priorityComparer; - } - - _heap = new BinaryMaxHeap>(capacity, _priorityComparer); - _keysMap = new Dictionary(); + _priorityComparer = Comparer>.Default; } else { - throw new ArgumentOutOfRangeException("Please provide a valid capacity."); + _priorityComparer = priorityComparer; } - } - - - /// - /// Returns the count of elements in the queue. - /// - public int Count => _heap.Count; - - /// - /// Checks if the queue is empty - /// True if queue is empty; false otherwise. - /// - public bool IsEmpty => _heap.IsEmpty; - - - /// - /// Returns an array of keys - /// - public K[] Keys + _heap = new BinaryMaxHeap>(capacity, _priorityComparer); + _keysMap = new Dictionary(); + } + else { - get - { - var keysArray = new K[_keysMap.Count]; - _keysMap.Keys.CopyTo(keysArray, 0); - return keysArray; - } + throw new ArgumentOutOfRangeException("Please provide a valid capacity."); } + } - /// - /// Returns the highest priority element. - /// - /// The at highest priority. - public V PeekAtHighestPriority() - { - if (_heap.IsEmpty) - { - throw new ArgumentOutOfRangeException("Queue is empty."); - } + /// + /// Returns the count of elements in the queue. + /// + public int Count => _heap.Count; - return _heap.Peek().Value; - } + + /// + /// Checks if the queue is empty + /// True if queue is empty; false otherwise. + /// + public bool IsEmpty => _heap.IsEmpty; - /// - /// Enqueue the specified key and value without priority. - /// - /// Key. - /// Value. - public void Enqueue(K key, V value) + /// + /// Returns an array of keys + /// + public K[] Keys + { + get { - Enqueue(key, value, default); + var keysArray = new K[_keysMap.Count]; + _keysMap.Keys.CopyTo(keysArray, 0); + return keysArray; } + } - /// - /// Enqueue the specified key, value and priority. - /// - /// Key. - /// Value. - /// Priority. - public void Enqueue(K key, V value, P priority) + /// + /// Returns the highest priority element. + /// + /// The at highest priority. + public V PeekAtHighestPriority() + { + if (_heap.IsEmpty) { - if (!_keysMap.ContainsKey(key)) - { - _keysMap.Add(key, 1); - } - else - { - _keysMap[key] += 1; - } - - var newNode = new PriorityQueueNode(key, value, priority); - _heap.Add(newNode); + throw new ArgumentOutOfRangeException("Queue is empty."); } + return _heap.Peek().Value; + } - /// - /// Dequeue this instance. - /// - public V Dequeue() - { - if (_heap.IsEmpty) - { - throw new ArgumentOutOfRangeException("Queue is empty."); - } - var highest = _heap.Peek(); + /// + /// Enqueue the specified key and value without priority. + /// + /// Key. + /// Value. + public void Enqueue(K key, V value) + { + Enqueue(key, value, default); + } - // Decrement the key's counter - _keysMap[highest.Key] = _keysMap[highest.Key] - 1; - if (_keysMap[highest.Key] == 0) - { - _keysMap.Remove(highest.Key); - } - _heap.RemoveMax(); - return highest.Value; + /// + /// Enqueue the specified key, value and priority. + /// + /// Key. + /// Value. + /// Priority. + public void Enqueue(K key, V value, P priority) + { + if (!_keysMap.ContainsKey(key)) + { + _keysMap.Add(key, 1); } - - - /// - /// Sets the priority. - /// - /// Key. - /// New priority. - public void SetPriority(K key, P newPriority) + else { - // Handle boundaries errors - if (_heap.IsEmpty) - { - throw new ArgumentOutOfRangeException("Queue is empty."); - } + _keysMap[key] += 1; + } - if (!_keysMap.ContainsKey(key)) - { - throw new KeyNotFoundException(); - } + var newNode = new PriorityQueueNode(key, value, priority); + _heap.Add(newNode); + } - var keyComparer = Comparer.Default; - for (int i = 0; i < _heap.Count; ++i) - { - if (keyComparer.Compare(_heap[i].Key, key) == 0) - { - _heap[i].Priority = newPriority; - break; - } - } + /// + /// Dequeue this instance. + /// + public V Dequeue() + { + if (_heap.IsEmpty) + { + throw new ArgumentOutOfRangeException("Queue is empty."); } + var highest = _heap.Peek(); - /// - /// Clear this priority queue. - /// - public void Clear() + // Decrement the key's counter + _keysMap[highest.Key] = _keysMap[highest.Key] - 1; + if (_keysMap[highest.Key] == 0) { - _heap.Clear(); + _keysMap.Remove(highest.Key); } - ///// - ///// Removes the node that has the specified key. - ///// - ///// Key. - //public void Remove(K key) - //{ - // if (_heap.IsEmpty) - // { - // throw new ArgumentOutOfRangeException ("Queue is empty."); - // } - // - // var keyComparer = Comparer.Default; - // - // Predicate> match = - // new Predicate> ( - // item => keyComparer.Compare(item.Key, key) == 0); - // - // _heap.RemoveAll (match); - //} - - - ///// - ///// Removes the node that has the specified key and value. - ///// - ///// Key. - ///// Value. - //public void Remove(K key, V value) - //{ - // if (_heap.IsEmpty) - // { - // throw new ArgumentOutOfRangeException ("Queue is empty."); - // } - // - // var keyComparer = Comparer.Default; - // var valueComparer = Comparer.Default; - // - // Predicate> match = - // new Predicate> ( - // item => - // keyComparer.Compare(item.Key, key) == 0 && - // valueComparer.Compare(item.Value, value) == 0); - // - // _heap.RemoveAll (match); - //} + _heap.RemoveMax(); + return highest.Value; } - /// - /// The Priority-queue node. + /// Sets the priority. /// - /// Node's Key type - /// Node's Value type - /// Node's Priority type - public class PriorityQueueNode : IComparable> where P : IComparable

+ /// Key. + /// New priority. + public void SetPriority(K key, P newPriority) { - public K Key { get; set; } - public V Value { get; set; } - public P Priority { get; set; } - - public PriorityQueueNode() : this(default, default, default) { } - - public PriorityQueueNode(K key, V value, P priority) + // Handle boundaries errors + if (_heap.IsEmpty) { - Key = key; - Value = value; - Priority = priority; + throw new ArgumentOutOfRangeException("Queue is empty."); } - public int CompareTo(PriorityQueueNode other) + if (!_keysMap.ContainsKey(key)) { - if (other == null) - return -1; + throw new KeyNotFoundException(); + } + + var keyComparer = Comparer.Default; - return Priority.CompareTo(other.Priority); + for (int i = 0; i < _heap.Count; ++i) + { + if (keyComparer.Compare(_heap[i].Key, key) == 0) + { + _heap[i].Priority = newPriority; + break; + } } - }//end-of-node-class + } ///

- /// Keyed Priority-queue node comparer. + /// Clear this priority queue. /// - public class PriorityQueueNodeComparer : IComparer> where P : IComparable

+ public void Clear() { - public int Compare(PriorityQueueNode first, PriorityQueueNode second) - { - return first.Priority.CompareTo(second.Priority); - } - }//end-of-comparer-class + _heap.Clear(); + } + /////

+ ///// Removes the node that has the specified key. + ///// + ///// Key. + //public void Remove(K key) + //{ + // if (_heap.IsEmpty) + // { + // throw new ArgumentOutOfRangeException ("Queue is empty."); + // } + // + // var keyComparer = Comparer.Default; + // + // Predicate> match = + // new Predicate> ( + // item => keyComparer.Compare(item.Key, key) == 0); + // + // _heap.RemoveAll (match); + //} + + + ///// + ///// Removes the node that has the specified key and value. + ///// + ///// Key. + ///// Value. + //public void Remove(K key, V value) + //{ + // if (_heap.IsEmpty) + // { + // throw new ArgumentOutOfRangeException ("Queue is empty."); + // } + // + // var keyComparer = Comparer.Default; + // var valueComparer = Comparer.Default; + // + // Predicate> match = + // new Predicate> ( + // item => + // keyComparer.Compare(item.Key, key) == 0 && + // valueComparer.Compare(item.Value, value) == 0); + // + // _heap.RemoveAll (match); + //} } + + + +/// +/// The Priority-queue node. +/// +/// Node's Key type +/// Node's Value type +/// Node's Priority type +public class PriorityQueueNode : IComparable> where P : IComparable

+{ + public K Key { get; set; } + public V Value { get; set; } + public P Priority { get; set; } + + public PriorityQueueNode() : this(default, default, default) { } + + public PriorityQueueNode(K key, V value, P priority) + { + Key = key; + Value = value; + Priority = priority; + } + + public int CompareTo(PriorityQueueNode other) + { + if (other == null) + return -1; + + return Priority.CompareTo(other.Priority); + } +}//end-of-node-class + + +///

+/// Keyed Priority-queue node comparer. +/// +public class PriorityQueueNodeComparer : IComparer> where P : IComparable

+{ + public int Compare(PriorityQueueNode first, PriorityQueueNode second) + { + return first.Priority.CompareTo(second.Priority); + } +}//end-of-comparer-class \ No newline at end of file diff --git a/DataStructures/Heaps/MinPriorityQueue.cs b/DataStructures/Heaps/MinPriorityQueue.cs index 294c3f03..6e59f1af 100644 --- a/DataStructures/Heaps/MinPriorityQueue.cs +++ b/DataStructures/Heaps/MinPriorityQueue.cs @@ -3,281 +3,279 @@ using DataStructures.Common; -namespace DataStructures.Heaps +namespace DataStructures.Heaps; + +///

+/// Implements the Priority Queue Data Structure. +/// Node's Value type +/// Node's Priority type +/// +public class MinPriorityQueue + where TKey : IComparable + where TPriority : IComparable { /// - /// Implements the Priority Queue Data Structure. - /// Node's Value type - /// Node's Priority type + /// Instance variables /// - public class MinPriorityQueue - where TKey : IComparable - where TPriority : IComparable - { - /// - /// Instance variables - /// - // A dictionary of keys and number of copies in the heap. - private Dictionary _keys { get; set; } + // A dictionary of keys and number of copies in the heap. + private Dictionary _keys { get; set; } + + // The internal heap. + private BinaryMinHeap> _heap { get; set; } - // The internal heap. - private BinaryMinHeap> _heap { get; set; } + // The priorities value comparer. + private Comparer> _priorityComparer { get; set; } - // The priorities value comparer. - private Comparer> _priorityComparer { get; set; } + /// + /// CONSTRUCTOR + /// + public MinPriorityQueue() : this(0, null) { } - /// - /// CONSTRUCTOR - /// - public MinPriorityQueue() : this(0, null) { } + public MinPriorityQueue(uint capacity) : this(capacity, null) { } + + public MinPriorityQueue(uint capacity, Comparer> priorityComparer) + { + // Make sure the TPriority is elegible for a priority + if (!_validPriorityType()) + throw new NotSupportedException("The priority type is not supported."); + + // Initialize comparer + if (priorityComparer == null) + _priorityComparer = Comparer>.Default; + else + _priorityComparer = priorityComparer; + + // Initialize. + _keys = new Dictionary(); + _heap = new BinaryMinHeap>((int)capacity, _priorityComparer); + } - public MinPriorityQueue(uint capacity) : this(capacity, null) { } - public MinPriorityQueue(uint capacity, Comparer> priorityComparer) + /// + /// Validates the Type of TPriority. Returns true if acceptable, false otherwise. + /// + /// + private bool _validPriorityType() + { + bool isValid = false; + TypeCode typeCode = Type.GetTypeCode(typeof(TPriority)); + + switch (typeCode) { - // Make sure the TPriority is elegible for a priority - if (!_validPriorityType()) - throw new NotSupportedException("The priority type is not supported."); - - // Initialize comparer - if (priorityComparer == null) - _priorityComparer = Comparer>.Default; - else - _priorityComparer = priorityComparer; - - // Initialize. - _keys = new Dictionary(); - _heap = new BinaryMinHeap>((int)capacity, _priorityComparer); + //case TypeCode.DateTime: + case TypeCode.Byte: + case TypeCode.Char: + case TypeCode.Decimal: + case TypeCode.Double: + case TypeCode.Int16: + case TypeCode.Int32: + case TypeCode.Int64: + case TypeCode.SByte: + case TypeCode.Single: + case TypeCode.UInt16: + case TypeCode.UInt32: + case TypeCode.UInt64: + isValid = true; + break; + default: + isValid = false; + break; } + return isValid; + } + - /// - /// Validates the Type of TPriority. Returns true if acceptable, false otherwise. - /// - /// - private bool _validPriorityType() + /// + /// Returns the count of elements in the queue. + /// + public int Count => _heap.Count; + + /// + /// Checks if the queue is empty + /// + public bool IsEmpty => _heap.IsEmpty; + + /// + /// Get the default max priority, if set, raises an exception if not set. + /// Also sets the default max priority. + /// + public TPriority DefaultMaxPriority + { + get { - bool isValid = false; + object maxValue = default(TPriority); TypeCode typeCode = Type.GetTypeCode(typeof(TPriority)); - switch (typeCode) { - //case TypeCode.DateTime: case TypeCode.Byte: + maxValue = byte.MaxValue; + break; case TypeCode.Char: + maxValue = char.MaxValue; + break; + case TypeCode.DateTime: + maxValue = DateTime.MaxValue; + break; case TypeCode.Decimal: + maxValue = decimal.MaxValue; + break; case TypeCode.Double: + maxValue = decimal.MaxValue; + break; case TypeCode.Int16: + maxValue = short.MaxValue; + break; case TypeCode.Int32: + maxValue = int.MaxValue; + break; case TypeCode.Int64: + maxValue = long.MaxValue; + break; case TypeCode.SByte: + maxValue = sbyte.MaxValue; + break; case TypeCode.Single: + maxValue = float.MaxValue; + break; case TypeCode.UInt16: + maxValue = ushort.MaxValue; + break; case TypeCode.UInt32: - case TypeCode.UInt64: - isValid = true; + maxValue = uint.MaxValue; break; - default: - isValid = false; + case TypeCode.UInt64: + maxValue = ulong.MaxValue; break; } - return isValid; - } - - - /// - /// Returns the count of elements in the queue. - /// - public int Count => _heap.Count; - - /// - /// Checks if the queue is empty - /// - public bool IsEmpty => _heap.IsEmpty; - - /// - /// Get the default max priority, if set, raises an exception if not set. - /// Also sets the default max priority. - /// - public TPriority DefaultMaxPriority - { - get - { - object maxValue = default(TPriority); - TypeCode typeCode = Type.GetTypeCode(typeof(TPriority)); - switch (typeCode) - { - case TypeCode.Byte: - maxValue = byte.MaxValue; - break; - case TypeCode.Char: - maxValue = char.MaxValue; - break; - case TypeCode.DateTime: - maxValue = DateTime.MaxValue; - break; - case TypeCode.Decimal: - maxValue = decimal.MaxValue; - break; - case TypeCode.Double: - maxValue = decimal.MaxValue; - break; - case TypeCode.Int16: - maxValue = short.MaxValue; - break; - case TypeCode.Int32: - maxValue = int.MaxValue; - break; - case TypeCode.Int64: - maxValue = long.MaxValue; - break; - case TypeCode.SByte: - maxValue = sbyte.MaxValue; - break; - case TypeCode.Single: - maxValue = float.MaxValue; - break; - case TypeCode.UInt16: - maxValue = ushort.MaxValue; - break; - case TypeCode.UInt32: - maxValue = uint.MaxValue; - break; - case TypeCode.UInt64: - maxValue = ulong.MaxValue; - break; - } - - return (TPriority)maxValue; - } - } - - /// - /// Returns the highest priority element. - /// - /// The at highest priority. - public TKey PeekAtMinPriority() - { - if (_heap.IsEmpty) - { - throw new ArgumentOutOfRangeException("Queue is empty."); - } - - return _heap.Peek().Key; - } - - /// - /// Checks for the existence of a key in the queue - /// - public bool Contains(TKey key) - { - return _keys.ContainsKey(key); + return (TPriority)maxValue; } + } - /// - /// Enqueue the specified key, with the default-max-priority value. - /// - public void Enqueue(TKey key) + /// + /// Returns the highest priority element. + /// + /// The at highest priority. + public TKey PeekAtMinPriority() + { + if (_heap.IsEmpty) { - Enqueue(key, DefaultMaxPriority); + throw new ArgumentOutOfRangeException("Queue is empty."); } - /// - /// Enqueue the specified key, value and priority. - /// - /// Value. - /// Priority. - public void Enqueue(TKey key, TPriority priority) - { - var newNode = new PriorityQueueNode(key, priority); - _heap.Add(newNode); + return _heap.Peek().Key; + } - if (_keys.ContainsKey(key)) - _keys[key] += 1; - else - _keys.Add(key, 1); - } + /// + /// Checks for the existence of a key in the queue + /// + public bool Contains(TKey key) + { + return _keys.ContainsKey(key); + } - /// - /// Dequeue this instance. - /// - public TKey DequeueMin() - { - if (_heap.IsEmpty) - throw new ArgumentOutOfRangeException("Queue is empty."); + /// + /// Enqueue the specified key, with the default-max-priority value. + /// + public void Enqueue(TKey key) + { + Enqueue(key, DefaultMaxPriority); + } - var key = _heap.ExtractMin().Key; + /// + /// Enqueue the specified key, value and priority. + /// + /// Value. + /// Priority. + public void Enqueue(TKey key, TPriority priority) + { + var newNode = new PriorityQueueNode(key, priority); + _heap.Add(newNode); - // Decrease the key count. - _keys[key] = _keys[key] - 1; + if (_keys.ContainsKey(key)) + _keys[key] += 1; + else + _keys.Add(key, 1); + } - // Remove key if its count is zero - if (_keys[key] == 0) - _keys.Remove(key); + /// + /// Dequeue this instance. + /// + public TKey DequeueMin() + { + if (_heap.IsEmpty) + throw new ArgumentOutOfRangeException("Queue is empty."); - return key; - } + var key = _heap.ExtractMin().Key; - /// - /// Sets the priority. - /// - public void UpdatePriority(TKey key, TPriority newPriority) - { - // Handle boundaries errors - if (_heap.IsEmpty) - throw new ArgumentOutOfRangeException("Queue is empty."); - if (!_keys.ContainsKey(key)) - throw new KeyNotFoundException(); - - int i; - for (i = 0; i < _heap.Count; ++i) - if (_heap[i].Key.IsEqualTo(key)) - break; + // Decrease the key count. + _keys[key] = _keys[key] - 1; - _heap[i].Priority = newPriority; - } + // Remove key if its count is zero + if (_keys[key] == 0) + _keys.Remove(key); - /// - /// Clear this priority queue. - /// - public void Clear() - { - _heap.Clear(); - _keys.Clear(); - } + return key; } - + /// + /// Sets the priority. + /// + public void UpdatePriority(TKey key, TPriority newPriority) + { + // Handle boundaries errors + if (_heap.IsEmpty) + throw new ArgumentOutOfRangeException("Queue is empty."); + if (!_keys.ContainsKey(key)) + throw new KeyNotFoundException(); + + int i; + for (i = 0; i < _heap.Count; ++i) + if (_heap[i].Key.IsEqualTo(key)) + break; + + _heap[i].Priority = newPriority; + } /// - /// The Priority-queue node. + /// Clear this priority queue. /// - /// Node's Key type - /// Node's Value type - public class PriorityQueueNode : IComparable> - where TKey : IComparable - where TPriority : IComparable + public void Clear() { - public TKey Key { get; set; } - public TPriority Priority { get; set; } + _heap.Clear(); + _keys.Clear(); + } +} - public PriorityQueueNode() : this(default, default) { } - public PriorityQueueNode(TKey value, TPriority priority) - { - Key = value; - Priority = priority; - } - public int CompareTo(PriorityQueueNode other) - { - if (other == null) - return -1; +/// +/// The Priority-queue node. +/// +/// Node's Key type +/// Node's Value type +public class PriorityQueueNode : IComparable> + where TKey : IComparable + where TPriority : IComparable +{ + public TKey Key { get; set; } + public TPriority Priority { get; set; } - return Priority.CompareTo(other.Priority); - } - }//end-of-node-class + public PriorityQueueNode() : this(default, default) { } -} + public PriorityQueueNode(TKey value, TPriority priority) + { + Key = value; + Priority = priority; + } + + public int CompareTo(PriorityQueueNode other) + { + if (other == null) + return -1; + + return Priority.CompareTo(other.Priority); + } +}//end-of-node-class \ No newline at end of file diff --git a/DataStructures/Lists/ArrayList.cs b/DataStructures/Lists/ArrayList.cs index 9d174a40..e66e4653 100644 --- a/DataStructures/Lists/ArrayList.cs +++ b/DataStructures/Lists/ArrayList.cs @@ -2,810 +2,808 @@ using System.Linq; using System.Collections.Generic; -namespace DataStructures.Lists +namespace DataStructures.Lists; + +/// +/// The Array-Based List Data Structure. +/// +public class ArrayList : IEnumerable { /// - /// The Array-Based List Data Structure. + /// Instance variables. /// - public class ArrayList : IEnumerable - { - /// - /// Instance variables. - /// - // This sets the default maximum array length to refer to MAXIMUM_ARRAY_LENGTH_x64 - // Set the flag IsMaximumCapacityReached to false - bool DefaultMaxCapacityIsX64 = true; - bool IsMaximumCapacityReached = false; + // This sets the default maximum array length to refer to MAXIMUM_ARRAY_LENGTH_x64 + // Set the flag IsMaximumCapacityReached to false + bool DefaultMaxCapacityIsX64 = true; + bool IsMaximumCapacityReached = false; - // The C# Maximum Array Length (before encountering overflow) - // Reference: http://referencesource.microsoft.com/#mscorlib/system/array.cs,2d2b551eabe74985 - public const int MAXIMUM_ARRAY_LENGTH_x64 = 0X7FEFFFFF; //x64 - public const int MAXIMUM_ARRAY_LENGTH_x86 = 0x8000000; //x86 + // The C# Maximum Array Length (before encountering overflow) + // Reference: http://referencesource.microsoft.com/#mscorlib/system/array.cs,2d2b551eabe74985 + public const int MAXIMUM_ARRAY_LENGTH_x64 = 0X7FEFFFFF; //x64 + public const int MAXIMUM_ARRAY_LENGTH_x86 = 0x8000000; //x86 - // This is used as a default empty list initialization. - private readonly T[] _emptyArray = new T[0]; + // This is used as a default empty list initialization. + private readonly T[] _emptyArray = new T[0]; - // The default capacity to resize to, when a minimum is lower than 5. - private const int _defaultCapacity = 8; + // The default capacity to resize to, when a minimum is lower than 5. + private const int _defaultCapacity = 8; - // The internal array of elements. - // NOT A PROPERTY. - private T[] _collection; + // The internal array of elements. + // NOT A PROPERTY. + private T[] _collection; - // This keeps track of the number of elements added to the array. - // Serves as an index of last item + 1. - private int _size { get; set; } + // This keeps track of the number of elements added to the array. + // Serves as an index of last item + 1. + private int _size { get; set; } - /// - /// CONSTRUCTORS - /// - public ArrayList() : this(capacity: 0) { } + /// + /// CONSTRUCTORS + /// + public ArrayList() : this(capacity: 0) { } - public ArrayList(int capacity) + public ArrayList(int capacity) + { + if (capacity < 0) { - if (capacity < 0) - { - throw new ArgumentOutOfRangeException(); - } - - if (capacity == 0) - { - _collection = _emptyArray; - } - else - { - _collection = new T[capacity]; - } + throw new ArgumentOutOfRangeException(); + } - // Zerofiy the _size; - _size = 0; + if (capacity == 0) + { + _collection = _emptyArray; + } + else + { + _collection = new T[capacity]; } + // Zerofiy the _size; + _size = 0; + } - /// - /// Ensures the capacity. - /// - /// Minimum capacity. - private void _ensureCapacity(int minCapacity) - { - // If the length of the inner collection is less than the minCapacity - // ... and if the maximum capacity wasn't reached yet, - // ... then maximize the inner collection. - if (_collection.Length < minCapacity && IsMaximumCapacityReached == false) - { - int newCapacity = _collection.Length == 0 ? _defaultCapacity : _collection.Length * 2; - // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. - // Note that this check works even when _items.Length overflowed thanks to the (uint) cast - int maxCapacity = DefaultMaxCapacityIsX64 == true ? MAXIMUM_ARRAY_LENGTH_x64 : MAXIMUM_ARRAY_LENGTH_x86; + /// + /// Ensures the capacity. + /// + /// Minimum capacity. + private void _ensureCapacity(int minCapacity) + { + // If the length of the inner collection is less than the minCapacity + // ... and if the maximum capacity wasn't reached yet, + // ... then maximize the inner collection. + if (_collection.Length < minCapacity && IsMaximumCapacityReached == false) + { + int newCapacity = _collection.Length == 0 ? _defaultCapacity : _collection.Length * 2; - if (newCapacity < minCapacity) - newCapacity = minCapacity; + // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. + // Note that this check works even when _items.Length overflowed thanks to the (uint) cast + int maxCapacity = DefaultMaxCapacityIsX64 == true ? MAXIMUM_ARRAY_LENGTH_x64 : MAXIMUM_ARRAY_LENGTH_x86; - if (newCapacity >= maxCapacity) - { - newCapacity = maxCapacity - 1; - IsMaximumCapacityReached = true; - } + if (newCapacity < minCapacity) + newCapacity = minCapacity; - _resizeCapacity(newCapacity); + if (newCapacity >= maxCapacity) + { + newCapacity = maxCapacity - 1; + IsMaximumCapacityReached = true; } + + _resizeCapacity(newCapacity); } + } - /// - /// Resizes the collection to a new maximum number of capacity. - /// - /// New capacity. - private void _resizeCapacity(int newCapacity) + /// + /// Resizes the collection to a new maximum number of capacity. + /// + /// New capacity. + private void _resizeCapacity(int newCapacity) + { + if (newCapacity != _collection.Length && newCapacity > _size) { - if (newCapacity != _collection.Length && newCapacity > _size) + try { - try + Array.Resize(ref _collection, newCapacity); + } + catch (OutOfMemoryException) + { + if (DefaultMaxCapacityIsX64 == true) { - Array.Resize(ref _collection, newCapacity); + DefaultMaxCapacityIsX64 = false; + _ensureCapacity(newCapacity); } - catch (OutOfMemoryException) - { - if (DefaultMaxCapacityIsX64 == true) - { - DefaultMaxCapacityIsX64 = false; - _ensureCapacity(newCapacity); - } - throw; - } + throw; } } + } - /// - /// Gets the the number of elements in list. - /// - /// Int. - public int Count => _size; + /// + /// Gets the the number of elements in list. + /// + /// Int. + public int Count => _size; - /// - /// Returns the capacity of list, which is the total number of slots. - /// - public int Capacity => _collection.Length; + /// + /// Returns the capacity of list, which is the total number of slots. + /// + public int Capacity => _collection.Length; - /// - /// Determines whether this list is empty. - /// - /// true if list is empty; otherwise, false. - public bool IsEmpty => Count == 0; + /// + /// Determines whether this list is empty. + /// + /// true if list is empty; otherwise, false. + public bool IsEmpty => Count == 0; - /// - /// Gets the first element in the list. - /// - /// The first. - public T First + /// + /// Gets the first element in the list. + /// + /// The first. + public T First + { + get { - get + if (Count == 0) { - if (Count == 0) - { - throw new IndexOutOfRangeException("List is empty."); - } - - return _collection[0]; + throw new IndexOutOfRangeException("List is empty."); } + + return _collection[0]; } + } - /// - /// Gets the last element in the list. - /// - /// The last. - public T Last + /// + /// Gets the last element in the list. + /// + /// The last. + public T Last + { + get { - get + if (IsEmpty) { - if (IsEmpty) - { - throw new IndexOutOfRangeException("List is empty."); - } - - return _collection[Count - 1]; + throw new IndexOutOfRangeException("List is empty."); } + + return _collection[Count - 1]; } + } - /// - /// Gets or sets the item at the specified index. - /// example: var a = list[0]; - /// example: list[0] = 1; - /// - /// Index. - public T this[int index] + /// + /// Gets or sets the item at the specified index. + /// example: var a = list[0]; + /// example: list[0] = 1; + /// + /// Index. + public T this[int index] + { + get { - get + if (index < 0 || index >= _size) { - if (index < 0 || index >= _size) - { - throw new IndexOutOfRangeException(); - } - - return _collection[index]; + throw new IndexOutOfRangeException(); } - set - { - if (index < 0 || index >= _size) - { - throw new IndexOutOfRangeException(); - } - - _collection[index] = value; - } + return _collection[index]; } - - /// - /// Add the specified dataItem to list. - /// - /// Data item. - public void Add(T dataItem) + set { - if (_size == _collection.Length) + if (index < 0 || index >= _size) { - _ensureCapacity(_size + 1); + throw new IndexOutOfRangeException(); } - _collection[_size++] = dataItem; + _collection[index] = value; } + } - /// - /// Adds an enumerable collection of items to list. - /// - /// - public void AddRange(IEnumerable elements) + /// + /// Add the specified dataItem to list. + /// + /// Data item. + public void Add(T dataItem) + { + if (_size == _collection.Length) { - if (elements == null) - throw new ArgumentNullException(); + _ensureCapacity(_size + 1); + } - // make sure the size won't overflow by adding the range - if ((uint)_size + elements.Count() > MAXIMUM_ARRAY_LENGTH_x64) - throw new OverflowException(); + _collection[_size++] = dataItem; + } - // grow the internal collection once to avoid doing multiple redundant grows - if (elements.Any()) - { - _ensureCapacity(_size + elements.Count()); - foreach (var element in elements) - Add(element); - } + /// + /// Adds an enumerable collection of items to list. + /// + /// + public void AddRange(IEnumerable elements) + { + if (elements == null) + throw new ArgumentNullException(); + + // make sure the size won't overflow by adding the range + if ((uint)_size + elements.Count() > MAXIMUM_ARRAY_LENGTH_x64) + throw new OverflowException(); + + // grow the internal collection once to avoid doing multiple redundant grows + if (elements.Any()) + { + _ensureCapacity(_size + elements.Count()); + + foreach (var element in elements) + Add(element); } + } - /// - /// Adds an element to list repeatedly for a specified count. - /// - public void AddRepeatedly(T value, int count) + /// + /// Adds an element to list repeatedly for a specified count. + /// + public void AddRepeatedly(T value, int count) + { + if (count < 0) + throw new ArgumentOutOfRangeException(); + + if ((uint)_size + count > MAXIMUM_ARRAY_LENGTH_x64) + throw new OverflowException(); + + // grow the internal collection once to avoid doing multiple redundant grows + if (count > 0) { - if (count < 0) - throw new ArgumentOutOfRangeException(); + _ensureCapacity(_size + count); - if ((uint)_size + count > MAXIMUM_ARRAY_LENGTH_x64) - throw new OverflowException(); + for (int i = 0; i < count; i++) + Add(value); + } + } - // grow the internal collection once to avoid doing multiple redundant grows - if (count > 0) - { - _ensureCapacity(_size + count); - for (int i = 0; i < count; i++) - Add(value); - } + /// + /// Inserts a new element at an index. Doesn't override the cell at index. + /// + /// Data item to insert. + /// Index of insertion. + public void InsertAt(T dataItem, int index) + { + if (index < 0 || index > _size) + { + throw new IndexOutOfRangeException("Please provide a valid index."); } + // If the inner array is full and there are no extra spaces, + // ... then maximize it's capacity to a minimum of _size + 1. + if (_size == _collection.Length) + { + _ensureCapacity(_size + 1); + } - /// - /// Inserts a new element at an index. Doesn't override the cell at index. - /// - /// Data item to insert. - /// Index of insertion. - public void InsertAt(T dataItem, int index) + // If the index is not "at the end", then copy the elements of the array + // ... between the specified index and the last index to the new range (index + 1, _size); + // The cell at "index" will become available. + if (index < _size) { - if (index < 0 || index > _size) - { - throw new IndexOutOfRangeException("Please provide a valid index."); - } + Array.Copy(_collection, index, _collection, index + 1, _size - index); + } - // If the inner array is full and there are no extra spaces, - // ... then maximize it's capacity to a minimum of _size + 1. - if (_size == _collection.Length) - { - _ensureCapacity(_size + 1); - } + // Write the dataItem to the available cell. + _collection[index] = dataItem; - // If the index is not "at the end", then copy the elements of the array - // ... between the specified index and the last index to the new range (index + 1, _size); - // The cell at "index" will become available. - if (index < _size) - { - Array.Copy(_collection, index, _collection, index + 1, _size - index); - } + // Increase the size. + _size++; + } - // Write the dataItem to the available cell. - _collection[index] = dataItem; - // Increase the size. - _size++; + /// + /// Removes the specified dataItem from list. + /// + /// >True if removed successfully, false otherwise. + /// Data item. + public bool Remove(T dataItem) + { + int index = IndexOf(dataItem); + + if (index >= 0) + { + RemoveAt(index); + return true; } + return false; + } + - /// - /// Removes the specified dataItem from list. - /// - /// >True if removed successfully, false otherwise. - /// Data item. - public bool Remove(T dataItem) + /// + /// Removes the list element at the specified index. + /// + /// Index of element. + public void RemoveAt(int index) + { + if (index < 0 || index >= _size) { - int index = IndexOf(dataItem); + throw new IndexOutOfRangeException("Please pass a valid index."); + } - if (index >= 0) - { - RemoveAt(index); - return true; - } + // Decrease the size by 1, to avoid doing Array.Copy if the element is to be removed from the tail of list. + _size--; - return false; + // If the index is still less than size, perform an Array.Copy to override the cell at index. + // This operation is O(N), where N = size - index. + if (index < _size) + { + Array.Copy(_collection, index + 1, _collection, index, _size - index); } + // Reset the writable cell to the default value of type T. + _collection[_size] = default; + } + - /// - /// Removes the list element at the specified index. - /// - /// Index of element. - public void RemoveAt(int index) + /// + /// Clear this instance. + /// + public void Clear() + { + if (_size > 0) { - if (index < 0 || index >= _size) - { - throw new IndexOutOfRangeException("Please pass a valid index."); - } + _size = 0; + Array.Clear(_collection, 0, _size); + _collection = _emptyArray; + } + } - // Decrease the size by 1, to avoid doing Array.Copy if the element is to be removed from the tail of list. - _size--; - // If the index is still less than size, perform an Array.Copy to override the cell at index. - // This operation is O(N), where N = size - index. - if (index < _size) - { - Array.Copy(_collection, index + 1, _collection, index, _size - index); - } + /// + /// Resize the List to a new size. + /// + public void Resize(int newSize) + { + Resize(newSize, default); + } - // Reset the writable cell to the default value of type T. - _collection[_size] = default; - } + /// + /// Resize the list to a new size. + /// + public void Resize(int newSize, T defaultValue) + { + int currentSize = Count; - /// - /// Clear this instance. - /// - public void Clear() + if (newSize < currentSize) { - if (_size > 0) - { - _size = 0; - Array.Clear(_collection, 0, _size); - _collection = _emptyArray; - } + _ensureCapacity(newSize); + } + else if (newSize > currentSize) + { + // Optimisation step. + // This is just to avoid multiple automatic capacity changes. + if (newSize > _collection.Length) + _ensureCapacity(newSize + 1); + + AddRange(Enumerable.Repeat(defaultValue, newSize - currentSize)); } + } + + + /// + /// Reverses this list. + /// + public void Reverse() + { + Reverse(0, _size); + } - /// - /// Resize the List to a new size. - /// - public void Resize(int newSize) + /// + /// Reverses the order of a number of elements. Starting a specific index. + /// + /// Start index. + /// Count of elements to reverse. + public void Reverse(int startIndex, int count) + { + // Handle the bounds of startIndex + if (startIndex < 0 || startIndex >= _size) { - Resize(newSize, default); + throw new IndexOutOfRangeException("Please pass a valid starting index."); } - - /// - /// Resize the list to a new size. - /// - public void Resize(int newSize, T defaultValue) + // Handle the bounds of count and startIndex with respect to _size. + if (count < 0 || startIndex > _size - count) { - int currentSize = Count; + throw new ArgumentOutOfRangeException(); + } - if (newSize < currentSize) - { - _ensureCapacity(newSize); - } - else if (newSize > currentSize) - { - // Optimisation step. - // This is just to avoid multiple automatic capacity changes. - if (newSize > _collection.Length) - _ensureCapacity(newSize + 1); + // Use Array.Reverse + // Running complexity is better than O(N). But unknown. + // Array.Reverse uses the closed-source function TrySZReverse. + Array.Reverse(_collection, startIndex, count); + } - AddRange(Enumerable.Repeat(defaultValue, newSize - currentSize)); - } - } + /// + /// For each element in list, apply the specified action to it. + /// + /// Typed Action. + public void ForEach(Action action) + { + // Null actions are not allowed. + if (action == null) + { + throw new ArgumentNullException(); + } - /// - /// Reverses this list. - /// - public void Reverse() + for (int i = 0; i < _size; ++i) { - Reverse(0, _size); + action(_collection[i]); } + } - /// - /// Reverses the order of a number of elements. Starting a specific index. - /// - /// Start index. - /// Count of elements to reverse. - public void Reverse(int startIndex, int count) + /// + /// Checks whether the list contains the specified dataItem. + /// + /// True if list contains the dataItem, false otherwise. + /// Data item. + public bool Contains(T dataItem) + { + // Null-value check + if ((Object)dataItem == null) { - // Handle the bounds of startIndex - if (startIndex < 0 || startIndex >= _size) + for (int i = 0; i < _size; ++i) { - throw new IndexOutOfRangeException("Please pass a valid starting index."); + if ((Object)_collection[i] == null) return true; } + } + else + { + // Construct a default equality comparer for this Type T + // Use it to get the equal match for the dataItem + EqualityComparer comparer = EqualityComparer.Default; - // Handle the bounds of count and startIndex with respect to _size. - if (count < 0 || startIndex > _size - count) + for (int i = 0; i < _size; ++i) { - throw new ArgumentOutOfRangeException(); + if (comparer.Equals(_collection[i], dataItem)) return true; } - - // Use Array.Reverse - // Running complexity is better than O(N). But unknown. - // Array.Reverse uses the closed-source function TrySZReverse. - Array.Reverse(_collection, startIndex, count); } + return false; + } + - /// - /// For each element in list, apply the specified action to it. - /// - /// Typed Action. - public void ForEach(Action action) + /// + /// Checks whether the list contains the specified dataItem. + /// + /// True if list contains the dataItem, false otherwise. + /// Data item. + /// The Equality Comparer object. + public bool Contains(T dataItem, IEqualityComparer comparer) + { + // Null comparers are not allowed. + if (comparer == null) { - // Null actions are not allowed. - if (action == null) - { - throw new ArgumentNullException(); - } + throw new ArgumentNullException(); + } + // Null-value check + if ((Object)dataItem == null) + { for (int i = 0; i < _size; ++i) { - action(_collection[i]); + if ((Object)_collection[i] == null) return true; } } - - - /// - /// Checks whether the list contains the specified dataItem. - /// - /// True if list contains the dataItem, false otherwise. - /// Data item. - public bool Contains(T dataItem) + else { - // Null-value check - if ((Object)dataItem == null) + for (int i = 0; i < _size; ++i) { - for (int i = 0; i < _size; ++i) - { - if ((Object)_collection[i] == null) return true; - } + if (comparer.Equals(_collection[i], dataItem)) return true; } - else - { - // Construct a default equality comparer for this Type T - // Use it to get the equal match for the dataItem - EqualityComparer comparer = EqualityComparer.Default; + } - for (int i = 0; i < _size; ++i) - { - if (comparer.Equals(_collection[i], dataItem)) return true; - } - } + return false; + } - return false; - } + /// + /// Checks whether an item specified via a Predicate function exists exists in list. + /// + /// Match predicate. + public bool Exists(Predicate searchMatch) + { + // Use the FindIndex to look through the collection + // If the returned index != -1 then it does exist, otherwise it doesn't. + return FindIndex(searchMatch) != -1; + } - /// - /// Checks whether the list contains the specified dataItem. - /// - /// True if list contains the dataItem, false otherwise. - /// Data item. - /// The Equality Comparer object. - public bool Contains(T dataItem, IEqualityComparer comparer) - { - // Null comparers are not allowed. - if (comparer == null) - { - throw new ArgumentNullException(); - } - // Null-value check - if ((Object)dataItem == null) - { - for (int i = 0; i < _size; ++i) - { - if ((Object)_collection[i] == null) return true; - } - } - else - { - for (int i = 0; i < _size; ++i) - { - if (comparer.Equals(_collection[i], dataItem)) return true; - } - } + /// + /// Finds the index of the element that matches the predicate. + /// + /// The index of element if found, -1 otherwise. + /// Match predicate. + public int FindIndex(Predicate searchMatch) + { + return FindIndex(0, _size, searchMatch); + } - return false; - } + + /// + /// Finds the index of the element that matches the predicate. + /// + /// The index of the element if found, -1 otherwise. + /// Starting index to search from. + /// Match predicate. + public int FindIndex(int startIndex, Predicate searchMatch) + { + return FindIndex(startIndex, _size - startIndex, searchMatch); + } - /// - /// Checks whether an item specified via a Predicate function exists exists in list. - /// - /// Match predicate. - public bool Exists(Predicate searchMatch) + /// + /// Finds the index of the first element that matches the given predicate function. + /// + /// The index of element if found, -1 if not found. + /// Starting index of search. + /// Count of elements to search through. + /// Match predicate function. + public int FindIndex(int startIndex, int count, Predicate searchMatch) + { + // Check bound of startIndex + if (startIndex < 0 || startIndex > _size) { - // Use the FindIndex to look through the collection - // If the returned index != -1 then it does exist, otherwise it doesn't. - return FindIndex(searchMatch) != -1; + throw new IndexOutOfRangeException("Please pass a valid starting index."); } - - /// - /// Finds the index of the element that matches the predicate. - /// - /// The index of element if found, -1 otherwise. - /// Match predicate. - public int FindIndex(Predicate searchMatch) + // CHeck the bounds of count and startIndex with respect to _size + if (count < 0 || startIndex > _size - count) { - return FindIndex(0, _size, searchMatch); + throw new ArgumentOutOfRangeException(); } - - /// - /// Finds the index of the element that matches the predicate. - /// - /// The index of the element if found, -1 otherwise. - /// Starting index to search from. - /// Match predicate. - public int FindIndex(int startIndex, Predicate searchMatch) + // Null match-predicates are not allowed + if (searchMatch == null) { - return FindIndex(startIndex, _size - startIndex, searchMatch); + throw new ArgumentNullException(); } - - /// - /// Finds the index of the first element that matches the given predicate function. - /// - /// The index of element if found, -1 if not found. - /// Starting index of search. - /// Count of elements to search through. - /// Match predicate function. - public int FindIndex(int startIndex, int count, Predicate searchMatch) + // Start the search + int endIndex = startIndex + count; + for (int index = startIndex; index < endIndex; ++index) { - // Check bound of startIndex - if (startIndex < 0 || startIndex > _size) - { - throw new IndexOutOfRangeException("Please pass a valid starting index."); - } + if (searchMatch(_collection[index]) == true) return index; + } - // CHeck the bounds of count and startIndex with respect to _size - if (count < 0 || startIndex > _size - count) - { - throw new ArgumentOutOfRangeException(); - } + // Not found, return -1 + return -1; + } - // Null match-predicates are not allowed - if (searchMatch == null) - { - throw new ArgumentNullException(); - } - // Start the search - int endIndex = startIndex + count; - for (int index = startIndex; index < endIndex; ++index) - { - if (searchMatch(_collection[index]) == true) return index; - } + /// + /// Returns the index of a given dataItem. + /// + /// Index of element in list. + /// Data item. + public int IndexOf(T dataItem) + { + return IndexOf(dataItem, 0, _size); + } - // Not found, return -1 - return -1; - } + + /// + /// Returns the index of a given dataItem. + /// + /// Index of element in list. + /// Data item. + /// The starting index to search from. + public int IndexOf(T dataItem, int startIndex) + { + return IndexOf(dataItem, startIndex, _size); + } - /// - /// Returns the index of a given dataItem. - /// - /// Index of element in list. - /// Data item. - public int IndexOf(T dataItem) + /// + /// Returns the index of a given dataItem. + /// + /// Index of element in list. + /// Data item. + /// The starting index to search from. + /// Count of elements to search through. + public int IndexOf(T dataItem, int startIndex, int count) + { + // Check the bound of the starting index. + if (startIndex < 0 || (uint)startIndex > (uint)_size) { - return IndexOf(dataItem, 0, _size); + throw new IndexOutOfRangeException("Please pass a valid starting index."); } - - /// - /// Returns the index of a given dataItem. - /// - /// Index of element in list. - /// Data item. - /// The starting index to search from. - public int IndexOf(T dataItem, int startIndex) + // Check the bounds of count and starting index with respect to _size. + if (count < 0 || startIndex > _size - count) { - return IndexOf(dataItem, startIndex, _size); + throw new ArgumentOutOfRangeException(); } + // Everything is cool, start looking for the index + // Use the Array.IndexOf + // Array.IndexOf has a O(n) running time complexity, where: "n = count - size". + // Array.IndexOf uses EqualityComparer.Default to return the index of element which loops + // ... over all the elements in the range [startIndex,count) in the array. + return Array.IndexOf(_collection, dataItem, startIndex, count); + } - /// - /// Returns the index of a given dataItem. - /// - /// Index of element in list. - /// Data item. - /// The starting index to search from. - /// Count of elements to search through. - public int IndexOf(T dataItem, int startIndex, int count) - { - // Check the bound of the starting index. - if (startIndex < 0 || (uint)startIndex > (uint)_size) - { - throw new IndexOutOfRangeException("Please pass a valid starting index."); - } - // Check the bounds of count and starting index with respect to _size. - if (count < 0 || startIndex > _size - count) - { - throw new ArgumentOutOfRangeException(); - } - - // Everything is cool, start looking for the index - // Use the Array.IndexOf - // Array.IndexOf has a O(n) running time complexity, where: "n = count - size". - // Array.IndexOf uses EqualityComparer.Default to return the index of element which loops - // ... over all the elements in the range [startIndex,count) in the array. - return Array.IndexOf(_collection, dataItem, startIndex, count); + /// + /// Find the specified element that matches the Search Predication. + /// + /// Match predicate. + public T Find(Predicate searchMatch) + { + // Null Predicate functions are not allowed. + if (searchMatch == null) + { + throw new ArgumentNullException(); } - - /// - /// Find the specified element that matches the Search Predication. - /// - /// Match predicate. - public T Find(Predicate searchMatch) + // Begin searching, and return the matched element + for (int i = 0; i < _size; ++i) { - // Null Predicate functions are not allowed. - if (searchMatch == null) + if (searchMatch(_collection[i])) { - throw new ArgumentNullException(); + return _collection[i]; } + } + + // Not found, return the default value of the type T. + return default; + } - // Begin searching, and return the matched element - for (int i = 0; i < _size; ++i) - { - if (searchMatch(_collection[i])) - { - return _collection[i]; - } - } - // Not found, return the default value of the type T. - return default; + /// + /// Finds all the elements that match the typed Search Predicate. + /// + /// ArrayList of matched elements. Empty list is returned if not element was found. + /// Match predicate. + public ArrayList FindAll(Predicate searchMatch) + { + // Null Predicate functions are not allowed. + if (searchMatch == null) + { + throw new ArgumentNullException(); } + ArrayList matchedElements = new ArrayList(); - /// - /// Finds all the elements that match the typed Search Predicate. - /// - /// ArrayList of matched elements. Empty list is returned if not element was found. - /// Match predicate. - public ArrayList FindAll(Predicate searchMatch) + // Begin searching, and add the matched elements to the new list. + for (int i = 0; i < _size; ++i) { - // Null Predicate functions are not allowed. - if (searchMatch == null) + if (searchMatch(_collection[i])) { - throw new ArgumentNullException(); + matchedElements.Add(_collection[i]); } + } - ArrayList matchedElements = new ArrayList(); + // Return the new list of elements. + return matchedElements; + } - // Begin searching, and add the matched elements to the new list. - for (int i = 0; i < _size; ++i) - { - if (searchMatch(_collection[i])) - { - matchedElements.Add(_collection[i]); - } - } - // Return the new list of elements. - return matchedElements; + /// + /// Get a range of elements, starting from an index.. + /// + /// The range as ArrayList. + /// Start index to get range from. + /// Count of elements. + public ArrayList GetRange(int startIndex, int count) + { + // Handle the bound errors of startIndex + if (startIndex < 0 || (uint)startIndex > (uint)_size) + { + throw new IndexOutOfRangeException("Please provide a valid starting index."); } - - /// - /// Get a range of elements, starting from an index.. - /// - /// The range as ArrayList. - /// Start index to get range from. - /// Count of elements. - public ArrayList GetRange(int startIndex, int count) + // Handle the bound errors of count and startIndex with respect to _size + if (count < 0 || startIndex > _size - count) { - // Handle the bound errors of startIndex - if (startIndex < 0 || (uint)startIndex > (uint)_size) - { - throw new IndexOutOfRangeException("Please provide a valid starting index."); - } + throw new ArgumentOutOfRangeException(); + } - // Handle the bound errors of count and startIndex with respect to _size - if (count < 0 || startIndex > _size - count) - { - throw new ArgumentOutOfRangeException(); - } + var newArrayList = new ArrayList(count); - var newArrayList = new ArrayList(count); + // Use Array.Copy to quickly copy the contents from this array to the new list's inner array. + Array.Copy(_collection, startIndex, newArrayList._collection, 0, count); - // Use Array.Copy to quickly copy the contents from this array to the new list's inner array. - Array.Copy(_collection, startIndex, newArrayList._collection, 0, count); + // Assign count to the new list's inner _size counter. + newArrayList._size = count; - // Assign count to the new list's inner _size counter. - newArrayList._size = count; + return newArrayList; + } - return newArrayList; - } + /// + /// Return an array version of this list. + /// + /// Array. + public T[] ToArray() + { + T[] newArray = new T[Count]; - /// - /// Return an array version of this list. - /// - /// Array. - public T[] ToArray() + if (Count > 0) { - T[] newArray = new T[Count]; + Array.Copy(_collection, 0, newArray, 0, Count); + } - if (Count > 0) - { - Array.Copy(_collection, 0, newArray, 0, Count); - } + return newArray; + } - return newArray; - } + /// + /// Return an array version of this list. + /// + /// Array. + public List ToList() + { + var newList = new List(Count); - /// - /// Return an array version of this list. - /// - /// Array. - public List ToList() + if (Count > 0) { - var newList = new List(Count); - - if (Count > 0) + for (int i = 0; i < Count; ++i) { - for (int i = 0; i < Count; ++i) - { - newList.Add(_collection[i]); - } + newList.Add(_collection[i]); } - - return newList; } + return newList; + } - /// - /// Return a human readable, multi-line, print-out (string) of this list. - /// - /// The human readable string. - /// If set to true a header with count and Type is added; otherwise, only elements are printed. - public string ToHumanReadable(bool addHeader = false) - { - int i = 0; - string listAsString = string.Empty; - string preLineIndent = addHeader == false ? "" : "\t"; + /// + /// Return a human readable, multi-line, print-out (string) of this list. + /// + /// The human readable string. + /// If set to true a header with count and Type is added; otherwise, only elements are printed. + public string ToHumanReadable(bool addHeader = false) + { + int i = 0; + string listAsString = string.Empty; - for (i = 0; i < Count; ++i) - { - listAsString = String.Format("{0}{1}[{2}] => {3}\r\n", listAsString, preLineIndent, i, _collection[i]); - } + string preLineIndent = addHeader == false ? "" : "\t"; - if (addHeader == true) - { - listAsString = String.Format("ArrayList of count: {0}.\r\n(\r\n{1})", Count, listAsString); - } + for (i = 0; i < Count; ++i) + { + listAsString = String.Format("{0}{1}[{2}] => {3}\r\n", listAsString, preLineIndent, i, _collection[i]); + } - return listAsString; + if (addHeader == true) + { + listAsString = String.Format("ArrayList of count: {0}.\r\n(\r\n{1})", Count, listAsString); } + return listAsString; + } - /********************************************************************************/ + /********************************************************************************/ - public IEnumerator GetEnumerator() - { - for (int i = 0; i < Count; i++) - { - yield return _collection[i]; - } - } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + public IEnumerator GetEnumerator() + { + for (int i = 0; i < Count; i++) { - return GetEnumerator(); + yield return _collection[i]; } + } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); } } \ No newline at end of file diff --git a/DataStructures/Lists/CircularBuffer.cs b/DataStructures/Lists/CircularBuffer.cs index a35ecf5d..0950fb28 100644 --- a/DataStructures/Lists/CircularBuffer.cs +++ b/DataStructures/Lists/CircularBuffer.cs @@ -3,211 +3,210 @@ using System.Collections.Generic; using System.Linq; -namespace DataStructures.Lists +namespace DataStructures.Lists; + +public class CircularBuffer : IEnumerable, ICollection where T : IComparable { - public class CircularBuffer : IEnumerable, ICollection where T : IComparable + private T[] _circularBuffer; + private int _end; + private int _start; + private static readonly int _defaultBufferLength = 10; + + /// + /// Returns the length of the buffer + /// + public int Length => _circularBuffer.Length - 1; + + /// + /// Checks if no element is inserted into the buffer + /// + public bool IsEmpty => Count == 0; + + /// + /// Checks if the buffer is filled up + /// + public bool IsFilledUp => (_end + 1) % _circularBuffer.Length == _start && !_circularBuffer[_start].Equals(_circularBuffer[_end]); + + /// + /// Controls whether data should be overridden when it is continously inserted without reading + /// + public bool CanOverride { - private T[] _circularBuffer; - private int _end; - private int _start; - private static readonly int _defaultBufferLength = 10; - - /// - /// Returns the length of the buffer - /// - public int Length => _circularBuffer.Length - 1; - - /// - /// Checks if no element is inserted into the buffer - /// - public bool IsEmpty => Count == 0; - - /// - /// Checks if the buffer is filled up - /// - public bool IsFilledUp => (_end + 1) % _circularBuffer.Length == _start && !_circularBuffer[_start].Equals(_circularBuffer[_end]); - - /// - /// Controls whether data should be overridden when it is continously inserted without reading - /// - public bool CanOverride - { - get; - } + get; + } - /// - /// Initializes a circular buffer with initial length of 10 - /// - public CircularBuffer(bool canOverride = true) : this(_defaultBufferLength, canOverride) - { - } + /// + /// Initializes a circular buffer with initial length of 10 + /// + public CircularBuffer(bool canOverride = true) : this(_defaultBufferLength, canOverride) + { + } - /// - /// Initializes a circular buffer with given length - /// - /// The length of the buffer - public CircularBuffer(int length, bool canOverride = true) + /// + /// Initializes a circular buffer with given length + /// + /// The length of the buffer + public CircularBuffer(int length, bool canOverride = true) + { + if (length < 1) { - if (length < 1) - { - throw new ArgumentOutOfRangeException("length can not be zero or negative"); - } - _circularBuffer = new T[length + 1]; - _end = 0; - _start = 0; - CanOverride = canOverride; - } - - /// - /// Writes value to the back of the buffer - /// - /// value to be added to the buffer - public void Add(T value) - { - if (CanOverride==false && IsFilledUp==true) - { - throw new CircularBufferFullException($"Circular Buffer is filled up. {value} can not be inserted"); - } - innerInsert(value); + throw new ArgumentOutOfRangeException("length can not be zero or negative"); } + _circularBuffer = new T[length + 1]; + _end = 0; + _start = 0; + CanOverride = canOverride; + } - // Inserts data into the buffer without checking if it is full - private void innerInsert(T value) + /// + /// Writes value to the back of the buffer + /// + /// value to be added to the buffer + public void Add(T value) + { + if (CanOverride==false && IsFilledUp==true) { - _circularBuffer[_end] = value; - _end = (_end + 1) % _circularBuffer.Length; - if (_end == _start) - { - _start = (_start + 1) % _circularBuffer.Length; - } - - // Count should not be greater than the length of the buffer when overriding - Count = Count < Length ? ++Count : Count; + throw new CircularBufferFullException($"Circular Buffer is filled up. {value} can not be inserted"); } + innerInsert(value); + } - /// - /// Reads and removes the value in front of the buffer, and places the next value in front. - /// - public T Pop() + // Inserts data into the buffer without checking if it is full + private void innerInsert(T value) + { + _circularBuffer[_end] = value; + _end = (_end + 1) % _circularBuffer.Length; + if (_end == _start) { - var result = _circularBuffer[_start]; - _circularBuffer[_start] = _circularBuffer[_end]; _start = (_start + 1) % _circularBuffer.Length; - //Count should not go below Zero when poping an empty buffer. - Count = Count > 0 ? --Count : Count; - return result; } - #region IEnumerable Implementation - public IEnumerator GetEnumerator() - { - for (int i = _start; i < Count; i++) - { - yield return _circularBuffer[i]; - } - } + // Count should not be greater than the length of the buffer when overriding + Count = Count < Length ? ++Count : Count; + } + + /// + /// Reads and removes the value in front of the buffer, and places the next value in front. + /// + public T Pop() + { + var result = _circularBuffer[_start]; + _circularBuffer[_start] = _circularBuffer[_end]; + _start = (_start + 1) % _circularBuffer.Length; + //Count should not go below Zero when poping an empty buffer. + Count = Count > 0 ? --Count : Count; + return result; + } - IEnumerator IEnumerable.GetEnumerator() + #region IEnumerable Implementation + public IEnumerator GetEnumerator() + { + for (int i = _start; i < Count; i++) { - return GetEnumerator(); + yield return _circularBuffer[i]; } - #endregion + } - #region ICollection Implementation + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + #endregion - /// - /// Returns the number of elements. - /// - public int Count { get; private set; } + #region ICollection Implementation - /// - /// Checks whether this collection is readonly - /// - public bool IsReadOnly => false; + /// + /// Returns the number of elements. + /// + public int Count { get; private set; } - /// - /// Clears this instance - /// - public void Clear() + /// + /// Checks whether this collection is readonly + /// + public bool IsReadOnly => false; + + /// + /// Clears this instance + /// + public void Clear() + { + Count = 0; + _start = 0; + _end = 0; + _circularBuffer = new T[Length + 1]; + } + /// + /// Checks whether the buffer contains an item + /// + public bool Contains(T item) + { + return _circularBuffer.Contains(item); + } + /// + /// Copies this buffer to an array + /// + public void CopyTo(T[] array, int arrayIndex) + { + if (array == null) { - Count = 0; - _start = 0; - _end = 0; - _circularBuffer = new T[Length + 1]; + throw new ArgumentNullException("array can not be null"); } - /// - /// Checks whether the buffer contains an item - /// - public bool Contains(T item) + + if (array.Length == 0 || arrayIndex >= array.Length || arrayIndex < 0) { - return _circularBuffer.Contains(item); + throw new IndexOutOfRangeException(); } - /// - /// Copies this buffer to an array - /// - public void CopyTo(T[] array, int arrayIndex) + + // Get enumerator + var enumarator = GetEnumerator(); + + // Copy elements if there is any in the buffer and if the index is within the valid range + while (arrayIndex < array.Length) { - if (array == null) + if (enumarator.MoveNext()) { - throw new ArgumentNullException("array can not be null"); + array[arrayIndex] = enumarator.Current; + arrayIndex++; } - - if (array.Length == 0 || arrayIndex >= array.Length || arrayIndex < 0) + else { - throw new IndexOutOfRangeException(); + break; } + } + } + /// + /// Removes an item from the buffer + /// + public bool Remove(T item) + { + if (!IsEmpty && Contains(item)) + { + var sourceArray = _circularBuffer.Except(new T[] { item }).ToArray(); + _circularBuffer = new T[Length + 1]; + Array.Copy(sourceArray, _circularBuffer, sourceArray.Length); - // Get enumerator - var enumarator = GetEnumerator(); - - // Copy elements if there is any in the buffer and if the index is within the valid range - while (arrayIndex < array.Length) + if (!Equals(item,default(T))) { - if (enumarator.MoveNext()) - { - array[arrayIndex] = enumarator.Current; - arrayIndex++; - } - else - { - break; - } + _end = sourceArray.Length - 1; + Count = sourceArray.Length-1; } - } - /// - /// Removes an item from the buffer - /// - public bool Remove(T item) - { - if (!IsEmpty && Contains(item)) + else { - var sourceArray = _circularBuffer.Except(new T[] { item }).ToArray(); - _circularBuffer = new T[Length + 1]; - Array.Copy(sourceArray, _circularBuffer, sourceArray.Length); - - if (!Equals(item,default(T))) - { - _end = sourceArray.Length - 1; - Count = sourceArray.Length-1; - } - else - { - _end = sourceArray.Length; - Count = sourceArray.Length; - } - - return true; + _end = sourceArray.Length; + Count = sourceArray.Length; } - return false; + return true; } - #endregion + + return false; } + #endregion +} - public class CircularBufferFullException : Exception +public class CircularBufferFullException : Exception +{ + public CircularBufferFullException(string message) : base(message) { - public CircularBufferFullException(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/DataStructures/Lists/DLinkedList.cs b/DataStructures/Lists/DLinkedList.cs index aa102671..a2bca2bd 100644 --- a/DataStructures/Lists/DLinkedList.cs +++ b/DataStructures/Lists/DLinkedList.cs @@ -3,79 +3,124 @@ using DataStructures.Common; -namespace DataStructures.Lists +namespace DataStructures.Lists; + +/// +/// The Doubly-Linked List Node class. +/// +/// Type +public class DLinkedListNode : IComparable> where T : IComparable { - /// - /// The Doubly-Linked List Node class. - /// - /// Type - public class DLinkedListNode : IComparable> where T : IComparable + public DLinkedListNode() : this(default) { } + public DLinkedListNode(T dataItem) : this(dataItem, null, null) { } + public DLinkedListNode(T dataItem, DLinkedListNode next, DLinkedListNode previous) { - public DLinkedListNode() : this(default) { } - public DLinkedListNode(T dataItem) : this(dataItem, null, null) { } - public DLinkedListNode(T dataItem, DLinkedListNode next, DLinkedListNode previous) - { - Data = dataItem; - Next = next; - Previous = previous; - } + Data = dataItem; + Next = next; + Previous = previous; + } - public virtual T Data { get; set; } + public virtual T Data { get; set; } - public virtual DLinkedListNode Next { get; set; } + public virtual DLinkedListNode Next { get; set; } - public virtual DLinkedListNode Previous { get; set; } + public virtual DLinkedListNode Previous { get; set; } - public int CompareTo(DLinkedListNode other) - { - if (other == null) return -1; + public int CompareTo(DLinkedListNode other) + { + if (other == null) return -1; - return Data.CompareTo(other.Data); - } + return Data.CompareTo(other.Data); } +} - /***********************************************************************************/ +/***********************************************************************************/ +/// +/// Doubly-Linked List Data Structure. +/// +/// Type +public class DLinkedList : IEnumerable where T : IComparable +{ /// - /// Doubly-Linked List Data Structure. + /// Instance variables. /// - /// Type - public class DLinkedList : IEnumerable where T : IComparable - { - /// - /// Instance variables. - /// - private int _count; - private DLinkedListNode _firstNode { get; set; } - private DLinkedListNode _lastNode { get; set; } + private int _count; + private DLinkedListNode _firstNode { get; set; } + private DLinkedListNode _lastNode { get; set; } - public virtual DLinkedListNode Head => _firstNode; + public virtual DLinkedListNode Head => _firstNode; - public virtual int Count => _count; + public virtual int Count => _count; - /// - /// Gets the element at the specified index - /// - /// Index of element - /// Element - protected virtual T _getElementAt(int index) + /// + /// Gets the element at the specified index + /// + /// Index of element + /// Element + protected virtual T _getElementAt(int index) + { + if (IsEmpty() || index < 0 || index >= Count) + throw new IndexOutOfRangeException("List is empty."); + + if (index == 0) { - if (IsEmpty() || index < 0 || index >= Count) - throw new IndexOutOfRangeException("List is empty."); + return First; + } - if (index == 0) + if (index == Count - 1) + { + return Last; + } + + DLinkedListNode currentNode = null; + + // Decide from which reference to traverse the list, and then move the currentNode reference to the index + // If index > half then traverse it from the end (_lastNode reference) + // Otherwise, traverse it from the beginning (_firstNode refrence) + if (index > Count / 2) + { + currentNode = _lastNode; + for (int i = Count - 1; i > index; --i) { - return First; + currentNode = currentNode.Previous; } - - if (index == Count - 1) + } + else + { + currentNode = _firstNode; + for (int i = 0; i < index; ++i) { - return Last; + currentNode = currentNode.Next; } + } + + return currentNode.Data; + } + /// + /// Sets the value of the element at the specified index + /// + /// Index of element to update. + /// Element + protected virtual void _setElementAt(int index, T value) + { + if (IsEmpty() || index < 0 || index >= Count) + throw new IndexOutOfRangeException("List is empty."); + + if (index == 0) + { + _firstNode.Data = value; + } + else if (index == Count - 1) + { + _lastNode.Data = value; + } + else + { DLinkedListNode currentNode = null; // Decide from which reference to traverse the list, and then move the currentNode reference to the index @@ -98,782 +143,735 @@ protected virtual T _getElementAt(int index) } } - return currentNode.Data; + currentNode.Data = value; } + } - /// - /// Sets the value of the element at the specified index - /// - /// Index of element to update. - /// Element - protected virtual void _setElementAt(int index, T value) - { - if (IsEmpty() || index < 0 || index >= Count) - throw new IndexOutOfRangeException("List is empty."); - if (index == 0) - { - _firstNode.Data = value; - } - else if (index == Count - 1) - { - _lastNode.Data = value; - } - else - { - DLinkedListNode currentNode = null; + /// + /// CONSTRUCTOR + /// + public DLinkedList() + { + _count = 0; + _firstNode = null; + _lastNode = null; + } - // Decide from which reference to traverse the list, and then move the currentNode reference to the index - // If index > half then traverse it from the end (_lastNode reference) - // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > Count / 2) - { - currentNode = _lastNode; - for (int i = Count - 1; i > index; --i) - { - currentNode = currentNode.Previous; - } - } - else - { - currentNode = _firstNode; - for (int i = 0; i < index; ++i) - { - currentNode = currentNode.Next; - } - } + /// + /// Determines whether this List is empty. + /// + /// true if this list is empty; otherwise, false. + public virtual bool IsEmpty() + { + return Count == 0; + } - currentNode.Data = value; + /// + /// Getter function that returns the first element + /// + public virtual T First + { + get + { + if (IsEmpty()) + { + throw new Exception("Empty list."); } - } - - /// - /// CONSTRUCTOR - /// - public DLinkedList() - { - _count = 0; - _firstNode = null; - _lastNode = null; + return _firstNode.Data; } + } - /// - /// Determines whether this List is empty. - /// - /// true if this list is empty; otherwise, false. - public virtual bool IsEmpty() + /// + /// Getter function that returns the last element + /// + public virtual T Last + { + get { - return Count == 0; - } + if (IsEmpty()) + { + throw new Exception("Empty list."); + } - /// - /// Getter function that returns the first element - /// - public virtual T First - { - get + if (_lastNode == null) { - if (IsEmpty()) + var currentNode = _firstNode; + while (currentNode.Next != null) { - throw new Exception("Empty list."); + currentNode = currentNode.Next; } - - return _firstNode.Data; + _lastNode = currentNode; + return currentNode.Data; } + + return _lastNode.Data; } + } + + /// + /// Implements the collection-index operator. + /// Gets or sets the element at the specified index + /// + /// Index of element. + public virtual T this[int index] + { + get => _getElementAt(index); + set => _setElementAt(index, value); + } - /// - /// Getter function that returns the last element - /// - public virtual T Last + /// + /// Returns the index of an item if exists. + /// + public virtual int IndexOf(T dataItem) + { + int i = 0; + bool found = false; + var currentNode = _firstNode; + + // Get currentNode to reference the element at the index. + while (i < Count) { - get + if (currentNode.Data.IsEqualTo(dataItem)) { - if (IsEmpty()) - { - throw new Exception("Empty list."); - } + found = true; + break; + } - if (_lastNode == null) - { - var currentNode = _firstNode; - while (currentNode.Next != null) - { - currentNode = currentNode.Next; - } - _lastNode = currentNode; - return currentNode.Data; - } + currentNode = currentNode.Next; + i++; + }//end-while - return _lastNode.Data; - } - } + return found == true ? i : -1; + } - /// - /// Implements the collection-index operator. - /// Gets or sets the element at the specified index - /// - /// Index of element. - public virtual T this[int index] + /// + /// Prepend the specified dataItem at the beginning of the list. + /// + /// Data item. + public virtual void Prepend(T dataItem) + { + DLinkedListNode newNode = new DLinkedListNode(dataItem); + + if (_firstNode == null) { - get => _getElementAt(index); - set => _setElementAt(index, value); + _firstNode = _lastNode = newNode; } - - /// - /// Returns the index of an item if exists. - /// - public virtual int IndexOf(T dataItem) + else { - int i = 0; - bool found = false; var currentNode = _firstNode; + newNode.Next = currentNode; + currentNode.Previous = newNode; + _firstNode = newNode; + } - // Get currentNode to reference the element at the index. - while (i < Count) - { - if (currentNode.Data.IsEqualTo(dataItem)) - { - found = true; - break; - } + // Increment the count. + _count++; + } - currentNode = currentNode.Next; - i++; - }//end-while + /// + /// Append the specified dataItem at the end of the list. + /// + /// Data item. + public virtual void Append(T dataItem) + { + DLinkedListNode newNode = new DLinkedListNode(dataItem); - return found == true ? i : -1; + if (_firstNode == null) + { + _firstNode = _lastNode = newNode; } - - /// - /// Prepend the specified dataItem at the beginning of the list. - /// - /// Data item. - public virtual void Prepend(T dataItem) + else { - DLinkedListNode newNode = new DLinkedListNode(dataItem); + var currentNode = _lastNode; + currentNode.Next = newNode; + newNode.Previous = currentNode; + _lastNode = newNode; + } - if (_firstNode == null) - { - _firstNode = _lastNode = newNode; - } - else - { - var currentNode = _firstNode; - newNode.Next = currentNode; - currentNode.Previous = newNode; - _firstNode = newNode; - } + // Increment the count. + _count++; + } - // Increment the count. - _count++; + /// + /// Inserts the dataItem at the specified index. + /// + /// Data item. + /// Index. + public virtual void InsertAt(T dataItem, int index) + { + if(index < 0 || index > Count) + throw new IndexOutOfRangeException(); + + if (index == 0) + { + Prepend(dataItem); } - - /// - /// Append the specified dataItem at the end of the list. - /// - /// Data item. - public virtual void Append(T dataItem) + else if (index == Count) + { + Append(dataItem); + } + else { + DLinkedListNode currentNode = null; DLinkedListNode newNode = new DLinkedListNode(dataItem); - if (_firstNode == null) + currentNode = _firstNode; + for (int i = 0; i < index - 1; ++i) { - _firstNode = _lastNode = newNode; - } - else - { - var currentNode = _lastNode; - currentNode.Next = newNode; - newNode.Previous = currentNode; - _lastNode = newNode; + currentNode = currentNode.Next; } - // Increment the count. - _count++; - } - - /// - /// Inserts the dataItem at the specified index. - /// - /// Data item. - /// Index. - public virtual void InsertAt(T dataItem, int index) - { - if(index < 0 || index > Count) - throw new IndexOutOfRangeException(); - - if (index == 0) - { - Prepend(dataItem); - } - else if (index == Count) - { - Append(dataItem); - } - else - { - DLinkedListNode currentNode = null; - DLinkedListNode newNode = new DLinkedListNode(dataItem); + var oldNext = currentNode.Next; - currentNode = _firstNode; - for (int i = 0; i < index - 1; ++i) - { - currentNode = currentNode.Next; - } + if (oldNext != null) + currentNode.Next.Previous = newNode; - var oldNext = currentNode.Next; + newNode.Next = oldNext; + currentNode.Next = newNode; + newNode.Previous = currentNode; - if (oldNext != null) - currentNode.Next.Previous = newNode; + // Increment the count + _count++; + } + } - newNode.Next = oldNext; - currentNode.Next = newNode; - newNode.Previous = currentNode; + /// + /// Inserts the dataItem after specified index. + /// + /// Data item. + /// Index. + public virtual void InsertAfter(T dataItem, int index) + { + // Insert at previous index. + InsertAt(dataItem, index - 1); + } - // Increment the count - _count++; - } - } + /// + /// Remove the specified dataItem. + /// + public virtual void Remove(T dataItem) + { + // Handle index out of bound errors + if (IsEmpty()) + throw new IndexOutOfRangeException(); - /// - /// Inserts the dataItem after specified index. - /// - /// Data item. - /// Index. - public virtual void InsertAfter(T dataItem, int index) + if (_firstNode.Data.IsEqualTo(dataItem)) { - // Insert at previous index. - InsertAt(dataItem, index - 1); + _firstNode = _firstNode.Next; + + if (_firstNode != null) + _firstNode.Previous = null; } + else if (_lastNode.Data.IsEqualTo(dataItem)) + { + _lastNode = _lastNode.Previous; - /// - /// Remove the specified dataItem. - /// - public virtual void Remove(T dataItem) + if (_lastNode != null) + _lastNode.Next = null; + } + else { - // Handle index out of bound errors - if (IsEmpty()) - throw new IndexOutOfRangeException(); + // Remove + var currentNode = _firstNode; - if (_firstNode.Data.IsEqualTo(dataItem)) + // Get currentNode to reference the element at the index. + while (currentNode.Next != null) { - _firstNode = _firstNode.Next; + if (currentNode.Data.IsEqualTo(dataItem)) + break; - if (_firstNode != null) - _firstNode.Previous = null; - } - else if (_lastNode.Data.IsEqualTo(dataItem)) - { - _lastNode = _lastNode.Previous; + currentNode = currentNode.Next; + }//end-while - if (_lastNode != null) - _lastNode.Next = null; - } - else - { - // Remove - var currentNode = _firstNode; + // Throw exception if item was not found + if (!currentNode.Data.IsEqualTo(dataItem)) + throw new Exception("Item was not found!"); - // Get currentNode to reference the element at the index. - while (currentNode.Next != null) - { - if (currentNode.Data.IsEqualTo(dataItem)) - break; + // Remove element + DLinkedListNode newPrevious = currentNode.Previous; + DLinkedListNode newNext = currentNode.Next; - currentNode = currentNode.Next; - }//end-while + if (newPrevious != null) + newPrevious.Next = newNext; - // Throw exception if item was not found - if (!currentNode.Data.IsEqualTo(dataItem)) - throw new Exception("Item was not found!"); + if (newNext != null) + newNext.Previous = newPrevious; - // Remove element - DLinkedListNode newPrevious = currentNode.Previous; - DLinkedListNode newNext = currentNode.Next; + currentNode = newPrevious; + } - if (newPrevious != null) - newPrevious.Next = newNext; + // Decrement count. + _count--; + } - if (newNext != null) - newNext.Previous = newPrevious; + /// + /// Remove the specified dataItem. + /// + public virtual void RemoveFirstMatch(Predicate match) + { + // Handle index out of bound errors + if (IsEmpty()) + throw new IndexOutOfRangeException(); - currentNode = newPrevious; - } + if (match(_firstNode.Data)) + { + _firstNode = _firstNode.Next; - // Decrement count. - _count--; + if (_firstNode != null) + _firstNode.Previous = null; } + else if (match(_lastNode.Data)) + { + _lastNode = _lastNode.Previous; - /// - /// Remove the specified dataItem. - /// - public virtual void RemoveFirstMatch(Predicate match) + if (_lastNode != null) + _lastNode.Next = null; + } + else { - // Handle index out of bound errors - if (IsEmpty()) - throw new IndexOutOfRangeException(); + // Remove + var currentNode = _firstNode; - if (match(_firstNode.Data)) + // Get currentNode to reference the element at the index. + while (currentNode.Next != null) { - _firstNode = _firstNode.Next; + if (match(currentNode.Data)) + break; - if (_firstNode != null) - _firstNode.Previous = null; - } - else if (match(_lastNode.Data)) - { - _lastNode = _lastNode.Previous; + currentNode = currentNode.Next; + }//end-while - if (_lastNode != null) - _lastNode.Next = null; - } - else - { - // Remove - var currentNode = _firstNode; + // If we reached the last node and item was not found + // Throw exception + if (!match(currentNode.Data)) + throw new Exception("Item was not found!"); - // Get currentNode to reference the element at the index. - while (currentNode.Next != null) - { - if (match(currentNode.Data)) - break; + // Remove element + DLinkedListNode newPrevious = currentNode.Previous; + DLinkedListNode newNext = currentNode.Next; - currentNode = currentNode.Next; - }//end-while + if (newPrevious != null) + newPrevious.Next = newNext; - // If we reached the last node and item was not found - // Throw exception - if (!match(currentNode.Data)) - throw new Exception("Item was not found!"); + if (newNext != null) + newNext.Previous = newPrevious; - // Remove element - DLinkedListNode newPrevious = currentNode.Previous; - DLinkedListNode newNext = currentNode.Next; + currentNode = newPrevious; + } - if (newPrevious != null) - newPrevious.Next = newNext; + // Decrement count. + _count--; + } - if (newNext != null) - newNext.Previous = newPrevious; + /// + /// Removes the item at the specified index. + /// + /// True if removed successfully, false otherwise. + /// Index of item. + public virtual void RemoveAt(int index) + { + // Handle index out of bound errors + if (IsEmpty() || index < 0 || index >= Count) + throw new IndexOutOfRangeException(); - currentNode = newPrevious; - } + // Remove + if (index == 0) + { + _firstNode = _firstNode.Next; - // Decrement count. - _count--; + if (_firstNode != null) + _firstNode.Previous = null; } - - /// - /// Removes the item at the specified index. - /// - /// True if removed successfully, false otherwise. - /// Index of item. - public virtual void RemoveAt(int index) + else if (index == Count - 1) { - // Handle index out of bound errors - if (IsEmpty() || index < 0 || index >= Count) - throw new IndexOutOfRangeException(); + _lastNode = _lastNode.Previous; - // Remove - if (index == 0) - { - _firstNode = _firstNode.Next; - - if (_firstNode != null) - _firstNode.Previous = null; - } - else if (index == Count - 1) - { - _lastNode = _lastNode.Previous; + if (_lastNode != null) + _lastNode.Next = null; + } + else + { + int i = 0; + var currentNode = _firstNode; - if (_lastNode != null) - _lastNode.Next = null; - } - else + // Get currentNode to reference the element at the index. + while (i < index) { - int i = 0; - var currentNode = _firstNode; + currentNode = currentNode.Next; + i++; + }//end-while - // Get currentNode to reference the element at the index. - while (i < index) - { - currentNode = currentNode.Next; - i++; - }//end-while + // Remove element + var newPrevious = currentNode.Previous; + var newNext = currentNode.Next; + newPrevious.Next = newNext; - // Remove element - var newPrevious = currentNode.Previous; - var newNext = currentNode.Next; - newPrevious.Next = newNext; + if (newNext != null) + newNext.Previous = newPrevious; - if (newNext != null) - newNext.Previous = newPrevious; + currentNode = newPrevious; + }//end-else - currentNode = newPrevious; - }//end-else + // Decrement count. + _count--; + } - // Decrement count. - _count--; - } + /// + /// Clears the list. + /// + public virtual void Clear() + { + _count = 0; + _firstNode = _lastNode = null; + } - /// - /// Clears the list. - /// - public virtual void Clear() + /// + /// Chesk whether the specified element exists in the list. + /// + /// Value to check for. + /// True if found; false otherwise. + public virtual bool Contains(T dataItem) + { + try { - _count = 0; - _firstNode = _lastNode = null; + return Find(dataItem).IsEqualTo(dataItem); } - - /// - /// Chesk whether the specified element exists in the list. - /// - /// Value to check for. - /// True if found; false otherwise. - public virtual bool Contains(T dataItem) + catch (Exception) { - try - { - return Find(dataItem).IsEqualTo(dataItem); - } - catch (Exception) - { - return false; - } + return false; } + } - /// - /// Find the specified item in the list. - /// - /// Value to find. - /// value. - public virtual T Find(T dataItem) - { - if (IsEmpty()) - throw new Exception("List is empty."); - - var currentNode = _firstNode; - while (currentNode != null) - { - if (currentNode.Data.IsEqualTo(dataItem)) - return dataItem; + /// + /// Find the specified item in the list. + /// + /// Value to find. + /// value. + public virtual T Find(T dataItem) + { + if (IsEmpty()) + throw new Exception("List is empty."); - currentNode = currentNode.Next; - } + var currentNode = _firstNode; + while (currentNode != null) + { + if (currentNode.Data.IsEqualTo(dataItem)) + return dataItem; - throw new Exception("Item was not found."); + currentNode = currentNode.Next; } - /// - /// Tries to find a match for the predicate. Returns true if found; otherwise false. - /// - public virtual bool TryFindFirst(Predicate match, out T found) - { - // Initialize the output parameter - found = default; + throw new Exception("Item was not found."); + } - if (IsEmpty()) - return false; + /// + /// Tries to find a match for the predicate. Returns true if found; otherwise false. + /// + public virtual bool TryFindFirst(Predicate match, out T found) + { + // Initialize the output parameter + found = default; - var currentNode = _firstNode; + if (IsEmpty()) + return false; + + var currentNode = _firstNode; - try + try + { + while (currentNode != null) { - while (currentNode != null) + if (match(currentNode.Data)) { - if (match(currentNode.Data)) - { - found = currentNode.Data; - return true; - } - - currentNode = currentNode.Next; + found = currentNode.Data; + return true; } - return false; - } - catch - { - return false; + currentNode = currentNode.Next; } - } - /// - /// Find the first element that matches the predicate from all elements in list. - /// - public virtual T FindFirst(Predicate match) + return false; + } + catch { - if (IsEmpty()) - throw new Exception("List is empty."); + return false; + } + } - var currentNode = _firstNode; + /// + /// Find the first element that matches the predicate from all elements in list. + /// + public virtual T FindFirst(Predicate match) + { + if (IsEmpty()) + throw new Exception("List is empty."); - while (currentNode != null) - { - if (match(currentNode.Data)) - return currentNode.Data; + var currentNode = _firstNode; - currentNode = currentNode.Next; - } + while (currentNode != null) + { + if (match(currentNode.Data)) + return currentNode.Data; - throw new KeyNotFoundException(); + currentNode = currentNode.Next; } - /// - /// Find all elements in list that match the predicate. - /// - /// Predicate function. - /// List of elements. - public virtual List FindAll(Predicate match) - { - if (IsEmpty()) - throw new Exception("List is empty."); + throw new KeyNotFoundException(); + } - var currentNode = _firstNode; - var list = new List(); + /// + /// Find all elements in list that match the predicate. + /// + /// Predicate function. + /// List of elements. + public virtual List FindAll(Predicate match) + { + if (IsEmpty()) + throw new Exception("List is empty."); - while (currentNode != null) - { - if (match(currentNode.Data)) - list.Add(currentNode.Data); + var currentNode = _firstNode; + var list = new List(); - currentNode = currentNode.Next; - } + while (currentNode != null) + { + if (match(currentNode.Data)) + list.Add(currentNode.Data); - return list; + currentNode = currentNode.Next; } - /// - /// Returns a number of elements as specified by countOfElements, starting from the specified index. - /// - /// Starting index. - /// The number of elements to return. - /// Doubly-Linked List of elements - public virtual DLinkedList GetRange(int index, int countOfElements) - { - DLinkedListNode currentNode = null; - DLinkedList newList = new DLinkedList(); + return list; + } - // Handle Index out of Bound errors - if (Count == 0) - { - return newList; - } + /// + /// Returns a number of elements as specified by countOfElements, starting from the specified index. + /// + /// Starting index. + /// The number of elements to return. + /// Doubly-Linked List of elements + public virtual DLinkedList GetRange(int index, int countOfElements) + { + DLinkedListNode currentNode = null; + DLinkedList newList = new DLinkedList(); - if (index < 0 || index > Count) - { - throw new IndexOutOfRangeException(); - } + // Handle Index out of Bound errors + if (Count == 0) + { + return newList; + } - // Decide from which reference to traverse the list, and then move the currentNode reference to the index - // If index > half then traverse it from the end (_lastNode reference) - // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > Count / 2) - { - currentNode = _lastNode; - for (int i = Count - 1; i > index; --i) - { - currentNode = currentNode.Previous; - } - } - else + if (index < 0 || index > Count) + { + throw new IndexOutOfRangeException(); + } + + // Decide from which reference to traverse the list, and then move the currentNode reference to the index + // If index > half then traverse it from the end (_lastNode reference) + // Otherwise, traverse it from the beginning (_firstNode refrence) + if (index > Count / 2) + { + currentNode = _lastNode; + for (int i = Count - 1; i > index; --i) { - currentNode = _firstNode; - for (int i = 0; i < index; ++i) - { - currentNode = currentNode.Next; - } + currentNode = currentNode.Previous; } - - // Append the elements to the new list using the currentNode reference - while (currentNode != null && newList.Count <= countOfElements) + } + else + { + currentNode = _firstNode; + for (int i = 0; i < index; ++i) { - newList.Append(currentNode.Data); currentNode = currentNode.Next; } - - return newList; } - /// - /// Sorts the entire list using Selection Sort. - /// - public virtual void SelectionSort() + // Append the elements to the new list using the currentNode reference + while (currentNode != null && newList.Count <= countOfElements) { - if (IsEmpty()) - return; + newList.Append(currentNode.Data); + currentNode = currentNode.Next; + } - var currentNode = _firstNode; - while (currentNode != null) - { - var minNode = currentNode; - var nextNode = currentNode.Next; - while (nextNode != null) - { - if (nextNode.Data.IsLessThan(minNode.Data)) - { - minNode = nextNode; - } + return newList; + } - nextNode = nextNode.Next; - } + /// + /// Sorts the entire list using Selection Sort. + /// + public virtual void SelectionSort() + { + if (IsEmpty()) + return; - if (minNode != currentNode) + var currentNode = _firstNode; + while (currentNode != null) + { + var minNode = currentNode; + var nextNode = currentNode.Next; + while (nextNode != null) + { + if (nextNode.Data.IsLessThan(minNode.Data)) { - var temp = minNode.Data; - minNode.Data = currentNode.Data; - currentNode.Data = temp; + minNode = nextNode; } - currentNode = currentNode.Next; + nextNode = nextNode.Next; } - } - - /// - /// Return an array version of this list. - /// - /// - public virtual T[] ToArray() - { - T[] array = new T[Count]; - var currentNode = _firstNode; - for (int i = 0; i < Count; ++i) + if (minNode != currentNode) { - if (currentNode != null) - { - array[i] = currentNode.Data; - currentNode = currentNode.Next; - } - else - { - break; - } + var temp = minNode.Data; + minNode.Data = currentNode.Data; + currentNode.Data = temp; } - return array; + currentNode = currentNode.Next; } + } - /// - /// Returns a System.List version of this DLList instace. - /// - /// System.List of elements - public virtual List ToList() - { - List list = new List(Count); + /// + /// Return an array version of this list. + /// + /// + public virtual T[] ToArray() + { + T[] array = new T[Count]; - var currentNode = _firstNode; - for (int i = 0; i < Count; ++i) + var currentNode = _firstNode; + for (int i = 0; i < Count; ++i) + { + if (currentNode != null) { - if (currentNode != null) - { - list.Add(currentNode.Data); - currentNode = currentNode.Next; - } - else - { - break; - } + array[i] = currentNode.Data; + currentNode = currentNode.Next; + } + else + { + break; } - - return list; } - /// - /// Returns the list items as a readable multi--line string. - /// - /// - public virtual string ToReadable() - { - string listAsString = string.Empty; - int i = 0; - var currentNode = _firstNode; + return array; + } - while (currentNode != null) + /// + /// Returns a System.List version of this DLList instace. + /// + /// System.List of elements + public virtual List ToList() + { + List list = new List(Count); + + var currentNode = _firstNode; + for (int i = 0; i < Count; ++i) + { + if (currentNode != null) { - listAsString = String.Format("{0}[{1}] => {2}\r\n", listAsString, i, currentNode.Data); + list.Add(currentNode.Data); currentNode = currentNode.Next; - ++i; } - - return listAsString; + else + { + break; + } } - /********************************************************************************/ + return list; + } - public IEnumerator GetEnumerator() - { - var node = _firstNode; - while (node != null) - { - yield return node.Data; - node = node.Next; - } + /// + /// Returns the list items as a readable multi--line string. + /// + /// + public virtual string ToReadable() + { + string listAsString = string.Empty; + int i = 0; + var currentNode = _firstNode; - // Alternative: IEnumerator class instance - // return new DLinkedListEnumerator(this); + while (currentNode != null) + { + listAsString = String.Format("{0}[{1}] => {2}\r\n", listAsString, i, currentNode.Data); + currentNode = currentNode.Next; + ++i; } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); + return listAsString; + } + + /********************************************************************************/ - // Alternative: IEnumerator class instance - // return new DLinkedListEnumerator(this); + public IEnumerator GetEnumerator() + { + var node = _firstNode; + while (node != null) + { + yield return node.Data; + node = node.Next; } - /********************************************************************************/ + // Alternative: IEnumerator class instance + // return new DLinkedListEnumerator(this); + } - internal class DLinkedListEnumerator : IEnumerator - { - private DLinkedListNode _current; - private DLinkedList _doublyLinkedList; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); - public DLinkedListEnumerator(DLinkedList list) - { - _current = list.Head; - _doublyLinkedList = list; - } + // Alternative: IEnumerator class instance + // return new DLinkedListEnumerator(this); + } - public T Current => _current.Data; + /********************************************************************************/ - object System.Collections.IEnumerator.Current => Current; + internal class DLinkedListEnumerator : IEnumerator + { + private DLinkedListNode _current; + private DLinkedList _doublyLinkedList; - public bool MoveNext() - { - if (_current.Next != null) - _current = _current.Next; - else - return false; + public DLinkedListEnumerator(DLinkedList list) + { + _current = list.Head; + _doublyLinkedList = list; + } - return true; - } + public T Current => _current.Data; - public bool MovePrevious() - { - if (_current.Previous != null) - _current = _current.Previous; - else - return false; + object System.Collections.IEnumerator.Current => Current; - return true; - } + public bool MoveNext() + { + if (_current.Next != null) + _current = _current.Next; + else + return false; - public void Reset() - { - _current = _doublyLinkedList.Head; - } + return true; + } - public void Dispose() - { - _current = null; - _doublyLinkedList = null; - } + public bool MovePrevious() + { + if (_current.Previous != null) + _current = _current.Previous; + else + return false; + + return true; + } + + public void Reset() + { + _current = _doublyLinkedList.Head; } + public void Dispose() + { + _current = null; + _doublyLinkedList = null; + } } -} +} \ No newline at end of file diff --git a/DataStructures/Lists/DLinkedList_KeyValue.cs b/DataStructures/Lists/DLinkedList_KeyValue.cs index 849dd023..b27d5ea1 100644 --- a/DataStructures/Lists/DLinkedList_KeyValue.cs +++ b/DataStructures/Lists/DLinkedList_KeyValue.cs @@ -3,126 +3,203 @@ using DataStructures.Common; -namespace DataStructures.Lists +namespace DataStructures.Lists; + +/// +/// The Doubly-Linked List Node class. +/// +/// Type +public class DLinkedListNode : IComparable> where TKey : IComparable { - /// - /// The Doubly-Linked List Node class. - /// - /// Type - public class DLinkedListNode : IComparable> where TKey : IComparable + public DLinkedListNode() : this(default, default) { } + public DLinkedListNode(TKey key, TValue value) : this(key, value, next: null, null) { } + public DLinkedListNode(TKey key, TValue value, DLinkedListNode next, DLinkedListNode previous) { - public DLinkedListNode() : this(default, default) { } - public DLinkedListNode(TKey key, TValue value) : this(key, value, next: null, null) { } - public DLinkedListNode(TKey key, TValue value, DLinkedListNode next, DLinkedListNode previous) - { - Key = key; - Value = value; - Next = next; - Previous = previous; - } + Key = key; + Value = value; + Next = next; + Previous = previous; + } - public virtual TKey Key { get; set; } + public virtual TKey Key { get; set; } - public virtual TValue Value { get; set; } + public virtual TValue Value { get; set; } - public virtual DLinkedListNode Next { get; set; } + public virtual DLinkedListNode Next { get; set; } - public virtual DLinkedListNode Previous { get; set; } + public virtual DLinkedListNode Previous { get; set; } - public int CompareTo(DLinkedListNode other) - { - if (other == null) return -1; + public int CompareTo(DLinkedListNode other) + { + if (other == null) return -1; - return Key.CompareTo(other.Key); - } + return Key.CompareTo(other.Key); } +} +/// +/// Doubly-Linked List Data Structure. +/// +/// Type +public class DLinkedList where TKey : IComparable +{ /// - /// Doubly-Linked List Data Structure. + /// Instance variables. /// - /// Type - public class DLinkedList where TKey : IComparable - { - /// - /// Instance variables. - /// - private int _count; - private DLinkedListNode _firstNode { get; set; } - private DLinkedListNode _lastNode { get; set; } + private int _count; + private DLinkedListNode _firstNode { get; set; } + private DLinkedListNode _lastNode { get; set; } - public virtual DLinkedListNode Head => _firstNode; + public virtual DLinkedListNode Head => _firstNode; - public virtual int Count => _count; + public virtual int Count => _count; - /// - /// Gets the element at the specified index - /// - protected virtual DLinkedListNode _getNodeByIndex(int index) + /// + /// Gets the element at the specified index + /// + protected virtual DLinkedListNode _getNodeByIndex(int index) + { + if (IsEmpty()) + throw new IndexOutOfRangeException("List is empty."); + + if (index == 0) { - if (IsEmpty()) - throw new IndexOutOfRangeException("List is empty."); + return _firstNode; + } - if (index == 0) - { - return _firstNode; - } + if (index == Count - 1) + { + return _lastNode; + } - if (index == Count - 1) - { - return _lastNode; - } + if (index > 0 && index < Count - 1) + { + DLinkedListNode currentNode = null; - if (index > 0 && index < Count - 1) + // Decide from which reference to traverse the list, and then move the currentNode reference to the index + // If index > half then traverse it from the end (_lastNode reference) + // Otherwise, traverse it from the beginning (_firstNode refrence) + if (index > Count / 2) { - DLinkedListNode currentNode = null; - - // Decide from which reference to traverse the list, and then move the currentNode reference to the index - // If index > half then traverse it from the end (_lastNode reference) - // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > Count / 2) + currentNode = _lastNode; + for (int i = Count - 1; i > index; --i) { - currentNode = _lastNode; - for (int i = Count - 1; i > index; --i) - { - currentNode = currentNode.Previous; - } + currentNode = currentNode.Previous; } - else + } + else + { + currentNode = _firstNode; + for (int i = 0; i < index; ++i) { - currentNode = _firstNode; - for (int i = 0; i < index; ++i) - { - currentNode = currentNode.Next; - } + currentNode = currentNode.Next; } - - return currentNode; } - throw new IndexOutOfRangeException(); + return currentNode; + } + + throw new IndexOutOfRangeException(); + } + + /// + /// Gets the element by the specified key + /// + protected virtual DLinkedListNode _getNodeByKey(TKey key) + { + if (key.IsEqualTo(_firstNode.Key)) + { + return _firstNode; } - /// - /// Gets the element by the specified key - /// - protected virtual DLinkedListNode _getNodeByKey(TKey key) + if (key.IsEqualTo(_lastNode.Key)) { - if (key.IsEqualTo(_firstNode.Key)) + return _lastNode; + } + + var currentNode = _firstNode; + while (currentNode != null) + { + if (key.IsEqualTo(currentNode.Key)) + break; + + currentNode = currentNode.Next; + } + + if (currentNode == null) + throw new KeyNotFoundException(); + + return currentNode; + } + + /// + /// Sets the node's value by index. + /// + protected virtual void _setValueByIndex(int index, TValue value) + { + if (IsEmpty() || index < 0 || index >= Count) + throw new IndexOutOfRangeException("List is empty."); + + if (index == 0) + { + _firstNode.Value = value; + } + else if (index == Count - 1) + { + _lastNode.Value = value; + } + else if (index > 0 && index < Count - 1) + { + DLinkedListNode currentNode = null; + + // Decide from which reference to traverse the list, and then move the currentNode reference to the index + // If index > half then traverse it from the end (_lastNode reference) + // Otherwise, traverse it from the beginning (_firstNode refrence) + if (index > Count / 2) { - return _firstNode; + currentNode = _lastNode; + for (int i = Count - 1; i > index; --i) + { + currentNode = currentNode.Previous; + } } - - if (key.IsEqualTo(_lastNode.Key)) + else { - return _lastNode; + currentNode = _firstNode; + for (int i = 0; i < index; ++i) + { + currentNode = currentNode.Next; + } } + currentNode.Value = value; + } + } + + /// + /// Sets the node's value by key. + /// + protected virtual void _setValueByKey(TKey key, TValue value) + { + if (IsEmpty()) + throw new IndexOutOfRangeException("List is empty."); + + if (key.IsEqualTo(_firstNode.Key)) + { + _firstNode.Value = value; + } + else if (key.IsEqualTo(_lastNode.Key)) + { + _lastNode.Value = value; + } + else + { var currentNode = _firstNode; while (currentNode != null) { - if (key.IsEqualTo(currentNode.Key)) + if (currentNode.Key.IsEqualTo(key)) break; currentNode = currentNode.Next; @@ -131,399 +208,378 @@ protected virtual DLinkedListNode _getNodeByKey(TKey key) if (currentNode == null) throw new KeyNotFoundException(); - return currentNode; + currentNode.Value = value; } + } + + /// + /// Sets the node object by index. + /// + protected virtual void _setNodeByIndex(int index, TKey key, TValue value) + { + if (IsEmpty() || index < 0 || index >= Count) + throw new IndexOutOfRangeException("List is empty."); - /// - /// Sets the node's value by index. - /// - protected virtual void _setValueByIndex(int index, TValue value) + if (index == 0) + { + _firstNode.Key = key; + _firstNode.Value = value; + } + else if (index == Count - 1) + { + _lastNode.Key = key; + _lastNode.Value = value; + } + else if (index > 0 && index < Count - 1) { - if (IsEmpty() || index < 0 || index >= Count) - throw new IndexOutOfRangeException("List is empty."); + DLinkedListNode currentNode = null; - if (index == 0) - { - _firstNode.Value = value; - } - else if (index == Count - 1) - { - _lastNode.Value = value; - } - else if (index > 0 && index < Count - 1) + // Decide from which reference to traverse the list, and then move the currentNode reference to the index + // If index > half then traverse it from the end (_lastNode reference) + // Otherwise, traverse it from the beginning (_firstNode refrence) + if (index > Count / 2) { - DLinkedListNode currentNode = null; - - // Decide from which reference to traverse the list, and then move the currentNode reference to the index - // If index > half then traverse it from the end (_lastNode reference) - // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > Count / 2) + currentNode = _lastNode; + for (int i = Count - 1; i > index; --i) { - currentNode = _lastNode; - for (int i = Count - 1; i > index; --i) - { - currentNode = currentNode.Previous; - } + currentNode = currentNode.Previous; } - else + } + else + { + currentNode = _firstNode; + for (int i = 0; i < index; ++i) { - currentNode = _firstNode; - for (int i = 0; i < index; ++i) - { - currentNode = currentNode.Next; - } + currentNode = currentNode.Next; } - - currentNode.Value = value; } + + currentNode.Key = key; + currentNode.Value = value; } + } + + + /// + /// CONSTRUCTOR + /// + public DLinkedList() + { + _count = 0; + _firstNode = null; + _lastNode = null; + } - /// - /// Sets the node's value by key. - /// - protected virtual void _setValueByKey(TKey key, TValue value) + /// + /// Determines whether this List is empty. + /// + /// true if this list is empty; otherwise, false. + public virtual bool IsEmpty() + { + return Count == 0; + } + + /// + /// Getter function that returns the first element + /// + public virtual KeyValuePair First + { + get { if (IsEmpty()) - throw new IndexOutOfRangeException("List is empty."); - - if (key.IsEqualTo(_firstNode.Key)) { - _firstNode.Value = value; + throw new Exception("Empty list."); } - else if (key.IsEqualTo(_lastNode.Key)) + + return new KeyValuePair(_firstNode.Key, _firstNode.Value); + } + } + + /// + /// Getter function that returns the last element + /// + public virtual KeyValuePair Last + { + get + { + if (IsEmpty()) { - _lastNode.Value = value; + throw new Exception("Empty list."); } - else + + if (_lastNode == null) { var currentNode = _firstNode; - while (currentNode != null) + while (currentNode.Next != null) { - if (currentNode.Key.IsEqualTo(key)) - break; - currentNode = currentNode.Next; } - - if (currentNode == null) - throw new KeyNotFoundException(); - - currentNode.Value = value; + _lastNode = currentNode; } + + return new KeyValuePair(_lastNode.Key, _lastNode.Value); } + } - /// - /// Sets the node object by index. - /// - protected virtual void _setNodeByIndex(int index, TKey key, TValue value) + /// + /// Returns a list of the keys. + /// + public virtual List Keys + { + get { - if (IsEmpty() || index < 0 || index >= Count) - throw new IndexOutOfRangeException("List is empty."); + List list = new List(Count); - if (index == 0) - { - _firstNode.Key = key; - _firstNode.Value = value; - } - else if (index == Count - 1) - { - _lastNode.Key = key; - _lastNode.Value = value; - } - else if (index > 0 && index < Count - 1) + var currentNode = _firstNode; + for (int i = 0; i < Count; ++i) { - DLinkedListNode currentNode = null; - - // Decide from which reference to traverse the list, and then move the currentNode reference to the index - // If index > half then traverse it from the end (_lastNode reference) - // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > Count / 2) + if (currentNode != null) { - currentNode = _lastNode; - for (int i = Count - 1; i > index; --i) - { - currentNode = currentNode.Previous; - } + list.Add(currentNode.Key); + currentNode = currentNode.Next; } else { - currentNode = _firstNode; - for (int i = 0; i < index; ++i) - { - currentNode = currentNode.Next; - } + break; } - - currentNode.Key = key; - currentNode.Value = value; } - } - - - /// - /// CONSTRUCTOR - /// - public DLinkedList() - { - _count = 0; - _firstNode = null; - _lastNode = null; - } - /// - /// Determines whether this List is empty. - /// - /// true if this list is empty; otherwise, false. - public virtual bool IsEmpty() - { - return Count == 0; + return list; } + } - /// - /// Getter function that returns the first element - /// - public virtual KeyValuePair First + /// + /// Returns a list of the values. + /// + public virtual List Values + { + get { - get - { - if (IsEmpty()) - { - throw new Exception("Empty list."); - } + List list = new List(Count); - return new KeyValuePair(_firstNode.Key, _firstNode.Value); - } - } - - /// - /// Getter function that returns the last element - /// - public virtual KeyValuePair Last - { - get + var currentNode = _firstNode; + for (int i = 0; i < Count; ++i) { - if (IsEmpty()) + if (currentNode != null) { - throw new Exception("Empty list."); + list.Add(currentNode.Value); + currentNode = currentNode.Next; } - - if (_lastNode == null) + else { - var currentNode = _firstNode; - while (currentNode.Next != null) - { - currentNode = currentNode.Next; - } - _lastNode = currentNode; + break; } - - return new KeyValuePair(_lastNode.Key, _lastNode.Value); } + + return list; } + } - /// - /// Returns a list of the keys. - /// - public virtual List Keys + /// + /// Prepend the key-value at the beginning of the list. + /// + public virtual void Prepend(TKey key, TValue value) + { + var newNode = new DLinkedListNode(key, value); + + if (_firstNode == null) { - get - { - List list = new List(Count); + _firstNode = _lastNode = newNode; + } + else + { + var currentNode = _firstNode; + newNode.Next = currentNode; + currentNode.Previous = newNode; + _firstNode = newNode; + } - var currentNode = _firstNode; - for (int i = 0; i < Count; ++i) - { - if (currentNode != null) - { - list.Add(currentNode.Key); - currentNode = currentNode.Next; - } - else - { - break; - } - } + // Increment the count. + _count++; + } - return list; - } - } + /// + /// Append the key-value item at the end of the list. + /// + public virtual void Append(TKey key, TValue value) + { + var newNode = new DLinkedListNode(key, value); - /// - /// Returns a list of the values. - /// - public virtual List Values + if (_firstNode == null) { - get - { - List list = new List(Count); + _firstNode = _lastNode = newNode; + } + else + { + var currentNode = _lastNode; + currentNode.Next = newNode; + newNode.Previous = currentNode; + _lastNode = newNode; + } - var currentNode = _firstNode; - for (int i = 0; i < Count; ++i) - { - if (currentNode != null) - { - list.Add(currentNode.Value); - currentNode = currentNode.Next; - } - else - { - break; - } - } + // Increment the count. + _count++; + } - return list; - } + /// + /// Inserts the a new key-value item at the specified index. + /// + public virtual void InsertAt(int index, TKey key, TValue value) + { + if (index == 0) + { + Prepend(key, value); } - - /// - /// Prepend the key-value at the beginning of the list. - /// - public virtual void Prepend(TKey key, TValue value) + else if (index == Count) { + Append(key, value); + } + else if (index > 0 && index < Count) + { + DLinkedListNode currentNode = null; var newNode = new DLinkedListNode(key, value); - if (_firstNode == null) + // Decide from which reference to traverse the list, and then move the currentNode reference to the index + // If index > half then traverse it from the end (_lastNode reference) + // Otherwise, traverse it from the beginning (_firstNode refrence) + if (index > Count / 2) { - _firstNode = _lastNode = newNode; + currentNode = _lastNode; + for (int i = Count - 1; i > index - 1; --i) + { + currentNode = currentNode.Previous; + } } else { - var currentNode = _firstNode; - newNode.Next = currentNode; - currentNode.Previous = newNode; - _firstNode = newNode; + currentNode = _firstNode; + for (int i = 0; i < index - 1; ++i) + { + currentNode = currentNode.Next; + } } - // Increment the count. + newNode.Next = currentNode.Next; + currentNode.Next = newNode; + newNode.Previous = currentNode; + + // Increment the count _count++; } + else + { + throw new IndexOutOfRangeException(); + } + } + + /// + /// Inserts the key-value after specified index. + /// + public virtual void InsertAfter(int index, TKey key, TValue value) + { + // Insert at previous index. + InsertAt(index - 1, key, value); + } - /// - /// Append the key-value item at the end of the list. - /// - public virtual void Append(TKey key, TValue value) + /// + /// Removes the item at the specified index. + /// + public virtual void RemoveAt(int index) + { + // Handle index out of bound errors + if (IsEmpty() || index < 0 || index >= Count) + throw new IndexOutOfRangeException(); + + // Remove + if (index == 0) { - var newNode = new DLinkedListNode(key, value); + _firstNode = _firstNode.Next; - if (_firstNode == null) - { - _firstNode = _lastNode = newNode; - } - else - { - var currentNode = _lastNode; - currentNode.Next = newNode; - newNode.Previous = currentNode; - _lastNode = newNode; - } + if (_firstNode != null) + _firstNode.Previous = null; - // Increment the count. - _count++; + // Decrement count. + _count--; } + else if (index == Count - 1) + { + _lastNode = _lastNode.Previous; - /// - /// Inserts the a new key-value item at the specified index. - /// - public virtual void InsertAt(int index, TKey key, TValue value) + if (_lastNode != null) + _lastNode.Next = null; + + // Decrement count. + _count--; + } + else { - if (index == 0) - { - Prepend(key, value); - } - else if (index == Count) - { - Append(key, value); - } - else if (index > 0 && index < Count) + int i = 0; + var currentNode = _firstNode; + + // Get currentNode to reference the element at the index. + while (i < index) { - DLinkedListNode currentNode = null; - var newNode = new DLinkedListNode(key, value); + currentNode = currentNode.Next; + i++; + }//end-while - // Decide from which reference to traverse the list, and then move the currentNode reference to the index - // If index > half then traverse it from the end (_lastNode reference) - // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > Count / 2) - { - currentNode = _lastNode; - for (int i = Count - 1; i > index - 1; --i) - { - currentNode = currentNode.Previous; - } - } - else - { - currentNode = _firstNode; - for (int i = 0; i < index - 1; ++i) - { - currentNode = currentNode.Next; - } - } - newNode.Next = currentNode.Next; - currentNode.Next = newNode; - newNode.Previous = currentNode; + // Remove element + var newPrevious = currentNode.Previous; + var newNext = currentNode.Next; + newPrevious.Next = newNext; - // Increment the count - _count++; - } - else - { - throw new IndexOutOfRangeException(); - } - } + if (newNext != null) + newNext.Previous = newPrevious; - /// - /// Inserts the key-value after specified index. - /// - public virtual void InsertAfter(int index, TKey key, TValue value) - { - // Insert at previous index. - InsertAt(index - 1, key, value); - } + currentNode = newPrevious; + + // Decrement count. + _count--; + }//end-else + } - /// - /// Removes the item at the specified index. - /// - public virtual void RemoveAt(int index) + /// + /// Removes the item with the specified key. + /// + public virtual void RemoveBy(TKey key) + { + // Remove + if (key.IsEqualTo(_firstNode.Key)) { - // Handle index out of bound errors - if (IsEmpty() || index < 0 || index >= Count) - throw new IndexOutOfRangeException(); + _firstNode = _firstNode.Next; - // Remove - if (index == 0) - { - _firstNode = _firstNode.Next; + if (_firstNode != null) + _firstNode.Previous = null; - if (_firstNode != null) - _firstNode.Previous = null; + // Decrement count. + _count--; + } + else if (key.IsEqualTo(_lastNode.Key)) + { + _lastNode = _lastNode.Previous; - // Decrement count. - _count--; - } - else if (index == Count - 1) - { - _lastNode = _lastNode.Previous; + if (_lastNode != null) + _lastNode.Next = null; - if (_lastNode != null) - _lastNode.Next = null; + // Decrement count. + _count--; + } + else + { + var currentNode = _firstNode; - // Decrement count. - _count--; - } - else + // Get currentNode to reference the element at the index. + while (currentNode != null) { - int i = 0; - var currentNode = _firstNode; - - // Get currentNode to reference the element at the index. - while (i < index) - { - currentNode = currentNode.Next; - i++; - }//end-while + if (currentNode.Key.IsEqualTo(key)) + break; + currentNode = currentNode.Next; + }//end-while + if (currentNode != null) + { // Remove element var newPrevious = currentNode.Previous; var newNext = currentNode.Next; @@ -534,279 +590,221 @@ public virtual void RemoveAt(int index) currentNode = newPrevious; - // Decrement count. - _count--; - }//end-else - } - - /// - /// Removes the item with the specified key. - /// - public virtual void RemoveBy(TKey key) - { - // Remove - if (key.IsEqualTo(_firstNode.Key)) - { - _firstNode = _firstNode.Next; - - if (_firstNode != null) - _firstNode.Previous = null; - // Decrement count. _count--; } - else if (key.IsEqualTo(_lastNode.Key)) + else { - _lastNode = _lastNode.Previous; + throw new KeyNotFoundException(); + } + }//end-else + } - if (_lastNode != null) - _lastNode.Next = null; + /// + /// Updates the value of an element at the specified index. + /// + public virtual void UpdateValueByIndex(int index, TValue value) + { + if (IsEmpty() || index < 0 || index >= Count) + throw new IndexOutOfRangeException(); - // Decrement count. - _count--; - } - else - { - var currentNode = _firstNode; + _setValueByIndex(index, value); + } - // Get currentNode to reference the element at the index. - while (currentNode != null) - { - if (currentNode.Key.IsEqualTo(key)) - break; + /// + /// Updates the value of an element by it's key. + /// + public virtual void UpdateValueByKey(TKey key, TValue value) + { + if (IsEmpty()) + throw new IndexOutOfRangeException(); - currentNode = currentNode.Next; - }//end-while + _setValueByKey(key, value); + } - if (currentNode != null) - { - // Remove element - var newPrevious = currentNode.Previous; - var newNext = currentNode.Next; - newPrevious.Next = newNext; + /// + /// Updates the key and value of an element at the specified index. + /// + public virtual void UpdateAtIndex(int index, TKey key, TValue value) + { + if (IsEmpty() || index < 0 || index >= Count) + throw new IndexOutOfRangeException(); - if (newNext != null) - newNext.Previous = newPrevious; + _setNodeByIndex(index, key, value); + } - currentNode = newPrevious; + /// + /// Clears the list. + /// + public virtual void Clear() + { + _count = 0; + _firstNode = _lastNode = null; + } - // Decrement count. - _count--; - } - else - { - throw new KeyNotFoundException(); - } - }//end-else - } + /// + /// Chesk whether the specified key exists in the list. + /// + public virtual bool ContainsKey(TKey key) + { + if (IsEmpty()) + throw new Exception("List is empty."); - /// - /// Updates the value of an element at the specified index. - /// - public virtual void UpdateValueByIndex(int index, TValue value) + try { - if (IsEmpty() || index < 0 || index >= Count) - throw new IndexOutOfRangeException(); - - _setValueByIndex(index, value); + return Find(key).Key.IsEqualTo(key); + } + catch (Exception) + { + return false; } + } - /// - /// Updates the value of an element by it's key. - /// - public virtual void UpdateValueByKey(TKey key, TValue value) + /// + /// Find the specified item in the list. + /// + public virtual KeyValuePair Find(TKey key) + { + if (IsEmpty()) + throw new Exception("List is empty."); + + var currentNode = _firstNode; + while (currentNode != null) { - if (IsEmpty()) - throw new IndexOutOfRangeException(); + if (currentNode.Key.IsEqualTo(key)) + break; - _setValueByKey(key, value); + currentNode = currentNode.Next; } - /// - /// Updates the key and value of an element at the specified index. - /// - public virtual void UpdateAtIndex(int index, TKey key, TValue value) + if (currentNode != null) + return new KeyValuePair(currentNode.Key, currentNode.Value); + throw new KeyNotFoundException("Item was not found."); + } + + /// + /// Find all elements in list that match the predicate. + /// + /// Predicate function. + /// List of elements. + public virtual List> FindAll(Predicate match) + { + if (IsEmpty()) + throw new Exception("List is empty."); + + var currentNode = _firstNode; + var list = new List>(); + + while (currentNode != null) { - if (IsEmpty() || index < 0 || index >= Count) - throw new IndexOutOfRangeException(); + if (match(currentNode.Key)) + list.Add(new KeyValuePair(currentNode.Key, currentNode.Value)); - _setNodeByIndex(index, key, value); + currentNode = currentNode.Next; } - /// - /// Clears the list. - /// - public virtual void Clear() + return list; + } + + /// + /// Returns a number of elements as specified by countOfElements, starting from the specified index. + /// + /// Starting index. + /// The number of elements to return. + /// Doubly-Linked List of elements + public virtual List> GetRange(int index, int countOfElements) + { + DLinkedListNode currentNode = null; + List> newList = new List>(); + + // Handle Index out of Bound errors + if (Count == 0) { - _count = 0; - _firstNode = _lastNode = null; + return newList; } - /// - /// Chesk whether the specified key exists in the list. - /// - public virtual bool ContainsKey(TKey key) + if (index < 0 || index > Count) { - if (IsEmpty()) - throw new Exception("List is empty."); - - try - { - return Find(key).Key.IsEqualTo(key); - } - catch (Exception) - { - return false; - } + throw new IndexOutOfRangeException(); } - /// - /// Find the specified item in the list. - /// - public virtual KeyValuePair Find(TKey key) + // Decide from which reference to traverse the list, and then move the currentNode reference to the index + // If index > half then traverse it from the end (_lastNode reference) + // Otherwise, traverse it from the beginning (_firstNode refrence) + if (index > Count / 2) { - if (IsEmpty()) - throw new Exception("List is empty."); - - var currentNode = _firstNode; - while (currentNode != null) + currentNode = _lastNode; + for (int i = Count - 1; i > index; --i) { - if (currentNode.Key.IsEqualTo(key)) - break; - - currentNode = currentNode.Next; + currentNode = currentNode.Previous; } - - if (currentNode != null) - return new KeyValuePair(currentNode.Key, currentNode.Value); - throw new KeyNotFoundException("Item was not found."); } - - /// - /// Find all elements in list that match the predicate. - /// - /// Predicate function. - /// List of elements. - public virtual List> FindAll(Predicate match) + else { - if (IsEmpty()) - throw new Exception("List is empty."); - - var currentNode = _firstNode; - var list = new List>(); - - while (currentNode != null) + currentNode = _firstNode; + for (int i = 0; i < index; ++i) { - if (match(currentNode.Key)) - list.Add(new KeyValuePair(currentNode.Key, currentNode.Value)); - currentNode = currentNode.Next; } - - return list; } - /// - /// Returns a number of elements as specified by countOfElements, starting from the specified index. - /// - /// Starting index. - /// The number of elements to return. - /// Doubly-Linked List of elements - public virtual List> GetRange(int index, int countOfElements) + // Append the elements to the new list using the currentNode reference + while (currentNode != null && newList.Count <= countOfElements) { - DLinkedListNode currentNode = null; - List> newList = new List>(); + var keyValue = new KeyValuePair(currentNode.Key, currentNode.Value); + newList.Add(keyValue); + currentNode = currentNode.Next; + } - // Handle Index out of Bound errors - if (Count == 0) - { - return newList; - } + return newList; + } - if (index < 0 || index > Count) - { - throw new IndexOutOfRangeException(); - } + /// + /// Sorts the entire list using Selection Sort. + /// + public virtual void SelectionSort() + { + if (IsEmpty()) + return; - // Decide from which reference to traverse the list, and then move the currentNode reference to the index - // If index > half then traverse it from the end (_lastNode reference) - // Otherwise, traverse it from the beginning (_firstNode refrence) - if (index > Count / 2) - { - currentNode = _lastNode; - for (int i = Count - 1; i > index; --i) - { - currentNode = currentNode.Previous; - } - } - else + var currentNode = _firstNode; + while (currentNode != null) + { + var nextNode = currentNode.Next; + while (nextNode != null) { - currentNode = _firstNode; - for (int i = 0; i < index; ++i) + if (nextNode.Key.IsLessThan(currentNode.Key)) { - currentNode = currentNode.Next; + var temp = nextNode.Key; + nextNode.Key = currentNode.Key; + currentNode.Key = temp; } - } - // Append the elements to the new list using the currentNode reference - while (currentNode != null && newList.Count <= countOfElements) - { - var keyValue = new KeyValuePair(currentNode.Key, currentNode.Value); - newList.Add(keyValue); - currentNode = currentNode.Next; + nextNode = nextNode.Next; } - return newList; + currentNode = currentNode.Next; } + } - /// - /// Sorts the entire list using Selection Sort. - /// - public virtual void SelectionSort() - { - if (IsEmpty()) - return; - - var currentNode = _firstNode; - while (currentNode != null) - { - var nextNode = currentNode.Next; - while (nextNode != null) - { - if (nextNode.Key.IsLessThan(currentNode.Key)) - { - var temp = nextNode.Key; - nextNode.Key = currentNode.Key; - currentNode.Key = temp; - } - - nextNode = nextNode.Next; - } - - currentNode = currentNode.Next; - } - } + /// + /// Returns the list items as a readable multi--line string. + /// + /// + public virtual string ToReadable() + { + string listAsString = string.Empty; + int i = 0; + var currentNode = _firstNode; - /// - /// Returns the list items as a readable multi--line string. - /// - /// - public virtual string ToReadable() + while (currentNode != null) { - string listAsString = string.Empty; - int i = 0; - var currentNode = _firstNode; - - while (currentNode != null) - { - listAsString = String.Format("{0}[{1}] => {2}\r\n", listAsString, i, currentNode.Key); - currentNode = currentNode.Next; - ++i; - } - - return listAsString; + listAsString = String.Format("{0}[{1}] => {2}\r\n", listAsString, i, currentNode.Key); + currentNode = currentNode.Next; + ++i; } + return listAsString; } -} +} \ No newline at end of file diff --git a/DataStructures/Lists/Queue.cs b/DataStructures/Lists/Queue.cs index 77a10515..6e5daa4a 100644 --- a/DataStructures/Lists/Queue.cs +++ b/DataStructures/Lists/Queue.cs @@ -1,242 +1,240 @@ using System; using System.Collections.Generic; -namespace DataStructures.Lists +namespace DataStructures.Lists; + +/// +/// The Queue (FIFO) Data Structure. +/// +public class Queue : IEnumerable where T : IComparable { /// - /// The Queue (FIFO) Data Structure. + /// INSTANCE VARIABLE. /// - public class Queue : IEnumerable where T : IComparable + private int _size { get; set; } + private int _headPointer { get; set; } + private int _tailPointer { get; set; } + + // The internal collection. + private T[] _collection { get; set; } + private const int _defaultCapacity = 8; + + // This sets the default maximum array length to refer to MAXIMUM_ARRAY_LENGTH_x64 + // Set the flag IsMaximumCapacityReached to false + bool DefaultMaxCapacityIsX64 = true; + bool IsMaximumCapacityReached = false; + + // The C# Maximum Array Length (before encountering overflow) + // Reference: http://referencesource.microsoft.com/#mscorlib/system/array.cs,2d2b551eabe74985 + public const int MAXIMUM_ARRAY_LENGTH_x64 = 0X7FEFFFFF; //x64 + public const int MAXIMUM_ARRAY_LENGTH_x86 = 0x8000000; //x86 + + + /// + /// CONSTRUCTOR + /// + public Queue() : this(_defaultCapacity) { } + + public Queue(int initialCapacity) { - /// - /// INSTANCE VARIABLE. - /// - private int _size { get; set; } - private int _headPointer { get; set; } - private int _tailPointer { get; set; } - - // The internal collection. - private T[] _collection { get; set; } - private const int _defaultCapacity = 8; - - // This sets the default maximum array length to refer to MAXIMUM_ARRAY_LENGTH_x64 - // Set the flag IsMaximumCapacityReached to false - bool DefaultMaxCapacityIsX64 = true; - bool IsMaximumCapacityReached = false; - - // The C# Maximum Array Length (before encountering overflow) - // Reference: http://referencesource.microsoft.com/#mscorlib/system/array.cs,2d2b551eabe74985 - public const int MAXIMUM_ARRAY_LENGTH_x64 = 0X7FEFFFFF; //x64 - public const int MAXIMUM_ARRAY_LENGTH_x86 = 0x8000000; //x86 - - - /// - /// CONSTRUCTOR - /// - public Queue() : this(_defaultCapacity) { } - - public Queue(int initialCapacity) + if (initialCapacity < 0) { - if (initialCapacity < 0) - { - throw new ArgumentOutOfRangeException(); - } - - _size = 0; - _headPointer = 0; - _tailPointer = 0; - _collection = new T[initialCapacity]; + throw new ArgumentOutOfRangeException(); } + _size = 0; + _headPointer = 0; + _tailPointer = 0; + _collection = new T[initialCapacity]; + } + - /// - /// Resize the internal array to a new size. - /// - private void _resize(int newSize) + /// + /// Resize the internal array to a new size. + /// + private void _resize(int newSize) + { + if (newSize > _size && !IsMaximumCapacityReached) { - if (newSize > _size && !IsMaximumCapacityReached) - { - int capacity = _collection.Length == 0 ? _defaultCapacity : _collection.Length * 2; + int capacity = _collection.Length == 0 ? _defaultCapacity : _collection.Length * 2; - // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. - // Note that this check works even when _items.Length overflowed thanks to the (uint) cast - int maxCapacity = DefaultMaxCapacityIsX64 == true ? MAXIMUM_ARRAY_LENGTH_x64 : MAXIMUM_ARRAY_LENGTH_x86; + // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. + // Note that this check works even when _items.Length overflowed thanks to the (uint) cast + int maxCapacity = DefaultMaxCapacityIsX64 == true ? MAXIMUM_ARRAY_LENGTH_x64 : MAXIMUM_ARRAY_LENGTH_x86; - // Handle the new proper size - if (capacity < newSize) - capacity = newSize; + // Handle the new proper size + if (capacity < newSize) + capacity = newSize; - if (capacity >= maxCapacity) - { - capacity = maxCapacity - 1; - IsMaximumCapacityReached = true; - } + if (capacity >= maxCapacity) + { + capacity = maxCapacity - 1; + IsMaximumCapacityReached = true; + } - // Try resizing and handle overflow - try - { - //Array.Resize (ref _collection, newSize); + // Try resizing and handle overflow + try + { + //Array.Resize (ref _collection, newSize); - var tempCollection = new T[newSize]; - Array.Copy(_collection, _headPointer, tempCollection, 0, _size); - _collection = tempCollection; + var tempCollection = new T[newSize]; + Array.Copy(_collection, _headPointer, tempCollection, 0, _size); + _collection = tempCollection; + } + catch (OutOfMemoryException) + { + if (DefaultMaxCapacityIsX64 == true) + { + DefaultMaxCapacityIsX64 = false; + _resize(capacity); } - catch (OutOfMemoryException) + else { - if (DefaultMaxCapacityIsX64 == true) - { - DefaultMaxCapacityIsX64 = false; - _resize(capacity); - } - else - { - throw; - } + throw; } } } + } - /// - /// Returns count of elements in queue - /// - public int Count => _size; + /// + /// Returns count of elements in queue + /// + public int Count => _size; - /// - /// Checks whether the queue is empty. - /// - public bool IsEmpty => _size == 0; + /// + /// Checks whether the queue is empty. + /// + public bool IsEmpty => _size == 0; - /// - /// Returns the top element in queue - /// - public T Top + /// + /// Returns the top element in queue + /// + public T Top + { + get { - get - { - if (IsEmpty) - throw new Exception("Queue is empty."); + if (IsEmpty) + throw new Exception("Queue is empty."); - return _collection[_headPointer]; - } + return _collection[_headPointer]; } + } - /// - /// Inserts an element at the end of the queue - /// - /// Element to be inserted. - public void Enqueue(T dataItem) + /// + /// Inserts an element at the end of the queue + /// + /// Element to be inserted. + public void Enqueue(T dataItem) + { + if (_size == _collection.Length) { - if (_size == _collection.Length) + try { - try - { - _resize(_collection.Length * 2); - } - catch (OutOfMemoryException ex) - { - throw ex; - } + _resize(_collection.Length * 2); } + catch (OutOfMemoryException ex) + { + throw ex; + } + } - // Enqueue item at tail and then increment tail - _collection[_tailPointer++] = dataItem; - - // Wrap around - if (_tailPointer == _collection.Length) - _tailPointer = 0; + // Enqueue item at tail and then increment tail + _collection[_tailPointer++] = dataItem; - // Increment size - _size++; - } + // Wrap around + if (_tailPointer == _collection.Length) + _tailPointer = 0; - /// - /// Removes the Top Element from queue, and assigns it's value to the "top" parameter. - /// - /// The top element container. - public T Dequeue() - { - if (IsEmpty) - throw new Exception("Queue is empty."); + // Increment size + _size++; + } - var topItem = _collection[_headPointer]; - _collection[_headPointer] = default; + /// + /// Removes the Top Element from queue, and assigns it's value to the "top" parameter. + /// + /// The top element container. + public T Dequeue() + { + if (IsEmpty) + throw new Exception("Queue is empty."); - // Decrement the size - _size--; + var topItem = _collection[_headPointer]; + _collection[_headPointer] = default; - // Increment the head pointer - _headPointer++; + // Decrement the size + _size--; - // Reset the pointer - if (_headPointer == _collection.Length) - _headPointer = 0; + // Increment the head pointer + _headPointer++; - // Shrink the internal collection - if (_size > 0 && _collection.Length > _defaultCapacity && _size <= _collection.Length / 4) - { - // Get head and tail - var head = _collection[_headPointer]; - var tail = _collection[_tailPointer]; + // Reset the pointer + if (_headPointer == _collection.Length) + _headPointer = 0; - // Shrink - _resize(_collection.Length / 3 * 2); + // Shrink the internal collection + if (_size > 0 && _collection.Length > _defaultCapacity && _size <= _collection.Length / 4) + { + // Get head and tail + var head = _collection[_headPointer]; + var tail = _collection[_tailPointer]; - // Update head and tail pointers - _headPointer = Array.IndexOf(_collection, head); - _tailPointer = Array.IndexOf(_collection, tail); - } + // Shrink + _resize(_collection.Length / 3 * 2); - return topItem; + // Update head and tail pointers + _headPointer = Array.IndexOf(_collection, head); + _tailPointer = Array.IndexOf(_collection, tail); } - /// - /// Returns an array version of this queue. - /// - /// System.Array. - public T[] ToArray() - { - var array = new T[_size]; + return topItem; + } - int j = 0; - for (int i = 0; i < _size; ++i) - { - array[j] = _collection[_headPointer + i]; - j++; - } + /// + /// Returns an array version of this queue. + /// + /// System.Array. + public T[] ToArray() + { + var array = new T[_size]; - return array; + int j = 0; + for (int i = 0; i < _size; ++i) + { + array[j] = _collection[_headPointer + i]; + j++; } - /// - /// Returns a human-readable, multi-line, print-out (string) of this queue. - /// - public string ToHumanReadable() - { - var array = ToArray(); - string listAsString = string.Empty; + return array; + } - int i = 0; - for (i = 0; i < Count; ++i) - listAsString = String.Format("{0}[{1}] => {2}\r\n", listAsString, i, array[i]); + /// + /// Returns a human-readable, multi-line, print-out (string) of this queue. + /// + public string ToHumanReadable() + { + var array = ToArray(); + string listAsString = string.Empty; - return listAsString; - } + int i = 0; + for (i = 0; i < Count; ++i) + listAsString = String.Format("{0}[{1}] => {2}\r\n", listAsString, i, array[i]); + return listAsString; + } - /********************************************************************************/ + /********************************************************************************/ - public IEnumerator GetEnumerator() - { - return _collection.GetEnumerator() as IEnumerator; - } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + public IEnumerator GetEnumerator() + { + return _collection.GetEnumerator() as IEnumerator; + } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); } -} +} \ No newline at end of file diff --git a/DataStructures/Lists/SLinkedList.cs b/DataStructures/Lists/SLinkedList.cs index 66d2595b..6ab25b56 100644 --- a/DataStructures/Lists/SLinkedList.cs +++ b/DataStructures/Lists/SLinkedList.cs @@ -3,470 +3,468 @@ using DataStructures.Common; -namespace DataStructures.Lists +namespace DataStructures.Lists; + +/// +/// The Singly-Linked List Node class +/// +/// +public class SLinkedListNode : IComparable> where T : IComparable { - /// - /// The Singly-Linked List Node class - /// - /// - public class SLinkedListNode : IComparable> where T : IComparable + public SLinkedListNode() { - public SLinkedListNode() - { - Next = null; - Data = default; - } + Next = null; + Data = default; + } - public SLinkedListNode(T dataItem) - { - Next = null; - Data = dataItem; - } + public SLinkedListNode(T dataItem) + { + Next = null; + Data = dataItem; + } - public T Data { get; set; } + public T Data { get; set; } - public SLinkedListNode Next { get; set; } + public SLinkedListNode Next { get; set; } - public int CompareTo(SLinkedListNode other) - { - if (other == null) return -1; + public int CompareTo(SLinkedListNode other) + { + if (other == null) return -1; - return Data.CompareTo(other.Data); - } + return Data.CompareTo(other.Data); } +} + +/// +/// Singly Linked List Data Structure +/// +public class SLinkedList : IEnumerable where T : IComparable +{ + private SLinkedListNode _firstNode { get; set; } + private SLinkedListNode _lastNode { get; set; } /// - /// Singly Linked List Data Structure + /// Instance variables /// - public class SLinkedList : IEnumerable where T : IComparable - { - private SLinkedListNode _firstNode { get; set; } - private SLinkedListNode _lastNode { get; set; } + public int Count { get; private set; } - /// - /// Instance variables - /// - public int Count { get; private set; } + public virtual SLinkedListNode Head => _firstNode; - public virtual SLinkedListNode Head => _firstNode; - - /// - /// CONSTRUCTOR - /// - public SLinkedList() - { - _firstNode = null; - _lastNode = null; - Count = 0; - } + /// + /// CONSTRUCTOR + /// + public SLinkedList() + { + _firstNode = null; + _lastNode = null; + Count = 0; + } - /// - /// The Is List Empty check. - /// - /// true, if the list is empty, false otherwise. - public bool IsEmpty() - { - return Count == 0; - } + /// + /// The Is List Empty check. + /// + /// true, if the list is empty, false otherwise. + public bool IsEmpty() + { + return Count == 0; + } - /// - /// Getter function that returns the first element - /// - public T First => _firstNode == null ? default : _firstNode.Data; + /// + /// Getter function that returns the first element + /// + public T First => _firstNode == null ? default : _firstNode.Data; - /// - /// Getter function that returns the last element - /// - public T Last + /// + /// Getter function that returns the last element + /// + public T Last + { + get { - get + if (Count == 0) { - if (Count == 0) - { - throw new Exception("Empty list."); - } + throw new Exception("Empty list."); + } - if (_lastNode == null) + if (_lastNode == null) + { + var currentNode = _firstNode; + while (currentNode.Next != null) { - var currentNode = _firstNode; - while (currentNode.Next != null) - { - currentNode = currentNode.Next; - } - _lastNode = currentNode; - return currentNode.Data; + currentNode = currentNode.Next; } - - return _lastNode.Data; + _lastNode = currentNode; + return currentNode.Data; } + + return _lastNode.Data; } + } + + /// + /// Inserts the specified dataItem at the beginning of the list. + /// + /// The data value to be inserted to the list. + public void Prepend(T dataItem) + { + SLinkedListNode newNode = new SLinkedListNode(dataItem); - /// - /// Inserts the specified dataItem at the beginning of the list. - /// - /// The data value to be inserted to the list. - public void Prepend(T dataItem) + if (_firstNode == null) + { + _firstNode = _lastNode = newNode; + } + else { - SLinkedListNode newNode = new SLinkedListNode(dataItem); + var currentNode = _firstNode; + newNode.Next = currentNode; + _firstNode = newNode; + } - if (_firstNode == null) - { - _firstNode = _lastNode = newNode; - } - else - { - var currentNode = _firstNode; - newNode.Next = currentNode; - _firstNode = newNode; - } + // Increment the count. + Count++; + } - // Increment the count. - Count++; + /// + /// Inserts the specified dataItem at the end of the list. + /// + /// The data value to be inserted to the list. + public void Append(T dataItem) + { + SLinkedListNode newNode = new SLinkedListNode(dataItem); + + if (_firstNode == null) + { + _firstNode = _lastNode = newNode; + } + else + { + var currentNode = _lastNode; + currentNode.Next = newNode; + _lastNode = newNode; } - /// - /// Inserts the specified dataItem at the end of the list. - /// - /// The data value to be inserted to the list. - public void Append(T dataItem) + // Increment the count. + Count++; + } + + /// + /// Inserts a specified item dataItem at an index. + /// + /// Data item. + /// Index. + public void InsertAt(T dataItem, int index) + { + // Handle scope of insertion. + // Prepend? Append? Or Insert in the range? + if (index == 0) { - SLinkedListNode newNode = new SLinkedListNode(dataItem); + Prepend(dataItem); + } + else if (index == Count) + { + Append(dataItem); + } + else if (index > 0 && index < Count) + { + var currentNode = _firstNode; + var newNode = new SLinkedListNode(dataItem); - if (_firstNode == null) + for (int i = 1; i < index; ++i) { - _firstNode = _lastNode = newNode; - } - else - { - var currentNode = _lastNode; - currentNode.Next = newNode; - _lastNode = newNode; + currentNode = currentNode.Next; } - // Increment the count. + newNode.Next = currentNode.Next; + currentNode.Next = newNode; + + // Increment the count Count++; } - - /// - /// Inserts a specified item dataItem at an index. - /// - /// Data item. - /// Index. - public void InsertAt(T dataItem, int index) + else { - // Handle scope of insertion. - // Prepend? Append? Or Insert in the range? - if (index == 0) - { - Prepend(dataItem); - } - else if (index == Count) - { - Append(dataItem); - } - else if (index > 0 && index < Count) - { - var currentNode = _firstNode; - var newNode = new SLinkedListNode(dataItem); + throw new IndexOutOfRangeException(); + } + } - for (int i = 1; i < index; ++i) - { - currentNode = currentNode.Next; - } + /// + /// Removes the item at the specified index. + /// + /// The index of the list node to be removed. + public void RemoveAt(int index) + { + // Handle index out of bound errors + if (IsEmpty() || index < 0 || index >= Count) + throw new IndexOutOfRangeException(); - newNode.Next = currentNode.Next; - currentNode.Next = newNode; + // Remove + if (index == 0) + { + _firstNode = _firstNode.Next; - // Increment the count - Count++; - } - else - { - throw new IndexOutOfRangeException(); - } + // Decrement count. + Count--; } - - /// - /// Removes the item at the specified index. - /// - /// The index of the list node to be removed. - public void RemoveAt(int index) + else if (index == Count - 1) { - // Handle index out of bound errors - if (IsEmpty() || index < 0 || index >= Count) - throw new IndexOutOfRangeException(); - - // Remove - if (index == 0) - { - _firstNode = _firstNode.Next; - - // Decrement count. - Count--; - } - else if (index == Count - 1) - { - var currentNode = _firstNode; + var currentNode = _firstNode; - while (currentNode.Next != null && currentNode.Next != _lastNode) - currentNode = currentNode.Next; + while (currentNode.Next != null && currentNode.Next != _lastNode) + currentNode = currentNode.Next; - currentNode.Next = null; - _lastNode = currentNode; + currentNode.Next = null; + _lastNode = currentNode; - // Decrement count. - Count--; - } - else + // Decrement count. + Count--; + } + else + { + int i = 0; + var currentNode = _firstNode; + while (currentNode.Next != null) { - int i = 0; - var currentNode = _firstNode; - while (currentNode.Next != null) + if (i + 1 == index) { - if (i + 1 == index) - { - currentNode.Next = currentNode.Next.Next; + currentNode.Next = currentNode.Next.Next; - // Decrement the count. - Count--; - break; - } - - ++i; - currentNode = currentNode.Next; + // Decrement the count. + Count--; + break; } + + ++i; + currentNode = currentNode.Next; } } + } + + /// + /// Clears all the items in the list. + /// + public void Clear() + { + _firstNode = null; + _lastNode = null; + Count = 0; + } - /// - /// Clears all the items in the list. - /// - public void Clear() + /// + /// Get the element at the specified index + /// + /// Index of element + /// Element + public T GetAt(int index) + { + if (index == 0) { - _firstNode = null; - _lastNode = null; - Count = 0; + return First; } - /// - /// Get the element at the specified index - /// - /// Index of element - /// Element - public T GetAt(int index) + if (index == Count - 1) { - if (index == 0) - { - return First; - } - - if (index == Count - 1) - { - return Last; - } - - if (index > 0 && index < Count - 1) - { - var currentNode = _firstNode; - for (int i = 0; i < index; ++i) - { - currentNode = currentNode.Next; - } - return currentNode.Data; - } - - throw new IndexOutOfRangeException(); + return Last; } - /// - /// Returns a number of elements as specified by countOfElements, starting from the specified index. - /// - /// Starting index. - /// The number of elements to return. - /// Singly-Linked List of elements - public SLinkedList GetRange(int index, int countOfElements) + if (index > 0 && index < Count - 1) { - SLinkedList newList = new SLinkedList(); var currentNode = _firstNode; - - // Handle Index out of Bound errors - if (Count == 0) - { - return newList; - } - - if (index < 0 || index > Count) - { - throw new IndexOutOfRangeException(); - } - - // Move the currentNode reference to the specified index for (int i = 0; i < index; ++i) { currentNode = currentNode.Next; } + return currentNode.Data; + } - // Append the elements to the new list using the currentNode reference - while (currentNode != null && newList.Count <= countOfElements) - { - newList.Append(currentNode.Data); - currentNode = currentNode.Next; - } + throw new IndexOutOfRangeException(); + } + + /// + /// Returns a number of elements as specified by countOfElements, starting from the specified index. + /// + /// Starting index. + /// The number of elements to return. + /// Singly-Linked List of elements + public SLinkedList GetRange(int index, int countOfElements) + { + SLinkedList newList = new SLinkedList(); + var currentNode = _firstNode; + // Handle Index out of Bound errors + if (Count == 0) + { return newList; } - /// - /// Sorts the entire list using Selection Sort. - /// - public virtual void SelectionSort() + if (index < 0 || index > Count) { - if (IsEmpty()) - return; - - var currentNode = _firstNode; - while (currentNode != null) - { - var minNode = currentNode; - var nextNode = currentNode.Next; - while (nextNode != null) - { - if (nextNode.Data.IsLessThan(minNode.Data)) - { - minNode = nextNode; - } - - nextNode = nextNode.Next; - } + throw new IndexOutOfRangeException(); + } - if (minNode != currentNode) - { - var temp = minNode.Data; - minNode.Data = currentNode.Data; - currentNode.Data = temp; - } - currentNode = currentNode.Next; - } + // Move the currentNode reference to the specified index + for (int i = 0; i < index; ++i) + { + currentNode = currentNode.Next; } - /// - /// Return an array version of this list. - /// - /// - public T[] ToArray() + // Append the elements to the new list using the currentNode reference + while (currentNode != null && newList.Count <= countOfElements) { - T[] array = new T[Count]; + newList.Append(currentNode.Data); + currentNode = currentNode.Next; + } - var currentNode = _firstNode; - for (int i = 0; i < Count; ++i) - { - if (currentNode != null) - { - array[i] = currentNode.Data; - currentNode = currentNode.Next; - } - else - { - break; - } - } + return newList; + } - return array; - } + /// + /// Sorts the entire list using Selection Sort. + /// + public virtual void SelectionSort() + { + if (IsEmpty()) + return; - /// - /// Returns a System.List version of this SLinkedList instace. - /// - /// System.List of elements - public List ToList() + var currentNode = _firstNode; + while (currentNode != null) { - List list = new List(); - - var currentNode = _firstNode; - for (int i = 0; i < Count; ++i) + var minNode = currentNode; + var nextNode = currentNode.Next; + while (nextNode != null) { - if (currentNode != null) + if (nextNode.Data.IsLessThan(minNode.Data)) { - list.Add(currentNode.Data); - currentNode = currentNode.Next; - } - else - { - break; + minNode = nextNode; } + + nextNode = nextNode.Next; } - return list; + if (minNode != currentNode) + { + var temp = minNode.Data; + minNode.Data = currentNode.Data; + currentNode.Data = temp; + } + currentNode = currentNode.Next; } + } - /// - /// Returns the list items as a readable multi--line string. - /// - /// - public string ToReadable() - { - int i = 0; - var currentNode = _firstNode; - string listAsString = string.Empty; + /// + /// Return an array version of this list. + /// + /// + public T[] ToArray() + { + T[] array = new T[Count]; - while (currentNode != null) + var currentNode = _firstNode; + for (int i = 0; i < Count; ++i) + { + if (currentNode != null) { - listAsString = String.Format("{0}[{1}] => {2}\r\n", listAsString, i, currentNode.Data); + array[i] = currentNode.Data; currentNode = currentNode.Next; - ++i; } - - return listAsString; + else + { + break; + } } - /********************************************************************************/ + return array; + } - public IEnumerator GetEnumerator() + /// + /// Returns a System.List version of this SLinkedList instace. + /// + /// System.List of elements + public List ToList() + { + List list = new List(); + + var currentNode = _firstNode; + for (int i = 0; i < Count; ++i) { - return new SLinkedListEnumerator(this); + if (currentNode != null) + { + list.Add(currentNode.Data); + currentNode = currentNode.Next; + } + else + { + break; + } } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + return list; + } + + /// + /// Returns the list items as a readable multi--line string. + /// + /// + public string ToReadable() + { + int i = 0; + var currentNode = _firstNode; + string listAsString = string.Empty; + + while (currentNode != null) { - return new SLinkedListEnumerator(this); + listAsString = String.Format("{0}[{1}] => {2}\r\n", listAsString, i, currentNode.Data); + currentNode = currentNode.Next; + ++i; } - /********************************************************************************/ + return listAsString; + } - internal class SLinkedListEnumerator : IEnumerator - { - private SLinkedListNode _current; - private SLinkedList _doublyLinkedList; + /********************************************************************************/ - public SLinkedListEnumerator(SLinkedList list) - { - _doublyLinkedList = list; - _current = list.Head; - } + public IEnumerator GetEnumerator() + { + return new SLinkedListEnumerator(this); + } - public T Current => _current.Data; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return new SLinkedListEnumerator(this); + } - object System.Collections.IEnumerator.Current => Current; + /********************************************************************************/ - public bool MoveNext() - { - _current = _current.Next; + internal class SLinkedListEnumerator : IEnumerator + { + private SLinkedListNode _current; + private SLinkedList _doublyLinkedList; - return _current != null; - } + public SLinkedListEnumerator(SLinkedList list) + { + _doublyLinkedList = list; + _current = list.Head; + } - public void Reset() - { - _current = _doublyLinkedList.Head; - } + public T Current => _current.Data; - public void Dispose() - { - _current = null; - _doublyLinkedList = null; - } + object System.Collections.IEnumerator.Current => Current; + + public bool MoveNext() + { + _current = _current.Next; + + return _current != null; } - } -} + public void Reset() + { + _current = _doublyLinkedList.Head; + } + + public void Dispose() + { + _current = null; + _doublyLinkedList = null; + } + } +} \ No newline at end of file diff --git a/DataStructures/Lists/SkipList.cs b/DataStructures/Lists/SkipList.cs index 1c463d5f..f74dd5f1 100644 --- a/DataStructures/Lists/SkipList.cs +++ b/DataStructures/Lists/SkipList.cs @@ -10,343 +10,341 @@ using System.Collections.Generic; using DataStructures.Common; -namespace DataStructures.Lists +namespace DataStructures.Lists; + +/// +/// THE SKIP-LIST DATA STRUCTURE +/// +public class SkipList : ICollection, IEnumerable where T : IComparable { + private int _count { get; set; } + private int _currentMaxLevel { get; set; } + private Random _randomizer { get; set; } + + // The skip-list root node + private SkipListNode _firstNode { get; set; } + + // Readonly values + private readonly int MaxLevel = 32; + private readonly double Probability = 0.5; + + /// - /// THE SKIP-LIST DATA STRUCTURE + /// Private helper. Used in Add method. /// - public class SkipList : ICollection, IEnumerable where T : IComparable + /// + private int _getNextLevel() { - private int _count { get; set; } - private int _currentMaxLevel { get; set; } - private Random _randomizer { get; set; } - - // The skip-list root node - private SkipListNode _firstNode { get; set; } + int lvl = 0; - // Readonly values - private readonly int MaxLevel = 32; - private readonly double Probability = 0.5; + while (_randomizer.NextDouble() < Probability && lvl <= _currentMaxLevel && lvl < MaxLevel) + ++lvl; + return lvl; + } - /// - /// Private helper. Used in Add method. - /// - /// - private int _getNextLevel() - { - int lvl = 0; - - while (_randomizer.NextDouble() < Probability && lvl <= _currentMaxLevel && lvl < MaxLevel) - ++lvl; - return lvl; - } + /// + /// CONSTRUCTOR + /// + public SkipList() + { + _count = 0; + _currentMaxLevel = 1; + _randomizer = new Random(); + _firstNode = new SkipListNode(default, MaxLevel); + for (int i = 0; i < MaxLevel; ++i) + _firstNode.Forwards[i] = _firstNode; + } - /// - /// CONSTRUCTOR - /// - public SkipList() - { - _count = 0; - _currentMaxLevel = 1; - _randomizer = new Random(); - _firstNode = new SkipListNode(default, MaxLevel); - for (int i = 0; i < MaxLevel; ++i) - _firstNode.Forwards[i] = _firstNode; - } + /// + /// Getter accessor for the first node + /// + public SkipListNode Root => _firstNode; + /// + /// Checks if list is empty or not + /// + public bool IsEmpty => Count == 0; - /// - /// Getter accessor for the first node - /// - public SkipListNode Root => _firstNode; - - /// - /// Checks if list is empty or not - /// - public bool IsEmpty => Count == 0; - - /// - /// Return count of elements - /// - public int Count => _count; - - /// - /// Return current max-node level - /// - public int Level => _currentMaxLevel; - - /// - /// Access elements by index - /// - public T this[int index] => throw - // TODO: - new NotImplementedException(); - - /// - /// Adds item to the list - /// - public void Add(T item) - { - var current = _firstNode; - var toBeUpdated = new SkipListNode[MaxLevel]; + /// + /// Return count of elements + /// + public int Count => _count; - for (int i = _currentMaxLevel - 1; i >= 0; --i) - { - while (current.Forwards[i] != _firstNode && current.Forwards[i].Value.IsLessThan(item)) - current = current.Forwards[i]; + /// + /// Return current max-node level + /// + public int Level => _currentMaxLevel; - toBeUpdated[i] = current; - } + /// + /// Access elements by index + /// + public T this[int index] => throw + // TODO: + new NotImplementedException(); - current = current.Forwards[0]; + /// + /// Adds item to the list + /// + public void Add(T item) + { + var current = _firstNode; + var toBeUpdated = new SkipListNode[MaxLevel]; - // Get the next node level, and update list level if required. - int lvl = _getNextLevel(); - if (lvl > _currentMaxLevel) - { - for (int i = _currentMaxLevel; i < lvl; ++i) - toBeUpdated[i] = _firstNode; + for (int i = _currentMaxLevel - 1; i >= 0; --i) + { + while (current.Forwards[i] != _firstNode && current.Forwards[i].Value.IsLessThan(item)) + current = current.Forwards[i]; - _currentMaxLevel = lvl; - } + toBeUpdated[i] = current; + } - // New node - var newNode = new SkipListNode(item, lvl); + current = current.Forwards[0]; - // Insert the new node into the skip list - for (int i = 0; i < lvl; ++i) - { - newNode.Forwards[i] = toBeUpdated[i].Forwards[i]; - toBeUpdated[i].Forwards[i] = newNode; - } + // Get the next node level, and update list level if required. + int lvl = _getNextLevel(); + if (lvl > _currentMaxLevel) + { + for (int i = _currentMaxLevel; i < lvl; ++i) + toBeUpdated[i] = _firstNode; - // Increment the count - ++_count; + _currentMaxLevel = lvl; } - /// - /// Remove element from the list. - /// - public bool Remove(T item) + // New node + var newNode = new SkipListNode(item, lvl); + + // Insert the new node into the skip list + for (int i = 0; i < lvl; ++i) { - T deleted; - return Remove(item, out deleted); + newNode.Forwards[i] = toBeUpdated[i].Forwards[i]; + toBeUpdated[i].Forwards[i] = newNode; } - /// - /// Remove an element from list and then return it - /// - public bool Remove(T item, out T deleted) + // Increment the count + ++_count; + } + + /// + /// Remove element from the list. + /// + public bool Remove(T item) + { + T deleted; + return Remove(item, out deleted); + } + + /// + /// Remove an element from list and then return it + /// + public bool Remove(T item, out T deleted) + { + // Find the node in each of the levels + var current = _firstNode; + var toBeUpdated = new SkipListNode[MaxLevel]; + + // Walk after all the nodes that have values less than the node we are looking for. + // Mark all nodes as toBeUpdated. + for (int i = _currentMaxLevel - 1; i >= 0; --i) { - // Find the node in each of the levels - var current = _firstNode; - var toBeUpdated = new SkipListNode[MaxLevel]; - - // Walk after all the nodes that have values less than the node we are looking for. - // Mark all nodes as toBeUpdated. - for (int i = _currentMaxLevel - 1; i >= 0; --i) - { - while (current.Forwards[i] != _firstNode && current.Forwards[i].Value.IsLessThan(item)) - current = current.Forwards[i]; - - toBeUpdated[i] = current; - } - - current = current.Forwards[0]; - - // Return default value of T if the item was not found - if (current.Value.IsEqualTo(item) == false) - { - deleted = default; - return false; - } - - // We know that the node is in the list. - // Unlink it from the levels where it exists. - for (int i = 0; i < _currentMaxLevel; ++i) - if (toBeUpdated[i].Forwards[i] == current) - toBeUpdated[i].Forwards[i] = current.Forwards[i]; - - // Decrement the count - --_count; - - // Check to see if we've deleted the highest-level node - // Decrement level - while (_currentMaxLevel > 1 && _firstNode.Forwards[_currentMaxLevel - 1] == _firstNode) - --_currentMaxLevel; - - // Assign the deleted output parameter to the node.Value - deleted = current.Value; - return true; + while (current.Forwards[i] != _firstNode && current.Forwards[i].Value.IsLessThan(item)) + current = current.Forwards[i]; + + toBeUpdated[i] = current; } - /// - /// Checks if an item is in the list - /// - public bool Contains(T item) + current = current.Forwards[0]; + + // Return default value of T if the item was not found + if (current.Value.IsEqualTo(item) == false) { - T itemOut; - return Find(item, out itemOut); + deleted = default; + return false; } - /// - /// Look for an element and return it if found - /// - public bool Find(T item, out T result) - { - var current = _firstNode; + // We know that the node is in the list. + // Unlink it from the levels where it exists. + for (int i = 0; i < _currentMaxLevel; ++i) + if (toBeUpdated[i].Forwards[i] == current) + toBeUpdated[i].Forwards[i] = current.Forwards[i]; - // Walk after all the nodes that have values less than the node we are looking for - for (int i = _currentMaxLevel - 1; i >= 0; --i) - while (current.Forwards[i] != _firstNode && current.Forwards[i].Value.IsLessThan(item)) - current = current.Forwards[i]; + // Decrement the count + --_count; - current = current.Forwards[0]; + // Check to see if we've deleted the highest-level node + // Decrement level + while (_currentMaxLevel > 1 && _firstNode.Forwards[_currentMaxLevel - 1] == _firstNode) + --_currentMaxLevel; - // Return true if we found the element; false otherwise - if (current.Value.IsEqualTo(item)) - { - result = current.Value; - return true; - } + // Assign the deleted output parameter to the node.Value + deleted = current.Value; + return true; + } - result = default; - return false; - } + /// + /// Checks if an item is in the list + /// + public bool Contains(T item) + { + T itemOut; + return Find(item, out itemOut); + } - /// - /// Deletes the min element if the list is empty; otherwise throws exception - /// - public T DeleteMin() - { - T min; + /// + /// Look for an element and return it if found + /// + public bool Find(T item, out T result) + { + var current = _firstNode; - if (!TryDeleteMin(out min)) - { - throw new InvalidOperationException("SkipList is empty."); - } + // Walk after all the nodes that have values less than the node we are looking for + for (int i = _currentMaxLevel - 1; i >= 0; --i) + while (current.Forwards[i] != _firstNode && current.Forwards[i].Value.IsLessThan(item)) + current = current.Forwards[i]; - return min; - } + current = current.Forwards[0]; - /// - /// Tries to delete the min element, returns false if list is empty - /// - public bool TryDeleteMin(out T result) + // Return true if we found the element; false otherwise + if (current.Value.IsEqualTo(item)) { - if (IsEmpty) - { - result = default; - return false; - } - - return Remove(_firstNode.Forwards[0].Value, out result); + result = current.Value; + return true; } - /// - /// Returns the first element if the list is not empty; otherwise throw an exception - /// - public T Peek() - { - T peek; + result = default; + return false; + } - if (!TryPeek(out peek)) - { - throw new InvalidOperationException("SkipList is empty."); - } + /// + /// Deletes the min element if the list is empty; otherwise throws exception + /// + public T DeleteMin() + { + T min; - return peek; + if (!TryDeleteMin(out min)) + { + throw new InvalidOperationException("SkipList is empty."); } - /// - /// Tries to return the first element, if the list is empty it returns false - /// - public bool TryPeek(out T result) - { - if (IsEmpty) - { - result = default; - return false; - } + return min; + } - result = _firstNode.Forwards[0].Value; - return true; + /// + /// Tries to delete the min element, returns false if list is empty + /// + public bool TryDeleteMin(out T result) + { + if (IsEmpty) + { + result = default; + return false; } + return Remove(_firstNode.Forwards[0].Value, out result); + } + + /// + /// Returns the first element if the list is not empty; otherwise throw an exception + /// + public T Peek() + { + T peek; - #region IEnumerable Implementation - /// - /// IEnumerable method implementation - /// - public IEnumerator GetEnumerator() + if (!TryPeek(out peek)) { - var node = _firstNode; - while (node.Forwards[0] != null && node.Forwards[0] != _firstNode) - { - node = node.Forwards[0]; - yield return node.Value; - } + throw new InvalidOperationException("SkipList is empty."); } - /// - /// IEnumerable method implementation - /// - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + return peek; + } + + /// + /// Tries to return the first element, if the list is empty it returns false + /// + public bool TryPeek(out T result) + { + if (IsEmpty) { - return GetEnumerator(); + result = default; + return false; } - #endregion IEnumerable Implementation + result = _firstNode.Forwards[0].Value; + return true; + } - #region ICollection Implementation - /// - /// Checks whether this collection is readonly - /// - public bool IsReadOnly => false; - /// - /// Copy this list to an array - /// - public void CopyTo(T[] array, int arrayIndex) + #region IEnumerable Implementation + /// + /// IEnumerable method implementation + /// + public IEnumerator GetEnumerator() + { + var node = _firstNode; + while (node.Forwards[0] != null && node.Forwards[0] != _firstNode) { - // Validate the array and arrayIndex - if (array == null) - throw new ArgumentNullException(); - if (array.Length == 0 || arrayIndex >= array.Length || arrayIndex < 0) - throw new IndexOutOfRangeException(); - - // Get enumerator - var enumarator = GetEnumerator(); - - // Copy elements as long as there is any in the list and as long as the index is within the valid range - for (int i = arrayIndex; i < array.Length; ++i) - { - if (enumarator.MoveNext()) - array[i] = enumarator.Current; - else - break; - } + node = node.Forwards[0]; + yield return node.Value; } + } + + /// + /// IEnumerable method implementation + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + #endregion IEnumerable Implementation - /// - /// Clears this instance - /// - public void Clear() - { - _count = 0; - _currentMaxLevel = 1; - _randomizer = new Random(); - _firstNode = new SkipListNode(default, MaxLevel); - for (int i = 0; i < MaxLevel; ++i) - _firstNode.Forwards[i] = _firstNode; + #region ICollection Implementation + /// + /// Checks whether this collection is readonly + /// + public bool IsReadOnly => false; + + /// + /// Copy this list to an array + /// + public void CopyTo(T[] array, int arrayIndex) + { + // Validate the array and arrayIndex + if (array == null) + throw new ArgumentNullException(); + if (array.Length == 0 || arrayIndex >= array.Length || arrayIndex < 0) + throw new IndexOutOfRangeException(); + + // Get enumerator + var enumarator = GetEnumerator(); + + // Copy elements as long as there is any in the list and as long as the index is within the valid range + for (int i = arrayIndex; i < array.Length; ++i) + { + if (enumarator.MoveNext()) + array[i] = enumarator.Current; + else + break; } - #endregion + } + + /// + /// Clears this instance + /// + public void Clear() + { + _count = 0; + _currentMaxLevel = 1; + _randomizer = new Random(); + _firstNode = new SkipListNode(default, MaxLevel); + for (int i = 0; i < MaxLevel; ++i) + _firstNode.Forwards[i] = _firstNode; } + #endregion -} +} \ No newline at end of file diff --git a/DataStructures/Lists/SkipListNode.cs b/DataStructures/Lists/SkipListNode.cs index 3eace4f5..c9ec8f70 100644 --- a/DataStructures/Lists/SkipListNode.cs +++ b/DataStructures/Lists/SkipListNode.cs @@ -1,54 +1,53 @@ using System; -namespace DataStructures.Lists +namespace DataStructures.Lists; + +public class SkipListNode : IComparable> where T : IComparable { - public class SkipListNode : IComparable> where T : IComparable + /// + /// Instance variables + /// + private T _value; + + /// + /// CONSTRUCTORS + /// + public SkipListNode(T value, int level) + { + if (level < 0) + throw new ArgumentOutOfRangeException("Invalid value for level."); + + Value = value; + Forwards = new SkipListNode[level]; + } + + /// + /// Get and set node's value + /// + public virtual T Value { - /// - /// Instance variables - /// - private T _value; - - /// - /// CONSTRUCTORS - /// - public SkipListNode(T value, int level) - { - if (level < 0) - throw new ArgumentOutOfRangeException("Invalid value for level."); - - Value = value; - Forwards = new SkipListNode[level]; - } - - /// - /// Get and set node's value - /// - public virtual T Value - { - get => _value; - private set => _value = value; - } - - /// - /// Get and set node's forwards links - /// - public virtual SkipListNode[] Forwards { get; private set; } - - /// - /// Return level of node. - /// - public virtual int Level => Forwards.Length; - - /// - /// IComparable method implementation - /// - public int CompareTo(SkipListNode other) - { - if (other == null) - return -1; - - return Value.CompareTo(other.Value); - } + get => _value; + private set => _value = value; + } + + /// + /// Get and set node's forwards links + /// + public virtual SkipListNode[] Forwards { get; private set; } + + /// + /// Return level of node. + /// + public virtual int Level => Forwards.Length; + + /// + /// IComparable method implementation + /// + public int CompareTo(SkipListNode other) + { + if (other == null) + return -1; + + return Value.CompareTo(other.Value); } -} +} \ No newline at end of file diff --git a/DataStructures/Lists/Stack.cs b/DataStructures/Lists/Stack.cs index 1913020a..ab09ee35 100644 --- a/DataStructures/Lists/Stack.cs +++ b/DataStructures/Lists/Stack.cs @@ -1,132 +1,130 @@ using System; using System.Collections.Generic; -namespace DataStructures.Lists +namespace DataStructures.Lists; + +/// +/// The Stack (LIFO) Data Structure. +/// +/// Type +public class Stack : IEnumerable where T : IComparable { /// - /// The Stack (LIFO) Data Structure. + /// Instance variables. + /// _collection: Array-Based List. + /// Count: Public Getter for returning the number of elements. /// - /// Type - public class Stack : IEnumerable where T : IComparable + private ArrayList _collection { get; set; } + public int Count => _collection.Count; + + + /// + /// CONSTRUCTORS + /// + public Stack() { - /// - /// Instance variables. - /// _collection: Array-Based List. - /// Count: Public Getter for returning the number of elements. - /// - private ArrayList _collection { get; set; } - public int Count => _collection.Count; - - - /// - /// CONSTRUCTORS - /// - public Stack() - { - // The internal collection is implemented as an array-based list. - // See the ArrayList.cs for the list implementation. - _collection = new ArrayList(); - } + // The internal collection is implemented as an array-based list. + // See the ArrayList.cs for the list implementation. + _collection = new ArrayList(); + } - public Stack(int initialCapacity) + public Stack(int initialCapacity) + { + if (initialCapacity < 0) { - if (initialCapacity < 0) - { - throw new ArgumentOutOfRangeException(); - } - - // The internal collection is implemented as an array-based list. - // See the ArrayList.cs for the list implementation. - _collection = new ArrayList(initialCapacity); + throw new ArgumentOutOfRangeException(); } + // The internal collection is implemented as an array-based list. + // See the ArrayList.cs for the list implementation. + _collection = new ArrayList(initialCapacity); + } - /// - /// Checks whether the stack is empty. - /// - /// True if stack is empty, false otherwise. - public bool IsEmpty => _collection.IsEmpty; + + /// + /// Checks whether the stack is empty. + /// + /// True if stack is empty, false otherwise. + public bool IsEmpty => _collection.IsEmpty; - /// - /// Returns the top element in the stack. - /// - public T Top + /// + /// Returns the top element in the stack. + /// + public T Top + { + get { - get + try + { + return _collection[_collection.Count - 1]; + } + catch (Exception) { - try - { - return _collection[_collection.Count - 1]; - } - catch (Exception) - { - throw new Exception("Stack is empty."); - } + throw new Exception("Stack is empty."); } } + } - /// - /// Inserts an element at the top of the stack. - /// - /// Element to be inserted. - public void Push(T dataItem) - { - _collection.Add(dataItem); - } + /// + /// Inserts an element at the top of the stack. + /// + /// Element to be inserted. + public void Push(T dataItem) + { + _collection.Add(dataItem); + } - /// - /// Removes the top element from stack. - /// - public T Pop() + /// + /// Removes the top element from stack. + /// + public T Pop() + { + if (Count > 0) { - if (Count > 0) - { - var top = Top; - _collection.RemoveAt(_collection.Count - 1); - return top; - } - - throw new Exception("Stack is empty."); + var top = Top; + _collection.RemoveAt(_collection.Count - 1); + return top; } - /// - /// Returns an array version of this stack. - /// - /// System.Array. - public T[] ToArray() - { - return _collection.ToArray(); - } + throw new Exception("Stack is empty."); + } + /// + /// Returns an array version of this stack. + /// + /// System.Array. + public T[] ToArray() + { + return _collection.ToArray(); + } - /// - /// Returns a human-readable, multi-line, print-out (string) of this stack. - /// - /// String. - public string ToHumanReadable() - { - return _collection.ToHumanReadable(); - } + /// + /// Returns a human-readable, multi-line, print-out (string) of this stack. + /// + /// String. + public string ToHumanReadable() + { + return _collection.ToHumanReadable(); + } - /********************************************************************************/ + /********************************************************************************/ - public IEnumerator GetEnumerator() - { - for (int i = _collection.Count - 1; i >= 0; --i) - yield return _collection[i]; - } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + public IEnumerator GetEnumerator() + { + for (int i = _collection.Count - 1; i >= 0; --i) + yield return _collection[i]; + } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); } -} +} \ No newline at end of file diff --git a/DataStructures/SortedCollections/SortedDictionary.cs b/DataStructures/SortedCollections/SortedDictionary.cs index 190c64be..45246c89 100644 --- a/DataStructures/SortedCollections/SortedDictionary.cs +++ b/DataStructures/SortedCollections/SortedDictionary.cs @@ -3,256 +3,253 @@ using DataStructures.Trees; -namespace DataStructures.SortedCollections +namespace DataStructures.SortedCollections; + +/// +/// Sorted Dictionary collection (Red-Black Tree based). +/// +public class SortedDictionary : IEnumerable>, IDictionary + where TKey : IComparable { /// - /// Sorted Dictionary collection (Red-Black Tree based). + /// The internal collection is a Red-Black Tree Map. /// - public class SortedDictionary : IEnumerable>, IDictionary - where TKey : IComparable - { - /// - /// The internal collection is a Red-Black Tree Map. - /// - private RedBlackTreeMap _collection { get; set; } + private RedBlackTreeMap _collection { get; set; } - /// - /// Constructor. - /// - public SortedDictionary() - { - _collection = new RedBlackTreeMap(allowDuplicates: false); - } + /// + /// Constructor. + /// + public SortedDictionary() + { + _collection = new RedBlackTreeMap(allowDuplicates: false); + } - /// - /// Gets the count of enteries in dictionary. - /// - public int Count => _collection.Count; + /// + /// Gets the count of enteries in dictionary. + /// + public int Count => _collection.Count; - /// - /// Returns true if dictionary is empty; otherwise, false. - /// - public bool IsEmpty => Count == 0; + /// + /// Returns true if dictionary is empty; otherwise, false. + /// + public bool IsEmpty => Count == 0; - public bool IsReadOnly => false; + public bool IsReadOnly => false; - /// - /// Determines whether the current dictionary contains an entry with the specified key. - /// - public bool ContainsKey(TKey key) + /// + /// Determines whether the current dictionary contains an entry with the specified key. + /// + public bool ContainsKey(TKey key) + { + return _collection.Contains(key); + } + + /// + /// Determines whether the current collection contains a specific key-value pair. + /// + public bool Contains(KeyValuePair item) + { + try { - return _collection.Contains(key); + var entry = _collection.Find(item.Key); + return entry.Value.Equals(item.Value); + } + catch(Exception) + { + return false; } + } - /// - /// Determines whether the current collection contains a specific key-value pair. - /// - public bool Contains(KeyValuePair item) + /// + /// Try to get the value of a key or default(TValue). Returns true if key exists; otherwise, false. + /// + public bool TryGetValue(TKey key, out TValue value) + { + // Set value to the default value of type TValue + value = default; + + try { - try - { - var entry = _collection.Find(item.Key); - return entry.Value.Equals(item.Value); - } - catch(Exception) - { - return false; - } + // Assign the returned object to value + value = _collection.Find(key).Value; + + // return Success. + return true; } + catch(KeyNotFoundException) + { + // No entry was found with the specified key. + // return Failure. + return false; + } + } - /// - /// Try to get the value of a key or default(TValue). Returns true if key exists; otherwise, false. - /// - public bool TryGetValue(TKey key, out TValue value) + /// + /// Gets or sets the value at the specified key. + /// + public TValue this[TKey index] + { + get { - // Set value to the default value of type TValue - value = default; + // In case dictionary is empty + if (IsEmpty) + throw new Exception("Dictionary is empty."); try { - // Assign the returned object to value - value = _collection.Find(key).Value; - - // return Success. - return true; + return _collection.Find(index).Value; } catch(KeyNotFoundException) { - // No entry was found with the specified key. - // return Failure. - return false; + // Mask the tree's exception with a new one. + throw new KeyNotFoundException("Key doesn't exist in dictionary."); } } - - /// - /// Gets or sets the value at the specified key. - /// - public TValue this[TKey index] + set { - get - { - // In case dictionary is empty - if (IsEmpty) - throw new Exception("Dictionary is empty."); - - try - { - return _collection.Find(index).Value; - } - catch(KeyNotFoundException) - { - // Mask the tree's exception with a new one. - throw new KeyNotFoundException("Key doesn't exist in dictionary."); - } - } - set - { - if (ContainsKey(index)) - _collection.Update(index, value); - else - Add(index, value); - } + if (ContainsKey(index)) + _collection.Update(index, value); + else + Add(index, value); } + } - /// - /// Gets the collection of keys in the dictionary. - /// - public ICollection Keys + /// + /// Gets the collection of keys in the dictionary. + /// + public ICollection Keys + { + get { - get - { - var keys = new List(Count); - var enumerator = _collection.GetInOrderEnumerator(); + var keys = new List(Count); + var enumerator = _collection.GetInOrderEnumerator(); - while (enumerator.MoveNext()) - keys.Add(enumerator.Current.Key); + while (enumerator.MoveNext()) + keys.Add(enumerator.Current.Key); - return keys; - } + return keys; } + } - /// - /// Gets the collection of values in the dictionary. - /// - public ICollection Values + /// + /// Gets the collection of values in the dictionary. + /// + public ICollection Values + { + get { - get - { - var values = new List(Count); - var enumerator = _collection.GetInOrderEnumerator(); + var values = new List(Count); + var enumerator = _collection.GetInOrderEnumerator(); - while (enumerator.MoveNext()) - values.Add(enumerator.Current.Value); + while (enumerator.MoveNext()) + values.Add(enumerator.Current.Value); - return values; - } + return values; } + } - /// - /// Add the specified key and value to the dictionary. - /// - public void Add(TKey key, TValue value) + /// + /// Add the specified key and value to the dictionary. + /// + public void Add(TKey key, TValue value) + { + // Throw an duplicate key exception if an entry with the same key exists + try { - // Throw an duplicate key exception if an entry with the same key exists - try - { - _collection.Insert(key, value); - } - catch(InvalidOperationException) - { - throw new InvalidOperationException("An entry with the same key already exists in dictionary."); - } + _collection.Insert(key, value); } - - /// - /// Removes the item with specific Key from the dictionary. - /// - public bool Remove(TKey key) + catch(InvalidOperationException) { - try - { - // Try removing it and return Success - _collection.Remove(key); - return true; - } - catch(Exception) - { - // Item was not found. Return Failure. - return false; - } + throw new InvalidOperationException("An entry with the same key already exists in dictionary."); } + } - /// - /// Add the key-value pair to the dictionary. - /// - public void Add(KeyValuePair item) + /// + /// Removes the item with specific Key from the dictionary. + /// + public bool Remove(TKey key) + { + try { - Add(item.Key, item.Value); + // Try removing it and return Success + _collection.Remove(key); + return true; } - - /// - /// Removes the first occurrence of an item from the current collection Key and Value will be matched. - /// - public bool Remove(KeyValuePair item) + catch(Exception) { - if (IsEmpty) - return false; - - // Get the entry from collection - var entry = _collection.Find(item.Key); - - // If the entry's value match the value of the specified item, remove it - if (entry.Value.Equals(item.Value)) - { - _collection.Remove(item.Key); - return true; - } - + // Item was not found. Return Failure. return false; } + } - /// - /// Copies the key-value pairs to a given array starting from specified index. - /// - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - if (array == null) - throw new ArgumentNullException(); - - var enumerator = _collection.GetInOrderEnumerator(); + /// + /// Add the key-value pair to the dictionary. + /// + public void Add(KeyValuePair item) + { + Add(item.Key, item.Value); + } - while (enumerator.MoveNext() && arrayIndex < array.Length) - { - array[arrayIndex] = enumerator.Current; - arrayIndex++; - } - } + /// + /// Removes the first occurrence of an item from the current collection Key and Value will be matched. + /// + public bool Remove(KeyValuePair item) + { + if (IsEmpty) + return false; + + // Get the entry from collection + var entry = _collection.Find(item.Key); - /// - /// Clears this instance. - /// - public void Clear() + // If the entry's value match the value of the specified item, remove it + if (entry.Value.Equals(item.Value)) { - _collection = new RedBlackTreeMap(allowDuplicates: false); + _collection.Remove(item.Key); + return true; } + return false; + } + + /// + /// Copies the key-value pairs to a given array starting from specified index. + /// + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + if (array == null) + throw new ArgumentNullException(); - #region IEnumerable implementation + var enumerator = _collection.GetInOrderEnumerator(); - public IEnumerator> GetEnumerator() + while (enumerator.MoveNext() && arrayIndex < array.Length) { - return _collection.GetInOrderEnumerator(); + array[arrayIndex] = enumerator.Current; + arrayIndex++; } + } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + /// + /// Clears this instance. + /// + public void Clear() + { + _collection = new RedBlackTreeMap(allowDuplicates: false); + } + + + #region IEnumerable implementation - #endregion + public IEnumerator> GetEnumerator() + { + return _collection.GetInOrderEnumerator(); } -} + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + #endregion +} \ No newline at end of file diff --git a/DataStructures/SortedCollections/SortedList.cs b/DataStructures/SortedCollections/SortedList.cs index 2f91da62..91f1895f 100644 --- a/DataStructures/SortedCollections/SortedList.cs +++ b/DataStructures/SortedCollections/SortedList.cs @@ -4,207 +4,205 @@ using DataStructures.Common; using DataStructures.Trees; -namespace DataStructures.SortedCollections +namespace DataStructures.SortedCollections; + +/// +/// Sorted List (RBTree-based). +/// +public class SortedList : IEnumerable, ICollection, IList where T : IComparable { /// - /// Sorted List (RBTree-based). + /// The internal collection is a Red-Black Tree. /// - public class SortedList : IEnumerable, ICollection, IList where T : IComparable + private RedBlackTree _collection { get; set; } + + + /// + /// Constructor. + /// + public SortedList() { - /// - /// The internal collection is a Red-Black Tree. - /// - private RedBlackTree _collection { get; set; } + _collection = new RedBlackTree(); + } + /// + /// Returns true if list is empty; otherwise, false. + /// + public bool IsEmpty => Count == 0; - /// - /// Constructor. - /// - public SortedList() - { - _collection = new RedBlackTree(); - } + /// + /// Gets the count of items in list. + /// + public int Count => _collection.Count; - /// - /// Returns true if list is empty; otherwise, false. - /// - public bool IsEmpty => Count == 0; + public bool IsReadOnly => false; - /// - /// Gets the count of items in list. - /// - public int Count => _collection.Count; + /// + /// Determines whether the current collection contains a specific value. + /// + public bool Contains(T item) + { + return _collection.Contains(item); + } + + /// + /// Determines the index of a specific item in the current collection. + /// + public int IndexOf(T item) + { + // If the item doesn't exist in collection, return -1 + if (!Contains(item)) + return -1; - public bool IsReadOnly => false; + int index = 0; + var enumerator = _collection.GetInOrderEnumerator(); - /// - /// Determines whether the current collection contains a specific value. - /// - public bool Contains(T item) + while (enumerator.MoveNext()) { - return _collection.Contains(item); + // If the current item is found return index + if (enumerator.Current.IsEqualTo(item)) + return index; + + // Increment index + index++; } - /// - /// Determines the index of a specific item in the current collection. - /// - public int IndexOf(T item) + return -1; + } + + /// + /// Gets or sets the item at the specified index. + /// + public T this[int index] + { + get { - // If the item doesn't exist in collection, return -1 - if (!Contains(item)) - return -1; + // In case list is empty + if (IsEmpty) + throw new Exception("List is empty."); + + // Validate index range + if (index < 0 || index >= Count) + throw new IndexOutOfRangeException(); - int index = 0; var enumerator = _collection.GetInOrderEnumerator(); - while (enumerator.MoveNext()) - { - // If the current item is found return index - if (enumerator.Current.IsEqualTo(item)) - return index; - - // Increment index - index++; - } + // Keep moving to the next item until index becomes 0 + while (enumerator.MoveNext() && index > 0) + index--; - return -1; + // Return the enumerator's Current value + return enumerator.Current; } - - /// - /// Gets or sets the item at the specified index. - /// - public T this[int index] + set { - get + try { - // In case list is empty - if (IsEmpty) - throw new Exception("List is empty."); - - // Validate index range - if (index < 0 || index >= Count) - throw new IndexOutOfRangeException(); - - var enumerator = _collection.GetInOrderEnumerator(); - - // Keep moving to the next item until index becomes 0 - while (enumerator.MoveNext() && index > 0) - index--; - - // Return the enumerator's Current value - return enumerator.Current; + _collection.Remove(this[index]); + Add(value); } - set + catch (IndexOutOfRangeException) { - try - { - _collection.Remove(this[index]); - Add(value); - } - catch (IndexOutOfRangeException) - { - // Masks the get method (see above) exception with a new one. - throw new IndexOutOfRangeException(); - } + // Masks the get method (see above) exception with a new one. + throw new IndexOutOfRangeException(); } } + } - /// - /// Adds the item to list. - /// - public void Add(T item) - { - _collection.Insert(item); - } + /// + /// Adds the item to list. + /// + public void Add(T item) + { + _collection.Insert(item); + } - /// - /// Removes the first occurrence of an item from list. - /// - public bool Remove(T item) + /// + /// Removes the first occurrence of an item from list. + /// + public bool Remove(T item) + { + try { - try - { - _collection.Remove(item); - return true; - } - catch(Exception) - { - return false; - } + _collection.Remove(item); + return true; } - - /// - /// Inserts the item at the specified index. - /// - public void Insert(int index, T item) + catch(Exception) { - // It is meaningless to insert at a specific index since after every - // insert operation, the collection will be rebalanced and the insertion - // operation itself needs to ensure the sorting criteria, therefore the item - // item insert at index i might not be the same after the operation has completed. - throw new NotImplementedException(); + return false; } + } - /// - /// Removes an item at a specific index. - /// - public void RemoveAt(int index) - { - // Validate index range - if (index < 0 || index >= Count) - throw new IndexOutOfRangeException(); + /// + /// Inserts the item at the specified index. + /// + public void Insert(int index, T item) + { + // It is meaningless to insert at a specific index since after every + // insert operation, the collection will be rebalanced and the insertion + // operation itself needs to ensure the sorting criteria, therefore the item + // item insert at index i might not be the same after the operation has completed. + throw new NotImplementedException(); + } - var enumerator = _collection.GetInOrderEnumerator(); + /// + /// Removes an item at a specific index. + /// + public void RemoveAt(int index) + { + // Validate index range + if (index < 0 || index >= Count) + throw new IndexOutOfRangeException(); - // Keep moving to the next item until index becomes 0 - while (enumerator.MoveNext() && index > 0) - index--; + var enumerator = _collection.GetInOrderEnumerator(); - // Remove the enumerator's Current value from collection - Remove(enumerator.Current); - } + // Keep moving to the next item until index becomes 0 + while (enumerator.MoveNext() && index > 0) + index--; - /// - /// Copies the items in list to an array starting from a given index. - /// - public void CopyTo(T[] array, int arrayIndex) - { - // Validate the array argument - if(array == null) - throw new ArgumentNullException("Array cannot be Null."); - - var enumerator = _collection.GetInOrderEnumerator(); + // Remove the enumerator's Current value from collection + Remove(enumerator.Current); + } - // Copy the items from the inorder-walker of the tree to the passed array - while (enumerator.MoveNext() && arrayIndex < array.Length) - { - array[arrayIndex] = enumerator.Current; - arrayIndex++; - } - } + /// + /// Copies the items in list to an array starting from a given index. + /// + public void CopyTo(T[] array, int arrayIndex) + { + // Validate the array argument + if(array == null) + throw new ArgumentNullException("Array cannot be Null."); + + var enumerator = _collection.GetInOrderEnumerator(); - /// - /// Clears this instance. - /// - public void Clear() + // Copy the items from the inorder-walker of the tree to the passed array + while (enumerator.MoveNext() && arrayIndex < array.Length) { - _collection = new RedBlackTree(); + array[arrayIndex] = enumerator.Current; + arrayIndex++; } + } + /// + /// Clears this instance. + /// + public void Clear() + { + _collection = new RedBlackTree(); + } - #region IEnumerable implementation - public IEnumerator GetEnumerator() - { - return _collection.GetInOrderEnumerator(); - } + #region IEnumerable implementation - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + public IEnumerator GetEnumerator() + { + return _collection.GetInOrderEnumerator(); + } - #endregion + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); } -} + #endregion +} \ No newline at end of file diff --git a/DataStructures/Trees/AVLTree.cs b/DataStructures/Trees/AVLTree.cs index 79b40015..31c3870e 100644 --- a/DataStructures/Trees/AVLTree.cs +++ b/DataStructures/Trees/AVLTree.cs @@ -1,399 +1,397 @@ using System; using System.Collections.Generic; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// AVL Tree Data Structure. +/// +public class AVLTree : BinarySearchTree where T : IComparable { /// - /// AVL Tree Data Structure. + /// Override the Root node accessors /// - public class AVLTree : BinarySearchTree where T : IComparable + public new AVLTreeNode Root { - /// - /// Override the Root node accessors - /// - public new AVLTreeNode Root - { - get => (AVLTreeNode)base.Root; - internal set => base.Root = value; - } + get => (AVLTreeNode)base.Root; + internal set => base.Root = value; + } - /// - /// CONSTRUCTOR. - /// Allows duplicates by default. - /// - public AVLTree() : base() { } + /// + /// CONSTRUCTOR. + /// Allows duplicates by default. + /// + public AVLTree() : base() { } - /// - /// CONSTRUCTOR. - /// If allowDuplictes is set to false, no duplicate items will be inserted. - /// - public AVLTree(bool allowDuplicates) : base(allowDuplicates) { } + /// + /// CONSTRUCTOR. + /// If allowDuplictes is set to false, no duplicate items will be inserted. + /// + public AVLTree(bool allowDuplicates) : base(allowDuplicates) { } - /// - /// Returns the height of a node. - /// - private int _getNodeHeight(AVLTreeNode node) - { - if (node == null) - return -1; - return node.Height; - } + /// + /// Returns the height of a node. + /// + private int _getNodeHeight(AVLTreeNode node) + { + if (node == null) + return -1; + return node.Height; + } - /// - /// Updates the height of a node. - /// - private void _updateNodeHeight(AVLTreeNode node) - { - if (node == null) - return; + /// + /// Updates the height of a node. + /// + private void _updateNodeHeight(AVLTreeNode node) + { + if (node == null) + return; - // height = 1 + the max between left and right children. - node.Height = 1 + Math.Max(_getNodeHeight(node.LeftChild), _getNodeHeight(node.RightChild)); - } + // height = 1 + the max between left and right children. + node.Height = 1 + Math.Max(_getNodeHeight(node.LeftChild), _getNodeHeight(node.RightChild)); + } - /// - /// Updates the height of a node and it's parents' recursivley up to the root of the tree. - /// - private void _updateHeightRecursive(AVLTreeNode node) - { - if (node == null) - return; + /// + /// Updates the height of a node and it's parents' recursivley up to the root of the tree. + /// + private void _updateHeightRecursive(AVLTreeNode node) + { + if (node == null) + return; - // height = 1 + the max between left and right children. - node.Height = 1 + Math.Max(_getNodeHeight(node.LeftChild), _getNodeHeight(node.RightChild)); + // height = 1 + the max between left and right children. + node.Height = 1 + Math.Max(_getNodeHeight(node.LeftChild), _getNodeHeight(node.RightChild)); - _updateHeightRecursive(node.Parent); - } + _updateHeightRecursive(node.Parent); + } - /// - /// Returns the AVL balance factor for a node. - /// - private int _getBalanceFactor(AVLTreeNode node) - { - if (node == null) - return -1; + /// + /// Returns the AVL balance factor for a node. + /// + private int _getBalanceFactor(AVLTreeNode node) + { + if (node == null) + return -1; - return _getNodeHeight(node.RightChild) - _getNodeHeight(node.LeftChild); - } + return _getNodeHeight(node.RightChild) - _getNodeHeight(node.LeftChild); + } - /// - /// Rotates a node to the left in the AVL tree. - /// - private void _rotateLeftAt(AVLTreeNode currentNode) - { - // We check the right child because it's going to be a pivot node for the rotation - if (currentNode == null || currentNode.HasRightChild == false) - return; + /// + /// Rotates a node to the left in the AVL tree. + /// + private void _rotateLeftAt(AVLTreeNode currentNode) + { + // We check the right child because it's going to be a pivot node for the rotation + if (currentNode == null || currentNode.HasRightChild == false) + return; - // Pivot on *right* child - AVLTreeNode pivotNode = currentNode.RightChild; + // Pivot on *right* child + AVLTreeNode pivotNode = currentNode.RightChild; - // Parent of currentNode - AVLTreeNode parent = currentNode.Parent; + // Parent of currentNode + AVLTreeNode parent = currentNode.Parent; - // Check if currentNode is it's parent's left child. - bool isLeftChild = currentNode.IsLeftChild; + // Check if currentNode is it's parent's left child. + bool isLeftChild = currentNode.IsLeftChild; - // Check if currentNode is the Root - bool isRootNode = currentNode == Root; + // Check if currentNode is the Root + bool isRootNode = currentNode == Root; - // Perform the rotation - currentNode.RightChild = pivotNode.LeftChild; - pivotNode.LeftChild = currentNode; + // Perform the rotation + currentNode.RightChild = pivotNode.LeftChild; + pivotNode.LeftChild = currentNode; - // Update parents references - currentNode.Parent = pivotNode; - pivotNode.Parent = parent; + // Update parents references + currentNode.Parent = pivotNode; + pivotNode.Parent = parent; - if (currentNode.HasRightChild) - currentNode.RightChild.Parent = currentNode; + if (currentNode.HasRightChild) + currentNode.RightChild.Parent = currentNode; - //Update the entire tree's Root if necessary - if (isRootNode) - Root = pivotNode; + //Update the entire tree's Root if necessary + if (isRootNode) + Root = pivotNode; - // Update the original parent's child node - if (isLeftChild) - parent.LeftChild = pivotNode; - else if (parent != null) - parent.RightChild = pivotNode; + // Update the original parent's child node + if (isLeftChild) + parent.LeftChild = pivotNode; + else if (parent != null) + parent.RightChild = pivotNode; - // Update the AVL Heights of each node. - // _updateHeightRecursive(pivotNode); - _updateHeightRecursive(currentNode); - } + // Update the AVL Heights of each node. + // _updateHeightRecursive(pivotNode); + _updateHeightRecursive(currentNode); + } - /// - /// Rotates a node to the right in the AVL tree. - /// - private void _rotateRightAt(AVLTreeNode currentNode) - { - // We check the right child because it's going to be a pivot node for the rotation - if (currentNode == null || currentNode.HasLeftChild == false) - return; + /// + /// Rotates a node to the right in the AVL tree. + /// + private void _rotateRightAt(AVLTreeNode currentNode) + { + // We check the right child because it's going to be a pivot node for the rotation + if (currentNode == null || currentNode.HasLeftChild == false) + return; - // Pivot on *left* child - var pivotNode = currentNode.LeftChild; + // Pivot on *left* child + var pivotNode = currentNode.LeftChild; - // Parent of currentNode - var parent = currentNode.Parent; + // Parent of currentNode + var parent = currentNode.Parent; - // Check if currentNode is it's parent's left child. - bool isLeftChild = currentNode.IsLeftChild; + // Check if currentNode is it's parent's left child. + bool isLeftChild = currentNode.IsLeftChild; - // Check if currentNode is the Root - bool isRootNode = currentNode == Root; + // Check if currentNode is the Root + bool isRootNode = currentNode == Root; - // Perform the rotation - currentNode.LeftChild = pivotNode.RightChild; - pivotNode.RightChild = currentNode; + // Perform the rotation + currentNode.LeftChild = pivotNode.RightChild; + pivotNode.RightChild = currentNode; - // Update parents references - currentNode.Parent = pivotNode; - pivotNode.Parent = parent; + // Update parents references + currentNode.Parent = pivotNode; + pivotNode.Parent = parent; - if (currentNode.HasLeftChild) - currentNode.LeftChild.Parent = currentNode; + if (currentNode.HasLeftChild) + currentNode.LeftChild.Parent = currentNode; - // Update the entire tree's Root if necessary - if (isRootNode) - Root = pivotNode; + // Update the entire tree's Root if necessary + if (isRootNode) + Root = pivotNode; - // Update the original parent's child node - if (isLeftChild) - parent.LeftChild = pivotNode; - else if (parent != null) - parent.RightChild = pivotNode; + // Update the original parent's child node + if (isLeftChild) + parent.LeftChild = pivotNode; + else if (parent != null) + parent.RightChild = pivotNode; - // Update the AVL Heights of each node. - // _updateHeightRecursive(pivotNode); - _updateHeightRecursive(currentNode); - } + // Update the AVL Heights of each node. + // _updateHeightRecursive(pivotNode); + _updateHeightRecursive(currentNode); + } - /// - /// Rebalances the tree around a node. - /// - private void _rebalanceSubtreeTreeAt(AVLTreeNode currentNode) - { - if (currentNode == null) - return; + /// + /// Rebalances the tree around a node. + /// + private void _rebalanceSubtreeTreeAt(AVLTreeNode currentNode) + { + if (currentNode == null) + return; - int balance = _getBalanceFactor(currentNode); + int balance = _getBalanceFactor(currentNode); - // Balance the tree only if the balance factor was less than -1 or greater than +1. - if (Math.Abs(balance) >= 2) // -2 or 2; -3 or 3 ... etc + // Balance the tree only if the balance factor was less than -1 or greater than +1. + if (Math.Abs(balance) >= 2) // -2 or 2; -3 or 3 ... etc + { + // if balance is a positive number: 2, 3 ... etc + // right subtree outweighs + if (balance > 0) { - // if balance is a positive number: 2, 3 ... etc - // right subtree outweighs - if (balance > 0) + int rightSubtreeBalance = _getBalanceFactor(currentNode.RightChild); + + if (rightSubtreeBalance == 0 || rightSubtreeBalance == 1) { - int rightSubtreeBalance = _getBalanceFactor(currentNode.RightChild); - - if (rightSubtreeBalance == 0 || rightSubtreeBalance == 1) - { - // Rotate *LEFT* on current node - _rotateLeftAt(currentNode); - } - else if (rightSubtreeBalance == -1) - { - // Rotate *RIGHT* on right child - _rotateRightAt(currentNode.RightChild); - - // Rotate *LEFT* on current node - _rotateLeftAt(currentNode); - } + // Rotate *LEFT* on current node + _rotateLeftAt(currentNode); } - // if balance is a negative number: -2, -3 ... etc - // left subtree outweighs - else + else if (rightSubtreeBalance == -1) { - int leftSubtreeBalance = _getBalanceFactor(currentNode.LeftChild); - - if (leftSubtreeBalance == 0 || leftSubtreeBalance == 1) - { - // Rotate *RIGHT* on current node - _rotateRightAt(currentNode); - } - else if (leftSubtreeBalance == -1) - { - // Rotate *LEFT* on left child - _rotateLeftAt(currentNode.LeftChild); - - // Rotate *RIGHT* on right child - _rotateRightAt(currentNode); - } + // Rotate *RIGHT* on right child + _rotateRightAt(currentNode.RightChild); + + // Rotate *LEFT* on current node + _rotateLeftAt(currentNode); } } - } - - /// - /// Rebalances the whole tree around a node. - /// - private void _rebalanceTreeAt(AVLTreeNode node) - { - var currentNode = node; - while (currentNode != null) + // if balance is a negative number: -2, -3 ... etc + // left subtree outweighs + else { - // Update this node's height value. - _updateNodeHeight(currentNode); - - // Get left and right for comparisons - var left = currentNode.LeftChild; - var right = currentNode.RightChild; + int leftSubtreeBalance = _getBalanceFactor(currentNode.LeftChild); - if (_getNodeHeight(left) >= 2 + _getNodeHeight(right)) + if (leftSubtreeBalance == 0 || leftSubtreeBalance == 1) { - if (currentNode.HasLeftChild && _getNodeHeight(left.LeftChild) >= _getNodeHeight(left.RightChild)) - { - _rotateRightAt(currentNode); - } - else - { - _rotateLeftAt(currentNode.LeftChild); - _rotateRightAt(currentNode); - } + // Rotate *RIGHT* on current node + _rotateRightAt(currentNode); } - else if (_getNodeHeight(right) >= 2 + _getNodeHeight(left)) + else if (leftSubtreeBalance == -1) { - if (currentNode.HasRightChild && _getNodeHeight(right.RightChild) >= _getNodeHeight(right.LeftChild)) - { - _rotateLeftAt(currentNode); - } - else - { - _rotateRightAt(currentNode.RightChild); - _rotateLeftAt(currentNode); - } - } + // Rotate *LEFT* on left child + _rotateLeftAt(currentNode.LeftChild); - currentNode = currentNode.Parent; + // Rotate *RIGHT* on right child + _rotateRightAt(currentNode); + } } } + } - /// - /// Inserts an item to the tree. - /// - public override void Insert(T item) + /// + /// Rebalances the whole tree around a node. + /// + private void _rebalanceTreeAt(AVLTreeNode node) + { + var currentNode = node; + while (currentNode != null) { - // New node object - var newNode = new AVLTreeNode() { Value = item }; - - // Invoke the super BST insert node method. - // This insert node recursively starting from the root and checks for success status (related to allowDuplicates flag). - // The functions increments count on its own. - var success = base._insertNode(newNode); - - if (success == false && _allowDuplicates == false) - throw new InvalidOperationException("Tree does not allow inserting duplicate elements."); + // Update this node's height value. + _updateNodeHeight(currentNode); - // Rebalance the tree - _rebalanceTreeAt(newNode); - } + // Get left and right for comparisons + var left = currentNode.LeftChild; + var right = currentNode.RightChild; - /// - /// Inserts an array of elements to the tree. - /// - public override void Insert(T[] collection) - { - if (collection == null) - throw new ArgumentNullException(); + if (_getNodeHeight(left) >= 2 + _getNodeHeight(right)) + { + if (currentNode.HasLeftChild && _getNodeHeight(left.LeftChild) >= _getNodeHeight(left.RightChild)) + { + _rotateRightAt(currentNode); + } + else + { + _rotateLeftAt(currentNode.LeftChild); + _rotateRightAt(currentNode); + } + } + else if (_getNodeHeight(right) >= 2 + _getNodeHeight(left)) + { + if (currentNode.HasRightChild && _getNodeHeight(right.RightChild) >= _getNodeHeight(right.LeftChild)) + { + _rotateLeftAt(currentNode); + } + else + { + _rotateRightAt(currentNode.RightChild); + _rotateLeftAt(currentNode); + } + } - if (collection.Length > 0) - for (int i = 0; i < collection.Length; ++i) - Insert(collection[i]); + currentNode = currentNode.Parent; } + } - /// - /// Inserts a list of elements to the tree. - /// - public override void Insert(List collection) - { - if (collection == null) - throw new ArgumentNullException(); + /// + /// Inserts an item to the tree. + /// + public override void Insert(T item) + { + // New node object + var newNode = new AVLTreeNode() { Value = item }; - if (collection.Count > 0) - for (int i = 0; i < collection.Count; ++i) - Insert(collection[i]); - } + // Invoke the super BST insert node method. + // This insert node recursively starting from the root and checks for success status (related to allowDuplicates flag). + // The functions increments count on its own. + var success = base._insertNode(newNode); - /// - /// Removes an item fromt he tree - /// - public override void Remove(T item) - { - if (IsEmpty) - throw new Exception("Tree is empty."); + if (success == false && _allowDuplicates == false) + throw new InvalidOperationException("Tree does not allow inserting duplicate elements."); - // Get the node from the tree - var node = (AVLTreeNode)base._findNode(Root, item); + // Rebalance the tree + _rebalanceTreeAt(newNode); + } - // Invoke the BST remove node method. - bool status = base._remove(node); + /// + /// Inserts an array of elements to the tree. + /// + public override void Insert(T[] collection) + { + if (collection == null) + throw new ArgumentNullException(); - if (status == true) - { - // Rebalance the tree - // node.parent is actually the old parent of the node, - // which is the first potentially out-of-balance node. - _rebalanceTreeAt(node); - } - else - { - throw new Exception("Item was not found."); - } + if (collection.Length > 0) + for (int i = 0; i < collection.Length; ++i) + Insert(collection[i]); + } - //// Update the node's parent height. - //_updateHeightRecursively(node.Parent); + /// + /// Inserts a list of elements to the tree. + /// + public override void Insert(List collection) + { + if (collection == null) + throw new ArgumentNullException(); - //// Rebalance the tree - //var parent = node.Parent; - //while(parent != null) - //{ - // _rebalanceSubtreeTreeAt(node.Parent); - //} - } + if (collection.Count > 0) + for (int i = 0; i < collection.Count; ++i) + Insert(collection[i]); + } - /// - /// Removes the min value from tree. - /// - public override void RemoveMin() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Removes an item fromt he tree + /// + public override void Remove(T item) + { + if (IsEmpty) + throw new Exception("Tree is empty."); - // Get the node from the tree - var node = (AVLTreeNode)base._findMinNode(Root); + // Get the node from the tree + var node = (AVLTreeNode)base._findNode(Root, item); - // Invoke the BST remove node method. - base._remove(node); + // Invoke the BST remove node method. + bool status = base._remove(node); + if (status == true) + { // Rebalance the tree // node.parent is actually the old parent of the node, // which is the first potentially out-of-balance node. _rebalanceTreeAt(node); } - - /// - /// Removes the max value from tree. - /// - public override void RemoveMax() + else { - if (IsEmpty) - throw new Exception("Tree is empty."); + throw new Exception("Item was not found."); + } - // Get the node from the tree - var node = (AVLTreeNode)base._findMaxNode(Root); + //// Update the node's parent height. + //_updateHeightRecursively(node.Parent); - // Invoke the BST remove node method. - base._remove(node); + //// Rebalance the tree + //var parent = node.Parent; + //while(parent != null) + //{ + // _rebalanceSubtreeTreeAt(node.Parent); + //} + } - // Rebalance the tree - // node.parent is actually the old parent of the node, - // which is the first potentially out-of-balance node. - _rebalanceTreeAt(node); - } + /// + /// Removes the min value from tree. + /// + public override void RemoveMin() + { + if (IsEmpty) + throw new Exception("Tree is empty."); + + // Get the node from the tree + var node = (AVLTreeNode)base._findMinNode(Root); + + // Invoke the BST remove node method. + base._remove(node); + + // Rebalance the tree + // node.parent is actually the old parent of the node, + // which is the first potentially out-of-balance node. + _rebalanceTreeAt(node); + } + + /// + /// Removes the max value from tree. + /// + public override void RemoveMax() + { + if (IsEmpty) + throw new Exception("Tree is empty."); + + // Get the node from the tree + var node = (AVLTreeNode)base._findMaxNode(Root); + + // Invoke the BST remove node method. + base._remove(node); + // Rebalance the tree + // node.parent is actually the old parent of the node, + // which is the first potentially out-of-balance node. + _rebalanceTreeAt(node); } -} +} \ No newline at end of file diff --git a/DataStructures/Trees/AVLTreeNode.cs b/DataStructures/Trees/AVLTreeNode.cs index a288cf65..c71c3bdd 100644 --- a/DataStructures/Trees/AVLTreeNode.cs +++ b/DataStructures/Trees/AVLTreeNode.cs @@ -1,39 +1,38 @@ -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// AVL Tree Node. +/// +public class AVLTreeNode : BSTNode where T : System.IComparable { - /// - /// AVL Tree Node. - /// - public class AVLTreeNode : BSTNode where T : System.IComparable + public AVLTreeNode() : this(default, 0, null, null, null) { } + public AVLTreeNode(T value) : this(value, 0, null, null, null) { } + public AVLTreeNode(T value, int height, AVLTreeNode parent, AVLTreeNode left, AVLTreeNode right) { - public AVLTreeNode() : this(default, 0, null, null, null) { } - public AVLTreeNode(T value) : this(value, 0, null, null, null) { } - public AVLTreeNode(T value, int height, AVLTreeNode parent, AVLTreeNode left, AVLTreeNode right) - { - base.Value = value; - Height = height; - Parent = parent; - LeftChild = left; - RightChild = right; - } + base.Value = value; + Height = height; + Parent = parent; + LeftChild = left; + RightChild = right; + } - public virtual int Height { get; set; } = 0; + public virtual int Height { get; set; } = 0; - public new AVLTreeNode Parent - { - get => (AVLTreeNode)base.Parent; - set => base.Parent = value; - } + public new AVLTreeNode Parent + { + get => (AVLTreeNode)base.Parent; + set => base.Parent = value; + } - public new AVLTreeNode LeftChild - { - get => (AVLTreeNode)base.LeftChild; - set => base.LeftChild = value; - } + public new AVLTreeNode LeftChild + { + get => (AVLTreeNode)base.LeftChild; + set => base.LeftChild = value; + } - public new AVLTreeNode RightChild - { - get => (AVLTreeNode)base.RightChild; - set => base.RightChild = value; - } + public new AVLTreeNode RightChild + { + get => (AVLTreeNode)base.RightChild; + set => base.RightChild = value; } -} +} \ No newline at end of file diff --git a/DataStructures/Trees/AugmentedBinarySearchTree.cs b/DataStructures/Trees/AugmentedBinarySearchTree.cs index feb0dbc7..3fed3b57 100644 --- a/DataStructures/Trees/AugmentedBinarySearchTree.cs +++ b/DataStructures/Trees/AugmentedBinarySearchTree.cs @@ -1,310 +1,307 @@ using System; using System.Collections.Generic; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// Binary Search Tree node. +/// This node extends the vanilla BSTNode class and adds an extra field to it for augmentation. +/// The BST now augments the subtree-sizes on insert, delete and get-height. +/// +public class BSTRankedNode : BSTNode where T : IComparable { - /// - /// Binary Search Tree node. - /// This node extends the vanilla BSTNode class and adds an extra field to it for augmentation. - /// The BST now augments the subtree-sizes on insert, delete and get-height. - /// - - public class BSTRankedNode : BSTNode where T : IComparable + public BSTRankedNode() : this(default, 0, null, null, null) { } + public BSTRankedNode(T value) : this(value, 0, null, null, null) { } + public BSTRankedNode(T value, int subtreeSize, BSTRankedNode parent, BSTRankedNode left, BSTRankedNode right) { - public BSTRankedNode() : this(default, 0, null, null, null) { } - public BSTRankedNode(T value) : this(value, 0, null, null, null) { } - public BSTRankedNode(T value, int subtreeSize, BSTRankedNode parent, BSTRankedNode left, BSTRankedNode right) - { - base.Value = value; - SubtreeSize = subtreeSize; - Parent = parent; - LeftChild = left; - RightChild = right; - } + base.Value = value; + SubtreeSize = subtreeSize; + Parent = parent; + LeftChild = left; + RightChild = right; + } - // Size of subtrees - public virtual int SubtreeSize { get; set; } = 0; + // Size of subtrees + public virtual int SubtreeSize { get; set; } = 0; - public new BSTRankedNode Parent - { - get => (BSTRankedNode)base.Parent; - set => base.Parent = value; - } + public new BSTRankedNode Parent + { + get => (BSTRankedNode)base.Parent; + set => base.Parent = value; + } - public new BSTRankedNode LeftChild - { - get => (BSTRankedNode)base.LeftChild; - set => base.LeftChild = value; - } + public new BSTRankedNode LeftChild + { + get => (BSTRankedNode)base.LeftChild; + set => base.LeftChild = value; + } - public new BSTRankedNode RightChild - { - get => (BSTRankedNode)base.RightChild; - set => base.RightChild = value; - } + public new BSTRankedNode RightChild + { + get => (BSTRankedNode)base.RightChild; + set => base.RightChild = value; } +} + +/******************************************************************************/ - /******************************************************************************/ +/// +/// Binary Search Tree Data Structure. +/// This is teh augmented version of BST. It is augmented to keep track of the nodes subtrees-sizes. +/// +public class AugmentedBinarySearchTree : BinarySearchTree where T : IComparable +{ /// - /// Binary Search Tree Data Structure. - /// This is teh augmented version of BST. It is augmented to keep track of the nodes subtrees-sizes. + /// Override the Root node accessors. /// + public new BSTRankedNode Root + { + get => (BSTRankedNode)base.Root; + set => base.Root = value; + } + + + /// + /// CONSTRUCTOR. + /// Allows duplicates by default. + /// + public AugmentedBinarySearchTree() : base() { } + + /// + /// CONSTRUCTOR. + /// If allowDuplictes is set to false, no duplicate items will be inserted. + /// + public AugmentedBinarySearchTree(bool allowDuplicates) : base(allowDuplicates) { } + - public class AugmentedBinarySearchTree : BinarySearchTree where T : IComparable + /// + /// Returns the height of the tree. + /// + /// Hight + public override int Height { - /// - /// Override the Root node accessors. - /// - public new BSTRankedNode Root + get { - get => (BSTRankedNode)base.Root; - set => base.Root = value; + if (IsEmpty) + return 0; + + var currentNode = Root; + return _getTreeHeight(currentNode); } + } + /// + /// Returns the Subtrees size for a tree node if node exists; otherwise 0 (left and right nodes of leafs). + /// This is used in the recursive function UpdateSubtreeSize. + /// + /// The size. + /// BST Node. + protected int _subtreeSize(BSTRankedNode node) + { + if (node == null) + return 0; + return node.SubtreeSize; + } + + /// + /// Updates the Subtree Size of a tree node. + /// Used in recusively calculating the Subtrees Sizes of nodes. + /// + /// BST Node. + protected void _updateSubtreeSize(BSTRankedNode node) + { + if (node == null) + return; - /// - /// CONSTRUCTOR. - /// Allows duplicates by default. - /// - public AugmentedBinarySearchTree() : base() { } + node.SubtreeSize = _subtreeSize(node.LeftChild) + _subtreeSize(node.RightChild) + 1; - /// - /// CONSTRUCTOR. - /// If allowDuplictes is set to false, no duplicate items will be inserted. - /// - public AugmentedBinarySearchTree(bool allowDuplicates) : base(allowDuplicates) { } + _updateSubtreeSize(node.Parent); + } + /// + /// Remove the specified node. + /// + /// Node. + /// >True if removed successfully; false if node wasn't found. + protected bool _remove(BSTRankedNode node) + { + if (node == null) + return false; - /// - /// Returns the height of the tree. - /// - /// Hight - public override int Height - { - get - { - if (IsEmpty) - return 0; - - var currentNode = Root; - return _getTreeHeight(currentNode); - } - } + var parent = node.Parent; - /// - /// Returns the Subtrees size for a tree node if node exists; otherwise 0 (left and right nodes of leafs). - /// This is used in the recursive function UpdateSubtreeSize. - /// - /// The size. - /// BST Node. - protected int _subtreeSize(BSTRankedNode node) + if (node.ChildrenCount == 2) // if both children are present { - if (node == null) - return 0; - return node.SubtreeSize; + var successor = _findNextLarger(node); + node.Value = successor.Value; + return true && _remove(successor); } - /// - /// Updates the Subtree Size of a tree node. - /// Used in recusively calculating the Subtrees Sizes of nodes. - /// - /// BST Node. - protected void _updateSubtreeSize(BSTRankedNode node) + if (node.HasLeftChild) // if the node has only a LEFT child { - if (node == null) - return; - - node.SubtreeSize = _subtreeSize(node.LeftChild) + _subtreeSize(node.RightChild) + 1; + base._replaceNodeInParent(node, node.LeftChild); + _updateSubtreeSize(parent); + _count--; - _updateSubtreeSize(node.Parent); } - - /// - /// Remove the specified node. - /// - /// Node. - /// >True if removed successfully; false if node wasn't found. - protected bool _remove(BSTRankedNode node) + else if (node.HasRightChild) // if the node has only a RIGHT child { - if (node == null) - return false; - - var parent = node.Parent; - - if (node.ChildrenCount == 2) // if both children are present - { - var successor = _findNextLarger(node); - node.Value = successor.Value; - return true && _remove(successor); - } - - if (node.HasLeftChild) // if the node has only a LEFT child - { - base._replaceNodeInParent(node, node.LeftChild); - _updateSubtreeSize(parent); - _count--; - - } - else if (node.HasRightChild) // if the node has only a RIGHT child - { - base._replaceNodeInParent(node, node.RightChild); - _updateSubtreeSize(parent); - _count--; - } - else //this node has no children - { - base._replaceNodeInParent(node, null); - _updateSubtreeSize(parent); - _count--; - } - - return true; + base._replaceNodeInParent(node, node.RightChild); + _updateSubtreeSize(parent); + _count--; } - - /// - /// Calculates the tree height from a specific node, recursively. - /// - /// Node - /// Height of node's longest subtree - protected int _getTreeHeight(BSTRankedNode node) + else //this node has no children { - if (node == null || node.HasChildren == false) - return 0; + base._replaceNodeInParent(node, null); + _updateSubtreeSize(parent); + _count--; + } - if (node.ChildrenCount == 2) // it has both a right child and a left child - { - if (node.LeftChild.SubtreeSize > node.RightChild.SubtreeSize) - return 1 + _getTreeHeight(node.LeftChild); - return 1 + _getTreeHeight(node.RightChild); - } + return true; + } - if (node.HasLeftChild) - { - return 1 + _getTreeHeight(node.LeftChild); - } + /// + /// Calculates the tree height from a specific node, recursively. + /// + /// Node + /// Height of node's longest subtree + protected int _getTreeHeight(BSTRankedNode node) + { + if (node == null || node.HasChildren == false) + return 0; - if (node.HasRightChild) - { - return 1 + _getTreeHeight(node.RightChild); - } + if (node.ChildrenCount == 2) // it has both a right child and a left child + { + if (node.LeftChild.SubtreeSize > node.RightChild.SubtreeSize) + return 1 + _getTreeHeight(node.LeftChild); + return 1 + _getTreeHeight(node.RightChild); + } - // return-functions-fix - return 0; + if (node.HasLeftChild) + { + return 1 + _getTreeHeight(node.LeftChild); } - /// - /// Inserts an element to the tree - /// - /// Item to insert - public override void Insert(T item) + if (node.HasRightChild) { - var newNode = new BSTRankedNode(item); + return 1 + _getTreeHeight(node.RightChild); + } - // Invoke the super BST insert node method. - // This insert node recursively starting from the root and checks for success status (related to allowDuplicates flag). - // The functions increments count on its own. - var success = base._insertNode(newNode); + // return-functions-fix + return 0; + } - if (success == false && _allowDuplicates == false) - throw new InvalidOperationException("Tree does not allow inserting duplicate elements."); + /// + /// Inserts an element to the tree + /// + /// Item to insert + public override void Insert(T item) + { + var newNode = new BSTRankedNode(item); - // Update the subtree-size for the newNode's parent. - _updateSubtreeSize(newNode.Parent); - } + // Invoke the super BST insert node method. + // This insert node recursively starting from the root and checks for success status (related to allowDuplicates flag). + // The functions increments count on its own. + var success = base._insertNode(newNode); - /// - /// Inserts an array of elements to the tree. - /// - public override void Insert(T[] collection) - { - if (collection == null) - throw new ArgumentNullException(); + if (success == false && _allowDuplicates == false) + throw new InvalidOperationException("Tree does not allow inserting duplicate elements."); - if (collection.Length > 0) - for (int i = 0; i < collection.Length; ++i) - Insert(collection[i]); - } + // Update the subtree-size for the newNode's parent. + _updateSubtreeSize(newNode.Parent); + } - /// - /// Inserts a list of elements to the tree. - /// - public override void Insert(List collection) - { - if (collection == null) - throw new ArgumentNullException(); + /// + /// Inserts an array of elements to the tree. + /// + public override void Insert(T[] collection) + { + if (collection == null) + throw new ArgumentNullException(); - if (collection.Count > 0) - for (int i = 0; i < collection.Count; ++i) - Insert(collection[i]); - } + if (collection.Length > 0) + for (int i = 0; i < collection.Length; ++i) + Insert(collection[i]); + } - /// - /// Deletes an element from the tree - /// - /// item to remove. - public override void Remove(T item) - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Inserts a list of elements to the tree. + /// + public override void Insert(List collection) + { + if (collection == null) + throw new ArgumentNullException(); - var node = (BSTRankedNode)base._findNode(Root, item); - bool status = _remove(node); - _updateSubtreeSize(node.Parent); + if (collection.Count > 0) + for (int i = 0; i < collection.Count; ++i) + Insert(collection[i]); + } - // If the element was found, remove it. - if (status == false) - throw new Exception("Item was not found."); - } + /// + /// Deletes an element from the tree + /// + /// item to remove. + public override void Remove(T item) + { + if (IsEmpty) + throw new Exception("Tree is empty."); - /// - /// Removes the min value from tree. - /// - public override void RemoveMin() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + var node = (BSTRankedNode)base._findNode(Root, item); + bool status = _remove(node); + _updateSubtreeSize(node.Parent); - var node = (BSTRankedNode)_findMinNode(Root); - var parent = node.Parent; - _remove(node); + // If the element was found, remove it. + if (status == false) + throw new Exception("Item was not found."); + } - // Update the subtrees-sizes - _updateSubtreeSize(parent); - } + /// + /// Removes the min value from tree. + /// + public override void RemoveMin() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - /// - /// Removes the max value from tree. - /// - public override void RemoveMax() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + var node = (BSTRankedNode)_findMinNode(Root); + var parent = node.Parent; + _remove(node); - var node = (BSTRankedNode)_findMaxNode(Root); - var parent = node.Parent; - _remove(node); + // Update the subtrees-sizes + _updateSubtreeSize(parent); + } - // Update the subtrees-sizes - _updateSubtreeSize(parent); - } + /// + /// Removes the max value from tree. + /// + public override void RemoveMax() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - /// - /// Returns the rank of the specified element - /// - /// Tree element - /// Rank(item) if found; otherwise throws an exception. - public virtual int Rank(T item) - { - var node = (BSTRankedNode)base._findNode(Root, item); + var node = (BSTRankedNode)_findMaxNode(Root); + var parent = node.Parent; + _remove(node); - if (node == null) - throw new Exception("Item was not found."); - return _subtreeSize(node.LeftChild) + 1; - } + // Update the subtrees-sizes + _updateSubtreeSize(parent); + } + /// + /// Returns the rank of the specified element + /// + /// Tree element + /// Rank(item) if found; otherwise throws an exception. + public virtual int Rank(T item) + { + var node = (BSTRankedNode)base._findNode(Root, item); + + if (node == null) + throw new Exception("Item was not found."); + return _subtreeSize(node.LeftChild) + 1; } -} +} \ No newline at end of file diff --git a/DataStructures/Trees/BTree.cs b/DataStructures/Trees/BTree.cs index 55c6c568..321f7ff6 100644 --- a/DataStructures/Trees/BTree.cs +++ b/DataStructures/Trees/BTree.cs @@ -1,408 +1,406 @@ using System; using System.Collections.Generic; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// B Tree Data Structure. Heavily influenced by Geeks for Geeks article. +/// https://www.geeksforgeeks.org/b-tree-set-1-introduction-2/ +/// +public class BTree where T : IComparable { + private int _count { get; set; } + private BTreeNode _root { get; set; } + private int _minDegree; + /// - /// B Tree Data Structure. Heavily influenced by Geeks for Geeks article. - /// https://www.geeksforgeeks.org/b-tree-set-1-introduction-2/ + /// CONSTRUCTOR. /// - public class BTree where T : IComparable - { - private int _count { get; set; } - private BTreeNode _root { get; set; } - private int _minDegree; - - /// - /// CONSTRUCTOR. - /// - public BTree(int minDegree) { - _minDegree = minDegree; - _count = 0; - } + public BTree(int minDegree) { + _minDegree = minDegree; + _count = 0; + } - public BTreeNode Root => _root; + public BTreeNode Root => _root; - /// - /// Inserts an item to the tree. - /// - public void Insert(T value) + /// + /// Inserts an item to the tree. + /// + public void Insert(T value) + { + if (_root == null) + { + _root = new BTreeNode(_minDegree); + _root.Keys.Add(value); + } + else { - if (_root == null) + if (_root.Keys.Count >= 2*_minDegree-1) { - _root = new BTreeNode(_minDegree); - _root.Keys.Add(value); + var newRoot = new BTreeNode(_minDegree); + newRoot.Children.Add(_root); + newRoot.SplitChild(0, _root); + + // Which of the 2 children should hold the new value? + var i = 0; + if (value.CompareTo(newRoot.Keys[0]) > 0) + { + i++; + } + newRoot.Children[i].InsertNonFull(value); + + _root = newRoot; } else { - if (_root.Keys.Count >= 2*_minDegree-1) - { - var newRoot = new BTreeNode(_minDegree); - newRoot.Children.Add(_root); - newRoot.SplitChild(0, _root); - - // Which of the 2 children should hold the new value? - var i = 0; - if (value.CompareTo(newRoot.Keys[0]) > 0) - { - i++; - } - newRoot.Children[i].InsertNonFull(value); - - _root = newRoot; - } - else - { - _root.InsertNonFull(value); - } + _root.InsertNonFull(value); } } + } - /// - /// Finds the Node that holds the given value. - /// - public BTreeNode Search(T value) - { - if (_root == null) - return null; + /// + /// Finds the Node that holds the given value. + /// + public BTreeNode Search(T value) + { + if (_root == null) + return null; + + return _root.Search(value); + } - return _root.Search(value); + /// + /// Removes an item from the tree + /// + public void Remove(T item) + { + if (_root == null) + { + Console.WriteLine("The B Tree is empty."); + return; } - /// - /// Removes an item from the tree - /// - public void Remove(T item) + _root.Remove(item); + if (_root.Keys.Count == 0) { - if (_root == null) + if (_root.IsLeaf) { - Console.WriteLine("The B Tree is empty."); - return; + _root = null; } - - _root.Remove(item); - if (_root.Keys.Count == 0) + else { - if (_root.IsLeaf) - { - _root = null; - } - else - { - _root = Root.Children[0]; - } + _root = Root.Children[0]; } } } +} - public class BTreeNode : IComparable> where T : IComparable +public class BTreeNode : IComparable> where T : IComparable +{ + private int _degree; + + public BTreeNode(int degree) { - private int _degree; + _degree = degree; + Children = new List>(degree*2-1); + Keys = new List(degree*2-1); + } - public BTreeNode(int degree) - { - _degree = degree; - Children = new List>(degree*2-1); - Keys = new List(degree*2-1); - } + public BTreeNode Parent { get; set; } - public BTreeNode Parent { get; set; } + public List Keys { set; get; } - public List Keys { set; get; } + public List> Children { set; get; } - public List> Children { set; get; } + public bool IsLeaf => Children.Count == 0; - public bool IsLeaf => Children.Count == 0; + /// + /// A utility function that returns the index of the first key + /// that is greater than or equal to k. + /// + public int FindKey(T value) + { + return Keys.FindLastIndex(searching => value.CompareTo(searching) > 0) + 1; + } - /// - /// A utility function that returns the index of the first key - /// that is greater than or equal to k. - /// - public int FindKey(T value) - { - return Keys.FindLastIndex(searching => value.CompareTo(searching) > 0) + 1; - } + public void Remove(T value) + { + var index = FindKey(value); - public void Remove(T value) + // We found the key! + if (index < Keys.Count && value.CompareTo(Keys[index]) == 0) { - var index = FindKey(value); - - // We found the key! - if (index < Keys.Count && value.CompareTo(Keys[index]) == 0) - { - if (IsLeaf) - RemoveFromLeaf(index); - else - RemoveFromNonLeaf(index); - } + if (IsLeaf) + RemoveFromLeaf(index); else - { - if (IsLeaf) - return; + RemoveFromNonLeaf(index); + } + else + { + if (IsLeaf) + return; - var didMergeLast = index == Children.Count; + var didMergeLast = index == Children.Count; - if (Children[index].Keys.Count < _degree) - Fill(index); + if (Children[index].Keys.Count < _degree) + Fill(index); - // If the last child has been merged, it must have merged with the previous - // child and so we recurse on the (idx-1)th child. Else, we recurse on the - // (idx)th child which now has atleast t keys - if (didMergeLast && index > Children.Count) - Children[index-1].Remove(value); - else - Children[index].Remove(value); - } + // If the last child has been merged, it must have merged with the previous + // child and so we recurse on the (idx-1)th child. Else, we recurse on the + // (idx)th child which now has atleast t keys + if (didMergeLast && index > Children.Count) + Children[index-1].Remove(value); + else + Children[index].Remove(value); } + } - /// - /// Removes the key at index from this leaf node. - /// - public void RemoveFromLeaf(int index) - { - Keys.RemoveAt(index); - } + /// + /// Removes the key at index from this leaf node. + /// + public void RemoveFromLeaf(int index) + { + Keys.RemoveAt(index); + } - /// - /// Removes the key at index from this non-leaf node. - /// - public void RemoveFromNonLeaf(int index) + /// + /// Removes the key at index from this non-leaf node. + /// + public void RemoveFromNonLeaf(int index) + { + // If the child that precedes our key has atleast this._degree keys, + // find the predecessor of our key in the subtree rooted at the child + // at index. Replace our key by it's pred. Recursively delete pred in + // the list of children. + if (Children[index].Keys.Count >= _degree) { - // If the child that precedes our key has atleast this._degree keys, - // find the predecessor of our key in the subtree rooted at the child - // at index. Replace our key by it's pred. Recursively delete pred in - // the list of children. - if (Children[index].Keys.Count >= _degree) - { - var pred = GetPredecessor(index); - Keys[index] = pred; - Children[index].Remove(pred); - } - // If the child has less than this._degree keys, examine the child on - // the other side. If it has atleast this._degree keys, find the successor - // of the key in the subtree rooted at our next child. Replace the key with - // the successor. Recursively delete the successor in the next child. - else if (Children[index+1].Keys.Count >= _degree) - { - var succ = GetSuccessor(index); - Keys[index] = succ; - Children[index+1].Remove(succ); - } - // If both the previous child and the next child has less than this._degree - // keys, merge our key and all of the next child into the previous child. - // Now the previous child contains 2 * this._degree - 1 keys. Recursively - // delete our key from the previous child. - else - { - Merge(index); - Children[index].Remove(Keys[index]); - } + var pred = GetPredecessor(index); + Keys[index] = pred; + Children[index].Remove(pred); } - - /// - /// Fills the Child at index, which has fewer than this._degree-1 keys. - /// - private void Fill(int index) + // If the child has less than this._degree keys, examine the child on + // the other side. If it has atleast this._degree keys, find the successor + // of the key in the subtree rooted at our next child. Replace the key with + // the successor. Recursively delete the successor in the next child. + else if (Children[index+1].Keys.Count >= _degree) { - // If the previous child has keys to spare, take them. - if (index != 0 && Children[index-1].Keys.Count >= _degree) - BorrowFromPrevious(index); - // If the next child has keys to spare, take them. - else if (index != Keys.Count && Children[index].Keys.Count >= _degree) - BorrowFromNext(index); - // Merge this sibling with the next, or previous in the event that this - // is the last child. - else - { - if (index != Children.Count-1) - Merge(index); - else - Merge(index-1); - } + var succ = GetSuccessor(index); + Keys[index] = succ; + Children[index+1].Remove(succ); } - - /// - /// Gets the highest value in the tree rooted at the child at index. - /// - private T GetPredecessor(int index) + // If both the previous child and the next child has less than this._degree + // keys, merge our key and all of the next child into the previous child. + // Now the previous child contains 2 * this._degree - 1 keys. Recursively + // delete our key from the previous child. + else { - var node = Children[index]; - while (!node.IsLeaf) - node = node.Children[node.Children.Count-1]; - return node.Keys[node.Keys.Count-1]; + Merge(index); + Children[index].Remove(Keys[index]); } + } - /// - /// Gets the lowest value in the tree rooted at the child at index+1. - /// - private T GetSuccessor(int index) + /// + /// Fills the Child at index, which has fewer than this._degree-1 keys. + /// + private void Fill(int index) + { + // If the previous child has keys to spare, take them. + if (index != 0 && Children[index-1].Keys.Count >= _degree) + BorrowFromPrevious(index); + // If the next child has keys to spare, take them. + else if (index != Keys.Count && Children[index].Keys.Count >= _degree) + BorrowFromNext(index); + // Merge this sibling with the next, or previous in the event that this + // is the last child. + else { - var node = Children[index+1]; - while (!node.IsLeaf) - node = node.Children[0]; - return node.Keys[0]; + if (index != Children.Count-1) + Merge(index); + else + Merge(index-1); } + } - /// - /// Merges the child at index with the child at index+1. - /// - private void Merge(int index) - { - var child = Children[index]; - var sibling = Children[index+1]; + /// + /// Gets the highest value in the tree rooted at the child at index. + /// + private T GetPredecessor(int index) + { + var node = Children[index]; + while (!node.IsLeaf) + node = node.Children[node.Children.Count-1]; + return node.Keys[node.Keys.Count-1]; + } + + /// + /// Gets the lowest value in the tree rooted at the child at index+1. + /// + private T GetSuccessor(int index) + { + var node = Children[index+1]; + while (!node.IsLeaf) + node = node.Children[0]; + return node.Keys[0]; + } - // Add our key and the siblings keys to the child. - child.Keys.Insert(_degree-1, Keys[index]); - Keys.RemoveAt(index); - child.Keys.AddRange(sibling.Keys); + /// + /// Merges the child at index with the child at index+1. + /// + private void Merge(int index) + { + var child = Children[index]; + var sibling = Children[index+1]; - // Now move the children. - if (!child.IsLeaf) - child.Children.AddRange(sibling.Children); + // Add our key and the siblings keys to the child. + child.Keys.Insert(_degree-1, Keys[index]); + Keys.RemoveAt(index); + child.Keys.AddRange(sibling.Keys); - Children.RemoveAt(index+1); - } + // Now move the children. + if (!child.IsLeaf) + child.Children.AddRange(sibling.Children); - /// - /// Pulls a key from the previous sibling and inserts it in the child - /// at index. - /// - private void BorrowFromPrevious(int index) - { - var child = Children[index]; - var sibling = Children[index-1]; + Children.RemoveAt(index+1); + } + + /// + /// Pulls a key from the previous sibling and inserts it in the child + /// at index. + /// + private void BorrowFromPrevious(int index) + { + var child = Children[index]; + var sibling = Children[index-1]; - // Rotate keys: sibling > parent > child - child.Keys.Insert(0, Keys[index-1]); - Keys[index-1] = sibling.Keys[sibling.Keys.Count-1]; - sibling.Keys.RemoveAt(sibling.Keys.Count-1); + // Rotate keys: sibling > parent > child + child.Keys.Insert(0, Keys[index-1]); + Keys[index-1] = sibling.Keys[sibling.Keys.Count-1]; + sibling.Keys.RemoveAt(sibling.Keys.Count-1); - // Rotate children, if its not a leaf node - if (!child.IsLeaf) - { - child.Children.Insert(0, sibling.Children[sibling.Keys.Count-1]); - sibling.Children.RemoveAt(sibling.Keys.Count-1); - } + // Rotate children, if its not a leaf node + if (!child.IsLeaf) + { + child.Children.Insert(0, sibling.Children[sibling.Keys.Count-1]); + sibling.Children.RemoveAt(sibling.Keys.Count-1); } + } - /// - /// Pulls a key from the next sibling and inserts it in the child - /// at index. - /// - private void BorrowFromNext(int index) - { - var child = Children[index]; - var sibling = Children[index+1]; + /// + /// Pulls a key from the next sibling and inserts it in the child + /// at index. + /// + private void BorrowFromNext(int index) + { + var child = Children[index]; + var sibling = Children[index+1]; - // Rotate keys sibling > parent > child - child.Keys.Add(Keys[index]); - Keys[index] = sibling.Keys[0]; - sibling.Keys.RemoveAt(0); + // Rotate keys sibling > parent > child + child.Keys.Add(Keys[index]); + Keys[index] = sibling.Keys[0]; + sibling.Keys.RemoveAt(0); - // Rotate children if it's not a leaf node - if (!child.IsLeaf) - { - child.Children.Add(sibling.Children[0]); - sibling.Children.RemoveAt(0); - } + // Rotate children if it's not a leaf node + if (!child.IsLeaf) + { + child.Children.Add(sibling.Children[0]); + sibling.Children.RemoveAt(0); } + } - /// - /// Finds the Node that holds the given value. - /// - public BTreeNode Search(T value) - { - var found = Keys.FindIndex(searching => value.CompareTo(searching) == 0); - if (found != -1) - return this; - if (found == -1 && IsLeaf) - return null; + /// + /// Finds the Node that holds the given value. + /// + public BTreeNode Search(T value) + { + var found = Keys.FindIndex(searching => value.CompareTo(searching) == 0); + if (found != -1) + return this; + if (found == -1 && IsLeaf) + return null; - // Find the child - found = Keys.FindLastIndex(searching => value.CompareTo(searching) > 0) + 1; - return Children[found].Search(value); - } + // Find the child + found = Keys.FindLastIndex(searching => value.CompareTo(searching) > 0) + 1; + return Children[found].Search(value); + } - /// - /// Assumes value can be inserted. Callers should verify this.Keys has - /// enough space. - /// - public void InsertNonFull(T value) + /// + /// Assumes value can be inserted. Callers should verify this.Keys has + /// enough space. + /// + public void InsertNonFull(T value) + { + if (IsLeaf) { - if (IsLeaf) - { - // Find where the new key should be inserted. - var i = Keys.FindLastIndex( - delegate(T compare) - { - return value.CompareTo(compare) > 0; - } - ) + 1; - Keys.Insert(i, value); - } - else - { - // Find which child to explore - var i = Keys.FindLastIndex( - delegate(T compare) - { - return value.CompareTo(compare) > 0; - } - ) + 1; - - if (Children[i].Keys.Count >= 2*_degree-1) + // Find where the new key should be inserted. + var i = Keys.FindLastIndex( + delegate(T compare) { - SplitChild(i, Children[i]); - - // One of the new nodes will need to have our value. - if (value.CompareTo(Keys[i]) > 0) - i++; + return value.CompareTo(compare) > 0; } - Children[i].InsertNonFull(value); - } + ) + 1; + Keys.Insert(i, value); } - - /// - /// Splits the given child in 2 - /// - public void SplitChild(int i, BTreeNode child) + else { - // Create a new Node which will store this._degree - 1 keys. - var node = new BTreeNode(child._degree); - - // Copy the keys over, leaving out the middle key - var mid = child.Keys[child._degree-1]; - node.Keys = child.Keys.GetRange(child._degree, child._degree-1); - child.Keys = child.Keys.GetRange(0, child._degree-1); + // Find which child to explore + var i = Keys.FindLastIndex( + delegate(T compare) + { + return value.CompareTo(compare) > 0; + } + ) + 1; - // Copy the children over - if (!child.IsLeaf) + if (Children[i].Keys.Count >= 2*_degree-1) { - node.Children = child.Children.GetRange(child._degree, child._degree); - child.Children = child.Children.GetRange(0, child._degree); + SplitChild(i, Children[i]); + + // One of the new nodes will need to have our value. + if (value.CompareTo(Keys[i]) > 0) + i++; } + Children[i].InsertNonFull(value); + } + } - // Insert the new node in this list of children. - // Keep in mind the index i is for the keys, not children. - Children.Insert(i+1, node); + /// + /// Splits the given child in 2 + /// + public void SplitChild(int i, BTreeNode child) + { + // Create a new Node which will store this._degree - 1 keys. + var node = new BTreeNode(child._degree); - // One of the keys of child will move up to this node. - Keys.Insert(i, mid); - } + // Copy the keys over, leaving out the middle key + var mid = child.Keys[child._degree-1]; + node.Keys = child.Keys.GetRange(child._degree, child._degree-1); + child.Keys = child.Keys.GetRange(0, child._degree-1); - /// - /// Compares to. - /// - public virtual int CompareTo(BTreeNode other) + // Copy the children over + if (!child.IsLeaf) { - if (other == null) - return -1; + node.Children = child.Children.GetRange(child._degree, child._degree); + child.Children = child.Children.GetRange(0, child._degree); + } - if (other.Children.Count != Children.Count) - return -1; + // Insert the new node in this list of children. + // Keep in mind the index i is for the keys, not children. + Children.Insert(i+1, node); - return 0; - } + // One of the keys of child will move up to this node. + Keys.Insert(i, mid); } -} + /// + /// Compares to. + /// + public virtual int CompareTo(BTreeNode other) + { + if (other == null) + return -1; + + if (other.Children.Count != Children.Count) + return -1; + + return 0; + } +} \ No newline at end of file diff --git a/DataStructures/Trees/BinarySearchTree.cs b/DataStructures/Trees/BinarySearchTree.cs index f5a62a6a..b9a57d0e 100644 --- a/DataStructures/Trees/BinarySearchTree.cs +++ b/DataStructures/Trees/BinarySearchTree.cs @@ -5,171 +5,156 @@ using DataStructures.Common; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// Implements a generic Binary Search Tree data structure. +/// +/// Type of elements. +public class BinarySearchTree : IBinarySearchTree where T : IComparable { /// - /// Implements a generic Binary Search Tree data structure. + /// Specifies the mode of travelling through the tree. /// - /// Type of elements. - public class BinarySearchTree : IBinarySearchTree where T : IComparable + public enum TraversalMode { - /// - /// Specifies the mode of travelling through the tree. - /// - public enum TraversalMode - { - InOrder = 0, - PreOrder = 1, - PostOrder = 2 - } + InOrder = 0, + PreOrder = 1, + PostOrder = 2 + } - /// - /// TREE INSTANCE VARIABLES - /// - /// - protected int _count { get; set; } - protected bool _allowDuplicates { get; set; } - protected virtual BSTNode _root { get; set; } + /// + /// TREE INSTANCE VARIABLES + /// + /// + protected int _count { get; set; } + protected bool _allowDuplicates { get; set; } + protected virtual BSTNode _root { get; set; } - public virtual BSTNode Root - { - get => _root; - internal set => _root = value; - } + public virtual BSTNode Root + { + get => _root; + internal set => _root = value; + } - /// - /// CONSTRUCTOR. - /// Allows duplicates by default. - /// - public BinarySearchTree() - { - _count = 0; - _allowDuplicates = true; - Root = null; - } + /// + /// CONSTRUCTOR. + /// Allows duplicates by default. + /// + public BinarySearchTree() + { + _count = 0; + _allowDuplicates = true; + Root = null; + } - /// - /// CONSTRUCTOR. - /// If allowDuplictes is set to false, no duplicate items will be inserted. - /// - public BinarySearchTree(bool allowDuplicates) - { - _count = 0; - _allowDuplicates = allowDuplicates; - Root = null; - } + /// + /// CONSTRUCTOR. + /// If allowDuplictes is set to false, no duplicate items will be inserted. + /// + public BinarySearchTree(bool allowDuplicates) + { + _count = 0; + _allowDuplicates = allowDuplicates; + Root = null; + } - /// - /// Replaces the node's value from it's parent node object with the newValue. - /// Used in the recusive _remove function. - /// - /// BST node. - /// New value. - protected virtual void _replaceNodeInParent(BSTNode node, BSTNode newNode = null) + /// + /// Replaces the node's value from it's parent node object with the newValue. + /// Used in the recusive _remove function. + /// + /// BST node. + /// New value. + protected virtual void _replaceNodeInParent(BSTNode node, BSTNode newNode = null) + { + if (node.Parent != null) { - if (node.Parent != null) - { - if (node.IsLeftChild) - node.Parent.LeftChild = newNode; - else - node.Parent.RightChild = newNode; - } + if (node.IsLeftChild) + node.Parent.LeftChild = newNode; else - { - Root = newNode; - } - - if (newNode != null) - newNode.Parent = node.Parent; + node.Parent.RightChild = newNode; } - - /// - /// Remove the specified node. - /// - /// Node. - /// >True if removed successfully; false if node wasn't found. - protected virtual bool _remove(BSTNode node) + else { - if (node == null) - return false; - - var parent = node.Parent; + Root = newNode; + } - if (node.ChildrenCount == 2) // if both children are present - { - var successor = _findNextLarger(node); - node.Value = successor.Value; - return true && _remove(successor); - } + if (newNode != null) + newNode.Parent = node.Parent; + } - if (node.HasLeftChild) // if the node has only a LEFT child - { - _replaceNodeInParent(node, node.LeftChild); - _count--; + /// + /// Remove the specified node. + /// + /// Node. + /// >True if removed successfully; false if node wasn't found. + protected virtual bool _remove(BSTNode node) + { + if (node == null) + return false; - } - else if (node.HasRightChild) // if the node has only a RIGHT child - { - _replaceNodeInParent(node, node.RightChild); - _count--; - } - else //this node has no children - { - _replaceNodeInParent(node, null); - _count--; - } + var parent = node.Parent; - return true; + if (node.ChildrenCount == 2) // if both children are present + { + var successor = _findNextLarger(node); + node.Value = successor.Value; + return true && _remove(successor); } - /// - /// Inserts a new node to the tree. - /// - /// Current node to insert afters. - /// New node to be inserted. - protected virtual bool _insertNode(BSTNode newNode) + if (node.HasLeftChild) // if the node has only a LEFT child { - // Handle empty trees - if (Root == null) - { - Root = newNode; - _count++; - return true; - } - - if (newNode.Parent == null) - newNode.Parent = Root; + _replaceNodeInParent(node, node.LeftChild); + _count--; - // Check for value equality and whether inserting duplicates is allowed - if (_allowDuplicates == false && newNode.Parent.Value.IsEqualTo(newNode.Value)) - { - return false; - } + } + else if (node.HasRightChild) // if the node has only a RIGHT child + { + _replaceNodeInParent(node, node.RightChild); + _count--; + } + else //this node has no children + { + _replaceNodeInParent(node, null); + _count--; + } - // Go Left - if (newNode.Parent.Value.IsGreaterThan(newNode.Value)) // newNode < parent - { - if (newNode.Parent.HasLeftChild == false) - { - newNode.Parent.LeftChild = newNode; + return true; + } - // Increment count. - _count++; + /// + /// Inserts a new node to the tree. + /// + /// Current node to insert afters. + /// New node to be inserted. + protected virtual bool _insertNode(BSTNode newNode) + { + // Handle empty trees + if (Root == null) + { + Root = newNode; + _count++; + return true; + } - return true; - } + if (newNode.Parent == null) + newNode.Parent = Root; - newNode.Parent = newNode.Parent.LeftChild; - return _insertNode(newNode); - } - // Go Right + // Check for value equality and whether inserting duplicates is allowed + if (_allowDuplicates == false && newNode.Parent.Value.IsEqualTo(newNode.Value)) + { + return false; + } - if (newNode.Parent.HasRightChild == false) + // Go Left + if (newNode.Parent.Value.IsGreaterThan(newNode.Value)) // newNode < parent + { + if (newNode.Parent.HasLeftChild == false) { - newNode.Parent.RightChild = newNode; + newNode.Parent.LeftChild = newNode; // Increment count. _count++; @@ -177,613 +162,626 @@ protected virtual bool _insertNode(BSTNode newNode) return true; } - newNode.Parent = newNode.Parent.RightChild; + newNode.Parent = newNode.Parent.LeftChild; return _insertNode(newNode); } + // Go Right - /// - /// Calculates the tree height from a specific node, recursively. - /// Time-complexity: O(n), where n = number of nodes. - /// - /// Node - /// Height of node's longest subtree - protected virtual int _getTreeHeight(BSTNode node) + if (newNode.Parent.HasRightChild == false) { - if (node == null) - return 0; - // Is leaf node - if (node.IsLeafNode) - return 1; - // Has two children - if (node.ChildrenCount == 2) - return 1 + Math.Max(_getTreeHeight(node.LeftChild), _getTreeHeight(node.RightChild)); - // Has only left - if (node.HasLeftChild) - return 1 + _getTreeHeight(node.LeftChild); - // Has only right - return 1 + _getTreeHeight(node.RightChild); - } - - /// - /// Finds a node inside another node's subtrees, given it's value. - /// - /// Node to start search from. - /// Search value - /// Node if found; otherwise null - protected virtual BSTNode _findNode(BSTNode currentNode, T item) - { - if (currentNode == null) - return currentNode; - - if (item.IsEqualTo(currentNode.Value)) - { - return currentNode; - } - - if (currentNode.HasLeftChild && item.IsLessThan(currentNode.Value)) - { - return _findNode(currentNode.LeftChild, item); - } + newNode.Parent.RightChild = newNode; - if (currentNode.HasRightChild && item.IsGreaterThan(currentNode.Value)) - { - return _findNode(currentNode.RightChild, item); - } + // Increment count. + _count++; - // Return-functions-fix - return null; + return true; } - /// - /// Returns the min-node in a subtree. - /// Used in the recusive _remove function. - /// - /// The minimum-valued tree node. - /// The tree node with subtree(s). - protected virtual BSTNode _findMinNode(BSTNode node) - { - if (node == null) - return node; + newNode.Parent = newNode.Parent.RightChild; + return _insertNode(newNode); + } - var currentNode = node; + /// + /// Calculates the tree height from a specific node, recursively. + /// Time-complexity: O(n), where n = number of nodes. + /// + /// Node + /// Height of node's longest subtree + protected virtual int _getTreeHeight(BSTNode node) + { + if (node == null) + return 0; + // Is leaf node + if (node.IsLeafNode) + return 1; + // Has two children + if (node.ChildrenCount == 2) + return 1 + Math.Max(_getTreeHeight(node.LeftChild), _getTreeHeight(node.RightChild)); + // Has only left + if (node.HasLeftChild) + return 1 + _getTreeHeight(node.LeftChild); + // Has only right + return 1 + _getTreeHeight(node.RightChild); + } - while (currentNode.HasLeftChild) - currentNode = currentNode.LeftChild; + /// + /// Finds a node inside another node's subtrees, given it's value. + /// + /// Node to start search from. + /// Search value + /// Node if found; otherwise null + protected virtual BSTNode _findNode(BSTNode currentNode, T item) + { + if (currentNode == null) + return currentNode; + if (item.IsEqualTo(currentNode.Value)) + { return currentNode; } - /// - /// Returns the max-node in a subtree. - /// Used in the recusive _remove function. - /// - /// The maximum-valued tree node. - /// The tree node with subtree(s). - protected virtual BSTNode _findMaxNode(BSTNode node) + if (currentNode.HasLeftChild && item.IsLessThan(currentNode.Value)) { - if (node == null) - return node; + return _findNode(currentNode.LeftChild, item); + } - var currentNode = node; + if (currentNode.HasRightChild && item.IsGreaterThan(currentNode.Value)) + { + return _findNode(currentNode.RightChild, item); + } - while (currentNode.HasRightChild) - currentNode = currentNode.RightChild; + // Return-functions-fix + return null; + } - return currentNode; - } + /// + /// Returns the min-node in a subtree. + /// Used in the recusive _remove function. + /// + /// The minimum-valued tree node. + /// The tree node with subtree(s). + protected virtual BSTNode _findMinNode(BSTNode node) + { + if (node == null) + return node; - /// - /// Finds the next smaller node in value compared to the specified node. - /// - protected virtual BSTNode _findNextSmaller(BSTNode node) - { - if (node == null) - return node; + var currentNode = node; - if (node.HasLeftChild) - return _findMaxNode(node.LeftChild); + while (currentNode.HasLeftChild) + currentNode = currentNode.LeftChild; - var currentNode = node; - while (currentNode.Parent != null && currentNode.IsLeftChild) - currentNode = currentNode.Parent; + return currentNode; + } - return currentNode.Parent; - } + /// + /// Returns the max-node in a subtree. + /// Used in the recusive _remove function. + /// + /// The maximum-valued tree node. + /// The tree node with subtree(s). + protected virtual BSTNode _findMaxNode(BSTNode node) + { + if (node == null) + return node; - /// - /// Finds the next larger node in value compared to the specified node. - /// - protected virtual BSTNode _findNextLarger(BSTNode node) - { - if (node == null) - return node; + var currentNode = node; - if (node.HasRightChild) - return _findMinNode(node.RightChild); + while (currentNode.HasRightChild) + currentNode = currentNode.RightChild; - var currentNode = node; - while (currentNode.Parent != null && currentNode.IsRightChild) - currentNode = currentNode.Parent; + return currentNode; + } - return currentNode.Parent; - } + /// + /// Finds the next smaller node in value compared to the specified node. + /// + protected virtual BSTNode _findNextSmaller(BSTNode node) + { + if (node == null) + return node; - /// - /// A recursive private method. Used in the public FindAll(predicate) functions. - /// Implements in-order traversal to find all the matching elements in a subtree. - /// - /// Node to start searching from. - /// - protected virtual void _findAll(BSTNode currentNode, Predicate match, ref List list) - { - if (currentNode == null) - return; + if (node.HasLeftChild) + return _findMaxNode(node.LeftChild); - // call the left child - _findAll(currentNode.LeftChild, match, ref list); + var currentNode = node; + while (currentNode.Parent != null && currentNode.IsLeftChild) + currentNode = currentNode.Parent; - if (match(currentNode.Value)) // match - { - list.Add(currentNode.Value); - } + return currentNode.Parent; + } - // call the right child - _findAll(currentNode.RightChild, match, ref list); - } + /// + /// Finds the next larger node in value compared to the specified node. + /// + protected virtual BSTNode _findNextLarger(BSTNode node) + { + if (node == null) + return node; - /// - /// In-order traversal of the subtrees of a node. Returns every node it vists. - /// - /// Node to traverse the tree from. - /// List to add elements to. - protected virtual void _inOrderTraverse(BSTNode currentNode, ref List list) - { - if (currentNode == null) - return; + if (node.HasRightChild) + return _findMinNode(node.RightChild); - // call the left child - _inOrderTraverse(currentNode.LeftChild, ref list); + var currentNode = node; + while (currentNode.Parent != null && currentNode.IsRightChild) + currentNode = currentNode.Parent; - // visit node - list.Add(currentNode.Value); + return currentNode.Parent; + } + + /// + /// A recursive private method. Used in the public FindAll(predicate) functions. + /// Implements in-order traversal to find all the matching elements in a subtree. + /// + /// Node to start searching from. + /// + protected virtual void _findAll(BSTNode currentNode, Predicate match, ref List list) + { + if (currentNode == null) + return; + + // call the left child + _findAll(currentNode.LeftChild, match, ref list); - // call the right child - _inOrderTraverse(currentNode.RightChild, ref list); + if (match(currentNode.Value)) // match + { + list.Add(currentNode.Value); } + // call the right child + _findAll(currentNode.RightChild, match, ref list); + } - /// - /// Return the number of elements in this tree - /// - /// - public virtual int Count => _count; + /// + /// In-order traversal of the subtrees of a node. Returns every node it vists. + /// + /// Node to traverse the tree from. + /// List to add elements to. + protected virtual void _inOrderTraverse(BSTNode currentNode, ref List list) + { + if (currentNode == null) + return; + + // call the left child + _inOrderTraverse(currentNode.LeftChild, ref list); + + // visit node + list.Add(currentNode.Value); + + // call the right child + _inOrderTraverse(currentNode.RightChild, ref list); + } - /// - /// Checks if tree is empty. - /// - /// - public virtual bool IsEmpty => _count == 0; - /// - /// Returns the height of the tree. - /// Time-complexity: O(n), where n = number of nodes. - /// - /// Hight - public virtual int Height + /// + /// Return the number of elements in this tree + /// + /// + public virtual int Count => _count; + + /// + /// Checks if tree is empty. + /// + /// + public virtual bool IsEmpty => _count == 0; + + /// + /// Returns the height of the tree. + /// Time-complexity: O(n), where n = number of nodes. + /// + /// Hight + public virtual int Height + { + get { - get - { - if (IsEmpty) - return 0; + if (IsEmpty) + return 0; - var currentNode = Root; - return _getTreeHeight(currentNode); - } + var currentNode = Root; + return _getTreeHeight(currentNode); } + } - public virtual bool AllowsDuplicates => _allowDuplicates; + public virtual bool AllowsDuplicates => _allowDuplicates; - /// - /// Inserts an element to the tree - /// - /// Item to insert - public virtual void Insert(T item) - { - var newNode = new BSTNode(item); + /// + /// Inserts an element to the tree + /// + /// Item to insert + public virtual void Insert(T item) + { + var newNode = new BSTNode(item); - // Insert node recursively starting from the root. check for success status. - var success = _insertNode(newNode); + // Insert node recursively starting from the root. check for success status. + var success = _insertNode(newNode); - if (success == false && _allowDuplicates == false) - throw new InvalidOperationException("Tree does not allow inserting duplicate elements."); - } + if (success == false && _allowDuplicates == false) + throw new InvalidOperationException("Tree does not allow inserting duplicate elements."); + } - /// - /// Inserts an array of elements to the tree. - /// - public virtual void Insert(T[] collection) - { - if (collection == null) - throw new ArgumentNullException(); + /// + /// Inserts an array of elements to the tree. + /// + public virtual void Insert(T[] collection) + { + if (collection == null) + throw new ArgumentNullException(); - if (collection.Length > 0) + if (collection.Length > 0) + { + for (int i = 0; i < collection.Length; ++i) { - for (int i = 0; i < collection.Length; ++i) - { - Insert(collection[i]); - } + Insert(collection[i]); } } + } - /// - /// Inserts a list of elements to the tree. - /// - public virtual void Insert(List collection) - { - if (collection == null) - throw new ArgumentNullException(); + /// + /// Inserts a list of elements to the tree. + /// + public virtual void Insert(List collection) + { + if (collection == null) + throw new ArgumentNullException(); - if (collection.Count > 0) + if (collection.Count > 0) + { + for (int i = 0; i < collection.Count; ++i) { - for (int i = 0; i < collection.Count; ++i) - { - Insert(collection[i]); - } + Insert(collection[i]); } } + } - /// - /// Deletes an element from the tree - /// - /// item to remove. - public virtual void Remove(T item) - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Deletes an element from the tree + /// + /// item to remove. + public virtual void Remove(T item) + { + if (IsEmpty) + throw new Exception("Tree is empty."); - var node = _findNode(Root, item); - bool status = _remove(node); + var node = _findNode(Root, item); + bool status = _remove(node); - // If the element was found, remove it. - if (status == false) - throw new Exception("Item was not found."); - } + // If the element was found, remove it. + if (status == false) + throw new Exception("Item was not found."); + } - /// - /// Removes the min value from tree. - /// - public virtual void RemoveMin() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Removes the min value from tree. + /// + public virtual void RemoveMin() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - var node = _findMinNode(Root); - _remove(node); - } + var node = _findMinNode(Root); + _remove(node); + } - /// - /// Removes the max value from tree. - /// - public virtual void RemoveMax() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Removes the max value from tree. + /// + public virtual void RemoveMax() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - var node = _findMaxNode(Root); - _remove(node); - } + var node = _findMaxNode(Root); + _remove(node); + } - /// - /// Clears all elements from tree. - /// - public virtual void Clear() - { - Root = null; - _count = 0; - } + /// + /// Clears all elements from tree. + /// + public virtual void Clear() + { + Root = null; + _count = 0; + } - /// - /// Checks for the existence of an item - /// - public virtual bool Contains(T item) - { - return _findNode(_root, item) != null; - } + /// + /// Checks for the existence of an item + /// + public virtual bool Contains(T item) + { + return _findNode(_root, item) != null; + } - /// - /// Finds the minimum in tree - /// - /// Min - public virtual T FindMin() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Finds the minimum in tree + /// + /// Min + public virtual T FindMin() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - return _findMinNode(Root).Value; - } + return _findMinNode(Root).Value; + } - /// - /// Finds the next smaller element in tree, compared to the specified item. - /// - public virtual T FindNextSmaller(T item) - { - var node = _findNode(Root, item); - var nextSmaller = _findNextSmaller(node); + /// + /// Finds the next smaller element in tree, compared to the specified item. + /// + public virtual T FindNextSmaller(T item) + { + var node = _findNode(Root, item); + var nextSmaller = _findNextSmaller(node); - if (nextSmaller == null) - throw new Exception("Item was not found."); + if (nextSmaller == null) + throw new Exception("Item was not found."); - return nextSmaller.Value; - } + return nextSmaller.Value; + } - /// - /// Finds the next larger element in tree, compared to the specified item. - /// - public virtual T FindNextLarger(T item) - { - var node = _findNode(Root, item); - var nextLarger = _findNextLarger(node); + /// + /// Finds the next larger element in tree, compared to the specified item. + /// + public virtual T FindNextLarger(T item) + { + var node = _findNode(Root, item); + var nextLarger = _findNextLarger(node); - if (nextLarger == null) - throw new Exception("Item was not found."); + if (nextLarger == null) + throw new Exception("Item was not found."); - return nextLarger.Value; - } + return nextLarger.Value; + } - /// - /// Finds the maximum in tree - /// - /// Max - public virtual T FindMax() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Finds the maximum in tree + /// + /// Max + public virtual T FindMax() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - return _findMaxNode(Root).Value; - } + return _findMaxNode(Root).Value; + } - /// - /// Find the item in the tree. Throws an exception if not found. - /// - /// Item to find. - /// Item. - public virtual T Find(T item) - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Find the item in the tree. Throws an exception if not found. + /// + /// Item to find. + /// Item. + public virtual T Find(T item) + { + if (IsEmpty) + throw new Exception("Tree is empty."); - var node = _findNode(Root, item); + var node = _findNode(Root, item); - if (node != null) - return node.Value; - throw new Exception("Item was not found."); - } + if (node != null) + return node.Value; + throw new Exception("Item was not found."); + } - /// - /// Given a predicate function, find all the elements that match it. - /// - /// The search predicate - /// ArrayList of elements. - public virtual IEnumerable FindAll(Predicate searchPredicate) - { - var list = new List(); - _findAll(Root, searchPredicate, ref list); + /// + /// Given a predicate function, find all the elements that match it. + /// + /// The search predicate + /// ArrayList of elements. + public virtual IEnumerable FindAll(Predicate searchPredicate) + { + var list = new List(); + _findAll(Root, searchPredicate, ref list); - return list; - } + return list; + } - /// - /// Returns an array of nodes' values. - /// - /// The array. - public virtual T[] ToArray() - { - return ToList().ToArray(); - } + /// + /// Returns an array of nodes' values. + /// + /// The array. + public virtual T[] ToArray() + { + return ToList().ToArray(); + } - /// - /// Returns a list of the nodes' value. - /// - public virtual List ToList() - { - var list = new List(); - _inOrderTraverse(Root, ref list); + /// + /// Returns a list of the nodes' value. + /// + public virtual List ToList() + { + var list = new List(); + _inOrderTraverse(Root, ref list); - return list; - } + return list; + } - /*********************************************************************/ + /*********************************************************************/ - /// - /// Returns an enumerator that visits node in the order: parent, left child, right child - /// - public virtual IEnumerator GetPreOrderEnumerator() - { - return new BinarySearchTreePreOrderEnumerator(this); - } + /// + /// Returns an enumerator that visits node in the order: parent, left child, right child + /// + public virtual IEnumerator GetPreOrderEnumerator() + { + return new BinarySearchTreePreOrderEnumerator(this); + } - /// - /// Returns an enumerator that visits node in the order: left child, parent, right child - /// - public virtual IEnumerator GetInOrderEnumerator() - { - return new BinarySearchTreeInOrderEnumerator(this); - } + /// + /// Returns an enumerator that visits node in the order: left child, parent, right child + /// + public virtual IEnumerator GetInOrderEnumerator() + { + return new BinarySearchTreeInOrderEnumerator(this); + } - /// - /// Returns an enumerator that visits node in the order: left child, right child, parent - /// - public virtual IEnumerator GetPostOrderEnumerator() - { - return new BinarySearchTreePostOrderEnumerator(this); - } + /// + /// Returns an enumerator that visits node in the order: left child, right child, parent + /// + public virtual IEnumerator GetPostOrderEnumerator() + { + return new BinarySearchTreePostOrderEnumerator(this); + } - /*********************************************************************/ + /*********************************************************************/ - /// - /// Returns an preorder-traversal enumerator for the tree values - /// - internal class BinarySearchTreePreOrderEnumerator : IEnumerator + /// + /// Returns an preorder-traversal enumerator for the tree values + /// + internal class BinarySearchTreePreOrderEnumerator : IEnumerator + { + private BSTNode current; + private BinarySearchTree tree; + internal Queue> traverseQueue; + + public BinarySearchTreePreOrderEnumerator(BinarySearchTree tree) { - private BSTNode current; - private BinarySearchTree tree; - internal Queue> traverseQueue; + this.tree = tree; - public BinarySearchTreePreOrderEnumerator(BinarySearchTree tree) - { - this.tree = tree; + //Build queue + traverseQueue = new Queue>(); + visitNode(this.tree.Root); + } - //Build queue - traverseQueue = new Queue>(); - visitNode(this.tree.Root); - } + private void visitNode(BSTNode node) + { + if (node == null) + return; + traverseQueue.Enqueue(node); + visitNode(node.LeftChild); + visitNode(node.RightChild); + } - private void visitNode(BSTNode node) - { - if (node == null) - return; - traverseQueue.Enqueue(node); - visitNode(node.LeftChild); - visitNode(node.RightChild); - } + public T Current => current.Value; - public T Current => current.Value; + object IEnumerator.Current => Current; - object IEnumerator.Current => Current; + public void Dispose() + { + current = null; + tree = null; + } - public void Dispose() - { - current = null; - tree = null; - } + public void Reset() + { + current = null; + } - public void Reset() - { + public bool MoveNext() + { + if (traverseQueue.Count > 0) + current = traverseQueue.Dequeue(); + else current = null; - } - - public bool MoveNext() - { - if (traverseQueue.Count > 0) - current = traverseQueue.Dequeue(); - else - current = null; - return current != null; - } + return current != null; } + } + + /// + /// Returns an inorder-traversal enumerator for the tree values + /// + internal class BinarySearchTreeInOrderEnumerator : IEnumerator + { + private BSTNode current; + private BinarySearchTree tree; + internal Queue> traverseQueue; - /// - /// Returns an inorder-traversal enumerator for the tree values - /// - internal class BinarySearchTreeInOrderEnumerator : IEnumerator + public BinarySearchTreeInOrderEnumerator(BinarySearchTree tree) { - private BSTNode current; - private BinarySearchTree tree; - internal Queue> traverseQueue; + this.tree = tree; - public BinarySearchTreeInOrderEnumerator(BinarySearchTree tree) - { - this.tree = tree; + //Build queue + traverseQueue = new Queue>(); + visitNode(this.tree.Root); + } - //Build queue - traverseQueue = new Queue>(); - visitNode(this.tree.Root); - } + private void visitNode(BSTNode node) + { + if (node == null) + return; + visitNode(node.LeftChild); + traverseQueue.Enqueue(node); + visitNode(node.RightChild); + } - private void visitNode(BSTNode node) - { - if (node == null) - return; - visitNode(node.LeftChild); - traverseQueue.Enqueue(node); - visitNode(node.RightChild); - } + public T Current => current.Value; - public T Current => current.Value; + object IEnumerator.Current => Current; - object IEnumerator.Current => Current; + public void Dispose() + { + current = null; + tree = null; + } - public void Dispose() - { - current = null; - tree = null; - } + public void Reset() + { + current = null; + } - public void Reset() - { + public bool MoveNext() + { + if (traverseQueue.Count > 0) + current = traverseQueue.Dequeue(); + else current = null; - } - public bool MoveNext() - { - if (traverseQueue.Count > 0) - current = traverseQueue.Dequeue(); - else - current = null; - - return current != null; - } + return current != null; } + } + + /// + /// Returns a postorder-traversal enumerator for the tree values + /// + internal class BinarySearchTreePostOrderEnumerator : IEnumerator + { + private BSTNode current; + private BinarySearchTree tree; + internal Queue> traverseQueue; - /// - /// Returns a postorder-traversal enumerator for the tree values - /// - internal class BinarySearchTreePostOrderEnumerator : IEnumerator + public BinarySearchTreePostOrderEnumerator(BinarySearchTree tree) { - private BSTNode current; - private BinarySearchTree tree; - internal Queue> traverseQueue; + this.tree = tree; - public BinarySearchTreePostOrderEnumerator(BinarySearchTree tree) - { - this.tree = tree; + //Build queue + traverseQueue = new Queue>(); + visitNode(this.tree.Root); + } - //Build queue - traverseQueue = new Queue>(); - visitNode(this.tree.Root); - } + private void visitNode(BSTNode node) + { + if (node == null) + return; + visitNode(node.LeftChild); + visitNode(node.RightChild); + traverseQueue.Enqueue(node); + } - private void visitNode(BSTNode node) - { - if (node == null) - return; - visitNode(node.LeftChild); - visitNode(node.RightChild); - traverseQueue.Enqueue(node); - } + public T Current => current.Value; - public T Current => current.Value; + object IEnumerator.Current => Current; - object IEnumerator.Current => Current; + public void Dispose() + { + current = null; + tree = null; + } - public void Dispose() - { - current = null; - tree = null; - } + public void Reset() + { + current = null; + } - public void Reset() - { + public bool MoveNext() + { + if (traverseQueue.Count > 0) + current = traverseQueue.Dequeue(); + else current = null; - } - - public bool MoveNext() - { - if (traverseQueue.Count > 0) - current = traverseQueue.Dequeue(); - else - current = null; - return current != null; - } + return current != null; } + } - }//end-of-binary-search-tree - -} +}//end-of-binary-search-tree \ No newline at end of file diff --git a/DataStructures/Trees/BinarySearchTreeMap.cs b/DataStructures/Trees/BinarySearchTreeMap.cs index f9f4d2db..ed9a4c9f 100644 --- a/DataStructures/Trees/BinarySearchTreeMap.cs +++ b/DataStructures/Trees/BinarySearchTreeMap.cs @@ -4,125 +4,110 @@ using DataStructures.Common; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// Implements a generic Binary Search Tree Map data structure. +/// +public class BinarySearchTreeMap : IBinarySearchTree where TKey : IComparable { /// - /// Implements a generic Binary Search Tree Map data structure. + /// Specifies the mode of travelling through the tree. /// - public class BinarySearchTreeMap : IBinarySearchTree where TKey : IComparable + public enum TraversalMode { - /// - /// Specifies the mode of travelling through the tree. - /// - public enum TraversalMode - { - InOrder = 0, - PreOrder = 1, - PostOrder = 2 - } + InOrder = 0, + PreOrder = 1, + PostOrder = 2 + } - /// - /// TREE INSTANCE VARIABLES - /// - protected int _count { get; set; } - protected bool _allowDuplicates { get; set; } - protected virtual BSTMapNode _root { get; set; } - - public virtual BSTMapNode Root - { - get => _root; - internal set => _root = value; - } - - - /// - /// CONSTRUCTOR. - /// Allows duplicates by default. - /// - public BinarySearchTreeMap() - { - _count = 0; - _allowDuplicates = true; - Root = null; - } + /// + /// TREE INSTANCE VARIABLES + /// + protected int _count { get; set; } + protected bool _allowDuplicates { get; set; } + protected virtual BSTMapNode _root { get; set; } - /// - /// CONSTRUCTOR. - /// If allowDuplictes is set to false, no duplicate items will be inserted. - /// - public BinarySearchTreeMap(bool allowDuplicates) - { - _count = 0; - _allowDuplicates = allowDuplicates; - Root = null; - } + public virtual BSTMapNode Root + { + get => _root; + internal set => _root = value; + } - /// - /// Calculates the tree height from a specific node, recursively. - /// Time-complexity: O(n), where n = number of nodes. - /// - protected virtual int _getTreeHeight(BSTMapNode node) - { - if (node == null) - return 0; - // Is leaf node - if (node.IsLeafNode) - return 1; - // Has two children - if (node.ChildrenCount == 2) - return 1 + Math.Max(_getTreeHeight(node.LeftChild), _getTreeHeight(node.RightChild)); - // Has only left - if (node.HasLeftChild) - return 1 + _getTreeHeight(node.LeftChild); - // Has only right - return 1 + _getTreeHeight(node.RightChild); - } - - /// - /// Inserts a new node to the tree. - /// - protected virtual bool _insertNode(BSTMapNode newNode) - { - // Handle empty trees - if (Root == null) - { - Root = newNode; - _count++; - return true; - } + /// + /// CONSTRUCTOR. + /// Allows duplicates by default. + /// + public BinarySearchTreeMap() + { + _count = 0; + _allowDuplicates = true; + Root = null; + } - if (newNode.Parent == null) - newNode.Parent = Root; + /// + /// CONSTRUCTOR. + /// If allowDuplictes is set to false, no duplicate items will be inserted. + /// + public BinarySearchTreeMap(bool allowDuplicates) + { + _count = 0; + _allowDuplicates = allowDuplicates; + Root = null; + } - // Check for value equality and whether inserting duplicates is allowed - if (_allowDuplicates == false && newNode.Parent.Key.IsEqualTo(newNode.Key)) - { - return false; - } - // Go Left - if (newNode.Parent.Key.IsGreaterThan(newNode.Key)) // newNode < parent - { - if (newNode.Parent.HasLeftChild == false) - { - newNode.Parent.LeftChild = newNode; + /// + /// Calculates the tree height from a specific node, recursively. + /// Time-complexity: O(n), where n = number of nodes. + /// + protected virtual int _getTreeHeight(BSTMapNode node) + { + if (node == null) + return 0; + // Is leaf node + if (node.IsLeafNode) + return 1; + // Has two children + if (node.ChildrenCount == 2) + return 1 + Math.Max(_getTreeHeight(node.LeftChild), _getTreeHeight(node.RightChild)); + // Has only left + if (node.HasLeftChild) + return 1 + _getTreeHeight(node.LeftChild); + // Has only right + return 1 + _getTreeHeight(node.RightChild); + } - // Increment count. - _count++; + /// + /// Inserts a new node to the tree. + /// + protected virtual bool _insertNode(BSTMapNode newNode) + { + // Handle empty trees + if (Root == null) + { + Root = newNode; + _count++; + return true; + } - return true; - } + if (newNode.Parent == null) + newNode.Parent = Root; - newNode.Parent = newNode.Parent.LeftChild; - return _insertNode(newNode); - } - // Go Right + // Check for value equality and whether inserting duplicates is allowed + if (_allowDuplicates == false && newNode.Parent.Key.IsEqualTo(newNode.Key)) + { + return false; + } - if (newNode.Parent.HasRightChild == false) + // Go Left + if (newNode.Parent.Key.IsGreaterThan(newNode.Key)) // newNode < parent + { + if (newNode.Parent.HasLeftChild == false) { - newNode.Parent.RightChild = newNode; + newNode.Parent.LeftChild = newNode; // Increment count. _count++; @@ -130,685 +115,698 @@ protected virtual bool _insertNode(BSTMapNode newNode) return true; } - newNode.Parent = newNode.Parent.RightChild; + newNode.Parent = newNode.Parent.LeftChild; return _insertNode(newNode); } + // Go Right - /// - /// Replaces the node's value from it's parent node object with the newValue. - /// Used in the recusive _remove function. - /// - protected virtual void _replaceNodeInParent(BSTMapNode node, BSTMapNode newNode = null) + if (newNode.Parent.HasRightChild == false) { - if (node.Parent != null) - { - if (node.IsLeftChild) - node.Parent.LeftChild = newNode; - else - node.Parent.RightChild = newNode; - } + newNode.Parent.RightChild = newNode; - if (newNode != null) - newNode.Parent = node.Parent; + // Increment count. + _count++; + + return true; } - /// - /// Remove the specified node. - /// - protected virtual bool _remove(BSTMapNode node) + newNode.Parent = newNode.Parent.RightChild; + return _insertNode(newNode); + } + + /// + /// Replaces the node's value from it's parent node object with the newValue. + /// Used in the recusive _remove function. + /// + protected virtual void _replaceNodeInParent(BSTMapNode node, BSTMapNode newNode = null) + { + if (node.Parent != null) { - if (node == null) - return false; + if (node.IsLeftChild) + node.Parent.LeftChild = newNode; + else + node.Parent.RightChild = newNode; + } - var parent = node.Parent; + if (newNode != null) + newNode.Parent = node.Parent; + } - if (node.ChildrenCount == 2) // if both children are present - { - var successor = node.RightChild; - node.Key = successor.Key; - node.Value = successor.Value; - return true && _remove(successor); - } + /// + /// Remove the specified node. + /// + protected virtual bool _remove(BSTMapNode node) + { + if (node == null) + return false; - if (node.HasLeftChild) // if the node has only a LEFT child - { - _replaceNodeInParent(node, node.LeftChild); - _count--; + var parent = node.Parent; - } - else if (node.HasRightChild) // if the node has only a RIGHT child - { - _replaceNodeInParent(node, node.RightChild); - _count--; - } - else //this node has no children - { - _replaceNodeInParent(node, null); - _count--; - } - - return true; + if (node.ChildrenCount == 2) // if both children are present + { + var successor = node.RightChild; + node.Key = successor.Key; + node.Value = successor.Value; + return true && _remove(successor); } - /// - /// Finds a node inside another node's subtrees, given it's value. - /// - protected virtual BSTMapNode _findNode(BSTMapNode currentNode, TKey key) + if (node.HasLeftChild) // if the node has only a LEFT child { - if (currentNode == null) - return currentNode; - - if (key.IsEqualTo(currentNode.Key)) - { - return currentNode; - } + _replaceNodeInParent(node, node.LeftChild); + _count--; - if (currentNode.HasLeftChild && key.IsLessThan(currentNode.Key)) - { - return _findNode(currentNode.LeftChild, key); - } - - if (currentNode.HasRightChild && key.IsGreaterThan(currentNode.Key)) - { - return _findNode(currentNode.RightChild, key); - } - - // Return-functions-fix - return null; } - - /// - /// Returns the min-node in a subtree. - /// Used in the recusive _remove function. - /// - protected virtual BSTMapNode _findMinNode(BSTMapNode node) + else if (node.HasRightChild) // if the node has only a RIGHT child { - if (node == null) - return node; + _replaceNodeInParent(node, node.RightChild); + _count--; + } + else //this node has no children + { + _replaceNodeInParent(node, null); + _count--; + } - var currentNode = node; + return true; + } - while (currentNode.HasLeftChild) - currentNode = currentNode.LeftChild; + /// + /// Finds a node inside another node's subtrees, given it's value. + /// + protected virtual BSTMapNode _findNode(BSTMapNode currentNode, TKey key) + { + if (currentNode == null) + return currentNode; + if (key.IsEqualTo(currentNode.Key)) + { return currentNode; } - /// - /// Returns the max-node in a subtree. - /// Used in the recusive _remove function. - /// - protected virtual BSTMapNode _findMaxNode(BSTMapNode node) + if (currentNode.HasLeftChild && key.IsLessThan(currentNode.Key)) { - if (node == null) - return node; - - var currentNode = node; - while (currentNode.HasRightChild) - currentNode = currentNode.RightChild; - - return currentNode; + return _findNode(currentNode.LeftChild, key); } - /// - /// Finds the next smaller node in value compared to the specified node. - /// - protected virtual BSTMapNode _findNextSmaller(BSTMapNode node) + if (currentNode.HasRightChild && key.IsGreaterThan(currentNode.Key)) { - if (node == null) - return node; + return _findNode(currentNode.RightChild, key); + } - if (node.HasLeftChild) - return _findMaxNode(node.LeftChild); + // Return-functions-fix + return null; + } - var currentNode = node; - while (currentNode.Parent != null && currentNode.IsLeftChild) - currentNode = currentNode.Parent; + /// + /// Returns the min-node in a subtree. + /// Used in the recusive _remove function. + /// + protected virtual BSTMapNode _findMinNode(BSTMapNode node) + { + if (node == null) + return node; - return currentNode.Parent; - } + var currentNode = node; - /// - /// Finds the next larger node in value compared to the specified node. - /// - protected virtual BSTMapNode _findNextLarger(BSTMapNode node) - { - if (node == null) - return node; + while (currentNode.HasLeftChild) + currentNode = currentNode.LeftChild; - if (node.HasRightChild) - return _findMinNode(node.RightChild); + return currentNode; + } - var currentNode = node; - while (currentNode.Parent != null && currentNode.IsRightChild) - currentNode = currentNode.Parent; + /// + /// Returns the max-node in a subtree. + /// Used in the recusive _remove function. + /// + protected virtual BSTMapNode _findMaxNode(BSTMapNode node) + { + if (node == null) + return node; - return currentNode.Parent; - } + var currentNode = node; + while (currentNode.HasRightChild) + currentNode = currentNode.RightChild; - /// - /// A recursive private method. Used in the public FindAll(predicate) functions. - /// Implements in-order traversal to find all the matching elements in a subtree. - /// - protected virtual void _findAll(BSTMapNode currentNode, Predicate match, ref List> list) - { - if (currentNode == null) - return; + return currentNode; + } - // call the left child - _findAll(currentNode.LeftChild, match, ref list); + /// + /// Finds the next smaller node in value compared to the specified node. + /// + protected virtual BSTMapNode _findNextSmaller(BSTMapNode node) + { + if (node == null) + return node; - if (match(currentNode.Key)) // match - list.Add(new KeyValuePair(currentNode.Key, currentNode.Value)); + if (node.HasLeftChild) + return _findMaxNode(node.LeftChild); - // call the right child - _findAll(currentNode.RightChild, match, ref list); - } + var currentNode = node; + while (currentNode.Parent != null && currentNode.IsLeftChild) + currentNode = currentNode.Parent; - /// - /// In-order traversal of the subtrees of a node. Returns every node it vists. - /// - protected virtual void _inOrderTraverse(BSTMapNode currentNode, ref List> list) - { - if (currentNode == null) - return; + return currentNode.Parent; + } - // call the left child - _inOrderTraverse(currentNode.LeftChild, ref list); + /// + /// Finds the next larger node in value compared to the specified node. + /// + protected virtual BSTMapNode _findNextLarger(BSTMapNode node) + { + if (node == null) + return node; - // visit node + if (node.HasRightChild) + return _findMinNode(node.RightChild); + + var currentNode = node; + while (currentNode.Parent != null && currentNode.IsRightChild) + currentNode = currentNode.Parent; + + return currentNode.Parent; + } + + /// + /// A recursive private method. Used in the public FindAll(predicate) functions. + /// Implements in-order traversal to find all the matching elements in a subtree. + /// + protected virtual void _findAll(BSTMapNode currentNode, Predicate match, ref List> list) + { + if (currentNode == null) + return; + + // call the left child + _findAll(currentNode.LeftChild, match, ref list); + + if (match(currentNode.Key)) // match list.Add(new KeyValuePair(currentNode.Key, currentNode.Value)); - // call the right child - _inOrderTraverse(currentNode.RightChild, ref list); - } + // call the right child + _findAll(currentNode.RightChild, match, ref list); + } + + /// + /// In-order traversal of the subtrees of a node. Returns every node it vists. + /// + protected virtual void _inOrderTraverse(BSTMapNode currentNode, ref List> list) + { + if (currentNode == null) + return; + + // call the left child + _inOrderTraverse(currentNode.LeftChild, ref list); + + // visit node + list.Add(new KeyValuePair(currentNode.Key, currentNode.Value)); + // call the right child + _inOrderTraverse(currentNode.RightChild, ref list); + } - /// - /// Return the number of elements in this tree - /// - public virtual int Count => _count; - /// - /// Checks if tree is empty. - /// - public virtual bool IsEmpty => _count == 0; + /// + /// Return the number of elements in this tree + /// + public virtual int Count => _count; + + /// + /// Checks if tree is empty. + /// + public virtual bool IsEmpty => _count == 0; - /// - /// Returns the height of the tree. - /// Time-complexity: O(n), where n = number of nodes. - /// - public virtual int Height + /// + /// Returns the height of the tree. + /// Time-complexity: O(n), where n = number of nodes. + /// + public virtual int Height + { + get { - get - { - if (IsEmpty) - return 0; + if (IsEmpty) + return 0; - var currentNode = Root; - return _getTreeHeight(currentNode); - } + var currentNode = Root; + return _getTreeHeight(currentNode); } + } - public virtual bool AllowsDuplicates => _allowDuplicates; + public virtual bool AllowsDuplicates => _allowDuplicates; - /// - /// Inserts a key-value pair to the tree - /// - public virtual void Insert(TKey key, TValue value) - { - var newNode = new BSTMapNode(key, value); + /// + /// Inserts a key-value pair to the tree + /// + public virtual void Insert(TKey key, TValue value) + { + var newNode = new BSTMapNode(key, value); - // Insert node recursively starting from the root. check for success status. - var success = _insertNode(newNode); + // Insert node recursively starting from the root. check for success status. + var success = _insertNode(newNode); - if (success == false && _allowDuplicates == false) - throw new InvalidOperationException("Tree does not allow inserting duplicate elements."); - } + if (success == false && _allowDuplicates == false) + throw new InvalidOperationException("Tree does not allow inserting duplicate elements."); + } - /// - /// Inserts a key-value pair to the tree - /// - public virtual void Insert(KeyValuePair keyValuePair) - { - Insert(keyValuePair.Key, keyValuePair.Value); - } + /// + /// Inserts a key-value pair to the tree + /// + public virtual void Insert(KeyValuePair keyValuePair) + { + Insert(keyValuePair.Key, keyValuePair.Value); + } - /// - /// Inserts an array of elements to the tree. - /// - public virtual void Insert(TKey[] collection) - { - if (collection == null) - throw new ArgumentNullException(); + /// + /// Inserts an array of elements to the tree. + /// + public virtual void Insert(TKey[] collection) + { + if (collection == null) + throw new ArgumentNullException(); - if (collection.Length > 0) + if (collection.Length > 0) + { + for (int i = 0; i < collection.Length; ++i) { - for (int i = 0; i < collection.Length; ++i) - { - Insert(collection[i], default); - } + Insert(collection[i], default); } } + } - /// - /// Inserts an array of key-value pairs to the tree. - /// - public virtual void Insert(KeyValuePair[] collection) - { - if (collection == null) - throw new ArgumentNullException(); + /// + /// Inserts an array of key-value pairs to the tree. + /// + public virtual void Insert(KeyValuePair[] collection) + { + if (collection == null) + throw new ArgumentNullException(); - if (collection.Length > 0) + if (collection.Length > 0) + { + for (int i = 0; i < collection.Length; ++i) { - for (int i = 0; i < collection.Length; ++i) - { - Insert(collection[i].Key, collection[i].Value); - } + Insert(collection[i].Key, collection[i].Value); } } + } - /// - /// Inserts a list of elements to the tree. - /// - public virtual void Insert(List collection) - { - if (collection == null) - throw new ArgumentNullException(); + /// + /// Inserts a list of elements to the tree. + /// + public virtual void Insert(List collection) + { + if (collection == null) + throw new ArgumentNullException(); - if (collection.Count > 0) + if (collection.Count > 0) + { + for (int i = 0; i < collection.Count; ++i) { - for (int i = 0; i < collection.Count; ++i) - { - Insert(collection[i], default); - } + Insert(collection[i], default); } } + } - /// - /// Inserts a list of elements to the tree. - /// - public virtual void Insert(List> collection) - { - if (collection == null) - throw new ArgumentNullException(); + /// + /// Inserts a list of elements to the tree. + /// + public virtual void Insert(List> collection) + { + if (collection == null) + throw new ArgumentNullException(); - if (collection.Count > 0) + if (collection.Count > 0) + { + for (int i = 0; i < collection.Count; ++i) { - for (int i = 0; i < collection.Count; ++i) - { - Insert(collection[i].Key, collection[i].Value); - } + Insert(collection[i].Key, collection[i].Value); } } + } - /// - /// Updates the node of a specific key with a new value. - /// - public virtual void Update(TKey key, TValue newValue) - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Updates the node of a specific key with a new value. + /// + public virtual void Update(TKey key, TValue newValue) + { + if (IsEmpty) + throw new Exception("Tree is empty."); - var node = _findNode(Root, key); + var node = _findNode(Root, key); - if (node == null) - throw new KeyNotFoundException("Key doesn't exist in tree."); + if (node == null) + throw new KeyNotFoundException("Key doesn't exist in tree."); - node.Value = newValue; - } + node.Value = newValue; + } - /// - /// Deletes an element from the tree with a specified key. - /// - public virtual void Remove(TKey key) - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Deletes an element from the tree with a specified key. + /// + public virtual void Remove(TKey key) + { + if (IsEmpty) + throw new Exception("Tree is empty."); - var node = _findNode(Root, key); + var node = _findNode(Root, key); - if (node == null) - throw new KeyNotFoundException("Key doesn't exist in tree."); + if (node == null) + throw new KeyNotFoundException("Key doesn't exist in tree."); - _remove(node); - } + _remove(node); + } - /// - /// Removes the min value from tree. - /// - public virtual void RemoveMin() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Removes the min value from tree. + /// + public virtual void RemoveMin() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - var node = _findMinNode(Root); - _remove(node); - } + var node = _findMinNode(Root); + _remove(node); + } - /// - /// Removes the max value from tree. - /// - public virtual void RemoveMax() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Removes the max value from tree. + /// + public virtual void RemoveMax() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - var node = _findMaxNode(Root); - _remove(node); - } + var node = _findMaxNode(Root); + _remove(node); + } - /// - /// Clears all elements from tree. - /// - public virtual void Clear() - { - Root = null; - _count = 0; - } + /// + /// Clears all elements from tree. + /// + public virtual void Clear() + { + Root = null; + _count = 0; + } - /// - /// Checks for the existence of an item - /// - public virtual bool Contains(TKey key) - { - return _findNode(_root, key) != null; - } + /// + /// Checks for the existence of an item + /// + public virtual bool Contains(TKey key) + { + return _findNode(_root, key) != null; + } - /// - /// Finds the minimum in tree - /// - /// Min - public virtual KeyValuePair FindMin() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Finds the minimum in tree + /// + /// Min + public virtual KeyValuePair FindMin() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - var minNode =_findMinNode(Root); - return new KeyValuePair(minNode.Key, minNode.Value); - } + var minNode =_findMinNode(Root); + return new KeyValuePair(minNode.Key, minNode.Value); + } - /// - /// Finds the next smaller element in tree, compared to the specified item. - /// - public virtual KeyValuePair FindNextSmaller(TKey key) - { - var node = _findNode(Root, key); - var nextSmaller = _findNextSmaller(node); + /// + /// Finds the next smaller element in tree, compared to the specified item. + /// + public virtual KeyValuePair FindNextSmaller(TKey key) + { + var node = _findNode(Root, key); + var nextSmaller = _findNextSmaller(node); - if (nextSmaller == null) - throw new Exception("Item was not found."); + if (nextSmaller == null) + throw new Exception("Item was not found."); - return new KeyValuePair(nextSmaller.Key, nextSmaller.Value); - } + return new KeyValuePair(nextSmaller.Key, nextSmaller.Value); + } - /// - /// Finds the next larger element in tree, compared to the specified item. - /// - public virtual KeyValuePair FindNextLarger(TKey item) - { - var node = _findNode(Root, item); - var nextLarger = _findNextLarger(node); + /// + /// Finds the next larger element in tree, compared to the specified item. + /// + public virtual KeyValuePair FindNextLarger(TKey item) + { + var node = _findNode(Root, item); + var nextLarger = _findNextLarger(node); - if (nextLarger == null) - throw new Exception("Item was not found."); + if (nextLarger == null) + throw new Exception("Item was not found."); - return new KeyValuePair(nextLarger.Key, nextLarger.Value); - } + return new KeyValuePair(nextLarger.Key, nextLarger.Value); + } - /// - /// Finds the maximum in tree - /// - /// Max - public virtual KeyValuePair FindMax() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Finds the maximum in tree + /// + /// Max + public virtual KeyValuePair FindMax() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - var maxNode = _findMaxNode(Root); - return new KeyValuePair(maxNode.Key, maxNode.Value); - } + var maxNode = _findMaxNode(Root); + return new KeyValuePair(maxNode.Key, maxNode.Value); + } - /// - /// Find the item in the tree. Throws an exception if not found. - /// - /// Item to find. - /// Item. - public virtual KeyValuePair Find(TKey key) - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Find the item in the tree. Throws an exception if not found. + /// + /// Item to find. + /// Item. + public virtual KeyValuePair Find(TKey key) + { + if (IsEmpty) + throw new Exception("Tree is empty."); - var node = _findNode(Root, key); + var node = _findNode(Root, key); - if (node != null) - return new KeyValuePair(node.Key, node.Value); - throw new KeyNotFoundException("Item was not found."); - } + if (node != null) + return new KeyValuePair(node.Key, node.Value); + throw new KeyNotFoundException("Item was not found."); + } - /// - /// Given a predicate function, find all the elements that match it. - /// - /// The search predicate - /// ArrayList of elements. - public virtual IEnumerable> FindAll(Predicate searchPredicate) - { - var list = new List>(); - _findAll(Root, searchPredicate, ref list); - return list; - } + /// + /// Given a predicate function, find all the elements that match it. + /// + /// The search predicate + /// ArrayList of elements. + public virtual IEnumerable> FindAll(Predicate searchPredicate) + { + var list = new List>(); + _findAll(Root, searchPredicate, ref list); + return list; + } - /// - /// Returns an array of nodes' values. - /// - /// The array. - public virtual KeyValuePair[] ToArray() - { - return ToList().ToArray(); - } + /// + /// Returns an array of nodes' values. + /// + /// The array. + public virtual KeyValuePair[] ToArray() + { + return ToList().ToArray(); + } - /// - /// Returns a list of the nodes' value. - /// - public virtual List> ToList() - { - var list = new List>(); - _inOrderTraverse(Root, ref list); - return list; - } + /// + /// Returns a list of the nodes' value. + /// + public virtual List> ToList() + { + var list = new List>(); + _inOrderTraverse(Root, ref list); + return list; + } - /*********************************************************************/ + /*********************************************************************/ - /// - /// Returns an enumerator that visits node in the order: parent, left child, right child - /// - public virtual IEnumerator> GetPreOrderEnumerator() - { - return new BinarySearchTreePreOrderEnumerator(this); - } + /// + /// Returns an enumerator that visits node in the order: parent, left child, right child + /// + public virtual IEnumerator> GetPreOrderEnumerator() + { + return new BinarySearchTreePreOrderEnumerator(this); + } - /// - /// Returns an enumerator that visits node in the order: left child, parent, right child - /// - public virtual IEnumerator> GetInOrderEnumerator() - { - return new BinarySearchTreeInOrderEnumerator(this); - } + /// + /// Returns an enumerator that visits node in the order: left child, parent, right child + /// + public virtual IEnumerator> GetInOrderEnumerator() + { + return new BinarySearchTreeInOrderEnumerator(this); + } + + /// + /// Returns an enumerator that visits node in the order: left child, right child, parent + /// + public virtual IEnumerator> GetPostOrderEnumerator() + { + return new BinarySearchTreePostOrderEnumerator(this); + } - /// - /// Returns an enumerator that visits node in the order: left child, right child, parent - /// - public virtual IEnumerator> GetPostOrderEnumerator() - { - return new BinarySearchTreePostOrderEnumerator(this); - } + /*********************************************************************/ - /*********************************************************************/ + /// + /// Returns an preorder-traversal enumerator for the tree values + /// + internal class BinarySearchTreePreOrderEnumerator : IEnumerator> + { + private BSTMapNode current; + private BinarySearchTreeMap tree; + internal Queue> traverseQueue; - /// - /// Returns an preorder-traversal enumerator for the tree values - /// - internal class BinarySearchTreePreOrderEnumerator : IEnumerator> + public BinarySearchTreePreOrderEnumerator(BinarySearchTreeMap tree) { - private BSTMapNode current; - private BinarySearchTreeMap tree; - internal Queue> traverseQueue; + this.tree = tree; - public BinarySearchTreePreOrderEnumerator(BinarySearchTreeMap tree) - { - this.tree = tree; + //Build queue + traverseQueue = new Queue>(); + visitNode(this.tree.Root); + } - //Build queue - traverseQueue = new Queue>(); - visitNode(this.tree.Root); - } + private void visitNode(BSTMapNode node) + { + if (node == null) + return; + traverseQueue.Enqueue(node); + visitNode(node.LeftChild); + visitNode(node.RightChild); + } - private void visitNode(BSTMapNode node) - { - if (node == null) - return; - traverseQueue.Enqueue(node); - visitNode(node.LeftChild); - visitNode(node.RightChild); - } + public KeyValuePair Current => new KeyValuePair(current.Key, current.Value); - public KeyValuePair Current => new KeyValuePair(current.Key, current.Value); + object IEnumerator.Current => Current; - object IEnumerator.Current => Current; + public void Dispose() + { + current = null; + tree = null; + } - public void Dispose() - { - current = null; - tree = null; - } + public void Reset() + { + current = null; + } - public void Reset() - { + public bool MoveNext() + { + if (traverseQueue.Count > 0) + current = traverseQueue.Dequeue(); + else current = null; - } - public bool MoveNext() - { - if (traverseQueue.Count > 0) - current = traverseQueue.Dequeue(); - else - current = null; - - return current != null; - } + return current != null; } + } - /// - /// Returns an inorder-traversal enumerator for the tree values - /// - internal class BinarySearchTreeInOrderEnumerator : IEnumerator> + /// + /// Returns an inorder-traversal enumerator for the tree values + /// + internal class BinarySearchTreeInOrderEnumerator : IEnumerator> + { + private BSTMapNode current; + private BinarySearchTreeMap tree; + internal Queue> traverseQueue; + + public BinarySearchTreeInOrderEnumerator(BinarySearchTreeMap tree) { - private BSTMapNode current; - private BinarySearchTreeMap tree; - internal Queue> traverseQueue; + this.tree = tree; - public BinarySearchTreeInOrderEnumerator(BinarySearchTreeMap tree) - { - this.tree = tree; + //Build queue + traverseQueue = new Queue>(); + visitNode(this.tree.Root); + } - //Build queue - traverseQueue = new Queue>(); - visitNode(this.tree.Root); - } + private void visitNode(BSTMapNode node) + { + if (node == null) + return; + visitNode(node.LeftChild); + traverseQueue.Enqueue(node); + visitNode(node.RightChild); + } - private void visitNode(BSTMapNode node) - { - if (node == null) - return; - visitNode(node.LeftChild); - traverseQueue.Enqueue(node); - visitNode(node.RightChild); - } + public KeyValuePair Current => new KeyValuePair(current.Key, current.Value); - public KeyValuePair Current => new KeyValuePair(current.Key, current.Value); + object IEnumerator.Current => Current; - object IEnumerator.Current => Current; + public void Dispose() + { + current = null; + tree = null; + } - public void Dispose() - { - current = null; - tree = null; - } + public void Reset() + { + current = null; + } - public void Reset() - { + public bool MoveNext() + { + if (traverseQueue.Count > 0) + current = traverseQueue.Dequeue(); + else current = null; - } - - public bool MoveNext() - { - if (traverseQueue.Count > 0) - current = traverseQueue.Dequeue(); - else - current = null; - return current != null; - } + return current != null; } + } - /// - /// Returns a postorder-traversal enumerator for the tree values - /// - internal class BinarySearchTreePostOrderEnumerator : IEnumerator> + /// + /// Returns a postorder-traversal enumerator for the tree values + /// + internal class BinarySearchTreePostOrderEnumerator : IEnumerator> + { + private BSTMapNode current; + private BinarySearchTreeMap tree; + internal Queue> traverseQueue; + + public BinarySearchTreePostOrderEnumerator(BinarySearchTreeMap tree) { - private BSTMapNode current; - private BinarySearchTreeMap tree; - internal Queue> traverseQueue; + this.tree = tree; - public BinarySearchTreePostOrderEnumerator(BinarySearchTreeMap tree) - { - this.tree = tree; + //Build queue + traverseQueue = new Queue>(); + visitNode(this.tree.Root); + } - //Build queue - traverseQueue = new Queue>(); - visitNode(this.tree.Root); - } + private void visitNode(BSTMapNode node) + { + if (node == null) + return; + visitNode(node.LeftChild); + visitNode(node.RightChild); + traverseQueue.Enqueue(node); + } - private void visitNode(BSTMapNode node) - { - if (node == null) - return; - visitNode(node.LeftChild); - visitNode(node.RightChild); - traverseQueue.Enqueue(node); - } + public KeyValuePair Current => new KeyValuePair(current.Key, current.Value); - public KeyValuePair Current => new KeyValuePair(current.Key, current.Value); + object IEnumerator.Current => Current; - object IEnumerator.Current => Current; + public void Dispose() + { + current = null; + tree = null; + } - public void Dispose() - { - current = null; - tree = null; - } + public void Reset() + { + current = null; + } - public void Reset() - { + public bool MoveNext() + { + if (traverseQueue.Count > 0) + current = traverseQueue.Dequeue(); + else current = null; - } - - public bool MoveNext() - { - if (traverseQueue.Count > 0) - current = traverseQueue.Dequeue(); - else - current = null; - return current != null; - } + return current != null; } + } - }//end-of-binary-search-tree - -} +}//end-of-binary-search-tree \ No newline at end of file diff --git a/DataStructures/Trees/BinarySearchTreeMapNode.cs b/DataStructures/Trees/BinarySearchTreeMapNode.cs index 147adc23..022771f9 100644 --- a/DataStructures/Trees/BinarySearchTreeMapNode.cs +++ b/DataStructures/Trees/BinarySearchTreeMapNode.cs @@ -1,93 +1,92 @@ using System; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// The Binary Search Tree Map node. +/// +public class BSTMapNode : IComparable> where TKey : IComparable { - /// - /// The Binary Search Tree Map node. - /// - public class BSTMapNode : IComparable> where TKey : IComparable + public BSTMapNode() { } + public BSTMapNode(TKey key) : this(key, default, 0, null, null, null) { } + public BSTMapNode(TKey key, TValue value) : this(key, value, 0, null, null, null) { } + public BSTMapNode(TKey key, TValue value, int subTreeSize, BSTMapNode parent, BSTMapNode left, BSTMapNode right) { - public BSTMapNode() { } - public BSTMapNode(TKey key) : this(key, default, 0, null, null, null) { } - public BSTMapNode(TKey key, TValue value) : this(key, value, 0, null, null, null) { } - public BSTMapNode(TKey key, TValue value, int subTreeSize, BSTMapNode parent, BSTMapNode left, BSTMapNode right) - { - Key = key; - Value = value; - Parent = parent; - LeftChild = left; - RightChild = right; - } + Key = key; + Value = value; + Parent = parent; + LeftChild = left; + RightChild = right; + } - public virtual TKey Key { get; set; } + public virtual TKey Key { get; set; } - public virtual TValue Value { get; set; } + public virtual TValue Value { get; set; } - public virtual BSTMapNode Parent { get; set; } + public virtual BSTMapNode Parent { get; set; } - public virtual BSTMapNode LeftChild { get; set; } + public virtual BSTMapNode LeftChild { get; set; } - public virtual BSTMapNode RightChild { get; set; } + public virtual BSTMapNode RightChild { get; set; } - /// - /// Checks whether this node has any children. - /// - public virtual bool HasChildren => ChildrenCount > 0; + /// + /// Checks whether this node has any children. + /// + public virtual bool HasChildren => ChildrenCount > 0; - /// - /// Checks whether this node has left child. - /// - public virtual bool HasLeftChild => LeftChild != null; + /// + /// Checks whether this node has left child. + /// + public virtual bool HasLeftChild => LeftChild != null; - /// - /// Checks whether this node has right child. - /// - public virtual bool HasRightChild => RightChild != null; + /// + /// Checks whether this node has right child. + /// + public virtual bool HasRightChild => RightChild != null; - /// - /// Checks whether this node is the left child of it's parent. - /// - public virtual bool IsLeftChild => Parent != null && Parent.LeftChild == this; + /// + /// Checks whether this node is the left child of it's parent. + /// + public virtual bool IsLeftChild => Parent != null && Parent.LeftChild == this; - /// - /// Checks whether this node is the left child of it's parent. - /// - public virtual bool IsRightChild => Parent != null && Parent.RightChild == this; + /// + /// Checks whether this node is the left child of it's parent. + /// + public virtual bool IsRightChild => Parent != null && Parent.RightChild == this; - /// - /// Checks whether this node is a leaf node. - /// - public virtual bool IsLeafNode => ChildrenCount == 0; + /// + /// Checks whether this node is a leaf node. + /// + public virtual bool IsLeafNode => ChildrenCount == 0; - /// - /// Returns number of direct descendents: 0, 1, 2 (none, left or right, or both). - /// - /// Number (0,1,2) - public virtual int ChildrenCount + /// + /// Returns number of direct descendents: 0, 1, 2 (none, left or right, or both). + /// + /// Number (0,1,2) + public virtual int ChildrenCount + { + get { - get - { - int count = 0; + int count = 0; - if (HasLeftChild) - count++; + if (HasLeftChild) + count++; - if (HasRightChild) - count++; + if (HasRightChild) + count++; - return count; - } + return count; } + } - /// - /// Compares to. - /// - public virtual int CompareTo(BSTMapNode other) - { - if (other == null) - return -1; + /// + /// Compares to. + /// + public virtual int CompareTo(BSTMapNode other) + { + if (other == null) + return -1; - return Key.CompareTo(other.Key); - } - }//end-of-bstnode -} + return Key.CompareTo(other.Key); + } +}//end-of-bstnode \ No newline at end of file diff --git a/DataStructures/Trees/BinarySearchTreeNode.cs b/DataStructures/Trees/BinarySearchTreeNode.cs index 04a04503..3b7253aa 100644 --- a/DataStructures/Trees/BinarySearchTreeNode.cs +++ b/DataStructures/Trees/BinarySearchTreeNode.cs @@ -1,96 +1,95 @@ -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// The binary search tree node. +/// +public class BSTNode : System.IComparable> where T : System.IComparable { - /// - /// The binary search tree node. - /// - public class BSTNode : System.IComparable> where T : System.IComparable + public BSTNode() : this(default, 0, null, null, null) { } + public BSTNode(T value) : this(value, 0, null, null, null) { } + public BSTNode(T value, int subTreeSize, BSTNode parent, BSTNode left, BSTNode right) { - public BSTNode() : this(default, 0, null, null, null) { } - public BSTNode(T value) : this(value, 0, null, null, null) { } - public BSTNode(T value, int subTreeSize, BSTNode parent, BSTNode left, BSTNode right) - { - Value = value; - Parent = parent; - LeftChild = left; - RightChild = right; - } + Value = value; + Parent = parent; + LeftChild = left; + RightChild = right; + } - public virtual T Value { get; set; } + public virtual T Value { get; set; } - public virtual BSTNode Parent { get; set; } + public virtual BSTNode Parent { get; set; } - public virtual BSTNode LeftChild { get; set; } + public virtual BSTNode LeftChild { get; set; } - public virtual BSTNode RightChild { get; set; } + public virtual BSTNode RightChild { get; set; } - /// - /// Checks whether this node has any children. - /// - public virtual bool HasChildren => ChildrenCount > 0; + /// + /// Checks whether this node has any children. + /// + public virtual bool HasChildren => ChildrenCount > 0; - /// - /// Checks whether this node has left child. - /// - public virtual bool HasLeftChild => LeftChild != null; + /// + /// Checks whether this node has left child. + /// + public virtual bool HasLeftChild => LeftChild != null; - /// - /// Check if this node has only one child and whether it is the right child. - /// - public virtual bool HasOnlyRightChild => !HasLeftChild && HasRightChild; + /// + /// Check if this node has only one child and whether it is the right child. + /// + public virtual bool HasOnlyRightChild => !HasLeftChild && HasRightChild; - /// - /// Checks whether this node has right child. - /// - public virtual bool HasRightChild => RightChild != null; + /// + /// Checks whether this node has right child. + /// + public virtual bool HasRightChild => RightChild != null; - /// - /// Check if this node has only one child and whether it is the left child. - /// - public virtual bool HasOnlyLeftChild => !HasRightChild && HasLeftChild; + /// + /// Check if this node has only one child and whether it is the left child. + /// + public virtual bool HasOnlyLeftChild => !HasRightChild && HasLeftChild; - /// - /// Checks whether this node is the left child of it's parent. - /// - public virtual bool IsLeftChild => Parent != null && Parent.LeftChild == this; + /// + /// Checks whether this node is the left child of it's parent. + /// + public virtual bool IsLeftChild => Parent != null && Parent.LeftChild == this; - /// - /// Checks whether this node is the left child of it's parent. - /// - public virtual bool IsRightChild => Parent != null && Parent.RightChild == this; + /// + /// Checks whether this node is the left child of it's parent. + /// + public virtual bool IsRightChild => Parent != null && Parent.RightChild == this; - /// - /// Checks whether this node is a leaf node. - /// - public virtual bool IsLeafNode => ChildrenCount == 0; + /// + /// Checks whether this node is a leaf node. + /// + public virtual bool IsLeafNode => ChildrenCount == 0; - /// - /// Returns number of direct descendents: 0, 1, 2 (none, left or right, or both). - /// - /// Number (0,1,2) - public virtual int ChildrenCount + /// + /// Returns number of direct descendents: 0, 1, 2 (none, left or right, or both). + /// + /// Number (0,1,2) + public virtual int ChildrenCount + { + get { - get - { - int count = 0; + int count = 0; - if (HasLeftChild) - count++; - if (HasRightChild) - count++; + if (HasLeftChild) + count++; + if (HasRightChild) + count++; - return count; - } + return count; } + } - /// - /// Compares to. - /// - public virtual int CompareTo(BSTNode other) - { - if (other == null) - return -1; + /// + /// Compares to. + /// + public virtual int CompareTo(BSTNode other) + { + if (other == null) + return -1; - return Value.CompareTo(other.Value); - } - }//end-of-bstnode -} + return Value.CompareTo(other.Value); + } +}//end-of-bstnode \ No newline at end of file diff --git a/DataStructures/Trees/IBinarySearchTree.cs b/DataStructures/Trees/IBinarySearchTree.cs index 69fbb103..ba8745c6 100644 --- a/DataStructures/Trees/IBinarySearchTree.cs +++ b/DataStructures/Trees/IBinarySearchTree.cs @@ -1,102 +1,101 @@ using System.Collections.Generic; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +public interface IBinarySearchTree where T : System.IComparable { - public interface IBinarySearchTree where T : System.IComparable - { - // Returns a copy of the tree root - BSTNode Root { get; } - - // Returns the number of elements in the Tree - int Count { get; } - - // Checks if the tree is empty. - bool IsEmpty { get; } - - // Returns the height of the tree. - int Height { get; } - - // Returns true if tree allows inserting duplicates; otherwise, false - bool AllowsDuplicates { get; } - - // Inserts an element to the tree - void Insert(T item); - - // Inserts an array of elements to the tree. - void Insert(T[] collection); - - // Inserts a list of items to the tree. - void Insert(List collection); - - // Removes the min value from tree - void RemoveMin(); - - // Removes the max value from tree - void RemoveMax(); - - // Remove an element from tree - void Remove(T item); - - // Check for the existence of an item - bool Contains(T item); - - // Finds the minimum element. - T FindMin(); - - // Finds the maximum element. - T FindMax(); - - // Find the element in the tree, returns null if not found. - T Find(T item); - - // Finds all the elements in the tree that match the predicate. - IEnumerable FindAll(System.Predicate searchPredicate); - - // Return an array of the tree elements - T[] ToArray(); - - // Return an array of the tree elements - List ToList(); - - // Returns an enumerator that visits node in the order: parent, left child, right child - IEnumerator GetPreOrderEnumerator(); - - // Returns an enumerator that visits node in the order: left child, parent, right child - IEnumerator GetInOrderEnumerator(); - - // Returns an enumerator that visits node in the order: left child, right child, parent - IEnumerator GetPostOrderEnumerator(); - - // Clear this tree. - void Clear(); - } - - /// - /// The itemed version of the Binary Search Tree. - /// - /// Type of items. - /// Type of records per node. - public interface IBinarySearchTree where TKey : System.IComparable - { - BSTMapNode Root { get; } - int Count { get; } - bool IsEmpty { get; } - int Height { get; } - bool AllowsDuplicates { get; } - void Insert(TKey key, TValue value); - void Insert(KeyValuePair keyValuePair); - void Insert(KeyValuePair[] collection); - void Insert(List> collection); - void RemoveMin(); - void RemoveMax(); - void Remove(TKey item); - bool Contains(TKey item); - KeyValuePair FindMin(); - KeyValuePair FindMax(); - KeyValuePair Find(TKey item); - IEnumerable> FindAll(System.Predicate searchPredicate); - KeyValuePair[] ToArray(); - List> ToList(); - void Clear(); - } + // Returns a copy of the tree root + BSTNode Root { get; } + + // Returns the number of elements in the Tree + int Count { get; } + + // Checks if the tree is empty. + bool IsEmpty { get; } + + // Returns the height of the tree. + int Height { get; } + + // Returns true if tree allows inserting duplicates; otherwise, false + bool AllowsDuplicates { get; } + + // Inserts an element to the tree + void Insert(T item); + + // Inserts an array of elements to the tree. + void Insert(T[] collection); + + // Inserts a list of items to the tree. + void Insert(List collection); + + // Removes the min value from tree + void RemoveMin(); + + // Removes the max value from tree + void RemoveMax(); + + // Remove an element from tree + void Remove(T item); + + // Check for the existence of an item + bool Contains(T item); + + // Finds the minimum element. + T FindMin(); + + // Finds the maximum element. + T FindMax(); + + // Find the element in the tree, returns null if not found. + T Find(T item); + + // Finds all the elements in the tree that match the predicate. + IEnumerable FindAll(System.Predicate searchPredicate); + + // Return an array of the tree elements + T[] ToArray(); + + // Return an array of the tree elements + List ToList(); + + // Returns an enumerator that visits node in the order: parent, left child, right child + IEnumerator GetPreOrderEnumerator(); + + // Returns an enumerator that visits node in the order: left child, parent, right child + IEnumerator GetInOrderEnumerator(); + + // Returns an enumerator that visits node in the order: left child, right child, parent + IEnumerator GetPostOrderEnumerator(); + + // Clear this tree. + void Clear(); } + +/// +/// The itemed version of the Binary Search Tree. +/// +/// Type of items. +/// Type of records per node. +public interface IBinarySearchTree where TKey : System.IComparable +{ + BSTMapNode Root { get; } + int Count { get; } + bool IsEmpty { get; } + int Height { get; } + bool AllowsDuplicates { get; } + void Insert(TKey key, TValue value); + void Insert(KeyValuePair keyValuePair); + void Insert(KeyValuePair[] collection); + void Insert(List> collection); + void RemoveMin(); + void RemoveMax(); + void Remove(TKey item); + bool Contains(TKey item); + KeyValuePair FindMin(); + KeyValuePair FindMax(); + KeyValuePair Find(TKey item); + IEnumerable> FindAll(System.Predicate searchPredicate); + KeyValuePair[] ToArray(); + List> ToList(); + void Clear(); +} \ No newline at end of file diff --git a/DataStructures/Trees/RedBlackTree.cs b/DataStructures/Trees/RedBlackTree.cs index f415fcf9..188fb29a 100644 --- a/DataStructures/Trees/RedBlackTree.cs +++ b/DataStructures/Trees/RedBlackTree.cs @@ -2,663 +2,662 @@ using System; using System.Collections.Generic; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// THE NODE COLORS TYPE +/// +public enum RedBlackTreeColors +{ + Red = 0, + Black = 1 +}; + +/// +/// Red-Black Tree Data Structure. +/// +public class RedBlackTree : BinarySearchTree where TKey : IComparable { /// - /// THE NODE COLORS TYPE + /// Root node accessors overriding /// - public enum RedBlackTreeColors + public new RedBlackTreeNode Root { - Red = 0, - Black = 1 - }; + get => (RedBlackTreeNode)base.Root; + internal set => base.Root = value; + } - /// - /// Red-Black Tree Data Structure. - /// - public class RedBlackTree : BinarySearchTree where TKey : IComparable + private bool IsRoot(RedBlackTreeNode node) { - /// - /// Root node accessors overriding - /// - public new RedBlackTreeNode Root - { - get => (RedBlackTreeNode)base.Root; - internal set => base.Root = value; - } - - private bool IsRoot(RedBlackTreeNode node) - { - return node == Root; - } + return node == Root; + } - /// - /// CONSTRUCTOR. - /// Allows duplicates by default. - /// - public RedBlackTree() : base() { } + /// + /// CONSTRUCTOR. + /// Allows duplicates by default. + /// + public RedBlackTree() : base() { } - /// - /// CONSTRUCTOR. - /// If allowDuplictes is set to false, no duplicate items will be inserted. - /// - public RedBlackTree(bool allowDuplicates) : base(allowDuplicates) { } + /// + /// CONSTRUCTOR. + /// If allowDuplictes is set to false, no duplicate items will be inserted. + /// + public RedBlackTree(bool allowDuplicates) : base(allowDuplicates) { } - /*************************************************************************************************/ - /*** - * Safety Checks/Getters/Setters. - * - * The following are helper methods for safely checking, getting and updating possibly-null objects. - * These helpers make the algorithms of adjusting the tree after insertion and removal more readable. - */ + /*************************************************************************************************/ + /*** + * Safety Checks/Getters/Setters. + * + * The following are helper methods for safely checking, getting and updating possibly-null objects. + * These helpers make the algorithms of adjusting the tree after insertion and removal more readable. + */ - protected RedBlackTreeNode _safeGetGrandParent(RedBlackTreeNode node) - { - if (node == null || node.Parent == null) - return null; + protected RedBlackTreeNode _safeGetGrandParent(RedBlackTreeNode node) + { + if (node == null || node.Parent == null) + return null; - return node.GrandParent; - } + return node.GrandParent; + } - protected RedBlackTreeNode _safeGetParent(RedBlackTreeNode node) - { - if (node == null || node.Parent == null) - return null; + protected RedBlackTreeNode _safeGetParent(RedBlackTreeNode node) + { + if (node == null || node.Parent == null) + return null; - return node.Parent; - } + return node.Parent; + } - protected RedBlackTreeNode _safeGetSibling(RedBlackTreeNode node) - { - if (node == null || node.Parent == null) - return null; + protected RedBlackTreeNode _safeGetSibling(RedBlackTreeNode node) + { + if (node == null || node.Parent == null) + return null; - return node.Sibling; - } + return node.Sibling; + } - protected RedBlackTreeNode _safeGetLeftChild(RedBlackTreeNode node) - { - if (node == null) - return null; + protected RedBlackTreeNode _safeGetLeftChild(RedBlackTreeNode node) + { + if (node == null) + return null; - return node.LeftChild; - } + return node.LeftChild; + } - protected RedBlackTreeNode _safeGetRightChild(RedBlackTreeNode node) - { - if (node == null) - return null; + protected RedBlackTreeNode _safeGetRightChild(RedBlackTreeNode node) + { + if (node == null) + return null; - return node.RightChild; - } + return node.RightChild; + } - protected virtual RedBlackTreeColors _safeGetColor(RedBlackTreeNode node) - { - if (node == null) - return RedBlackTreeColors.Black; + protected virtual RedBlackTreeColors _safeGetColor(RedBlackTreeNode node) + { + if (node == null) + return RedBlackTreeColors.Black; - return node.Color; - } + return node.Color; + } - protected virtual void _safeUpdateColor(RedBlackTreeNode node, RedBlackTreeColors color) - { - if (node == null) - return; + protected virtual void _safeUpdateColor(RedBlackTreeNode node, RedBlackTreeColors color) + { + if (node == null) + return; - node.Color = color; - } + node.Color = color; + } - protected virtual bool _safeCheckIsBlack(RedBlackTreeNode node) - { - return node == null || (node != null && node.IsBlack); - } + protected virtual bool _safeCheckIsBlack(RedBlackTreeNode node) + { + return node == null || (node != null && node.IsBlack); + } - protected virtual bool _safeCheckIsRed(RedBlackTreeNode node) - { - return node != null && node.IsRed; - } + protected virtual bool _safeCheckIsRed(RedBlackTreeNode node) + { + return node != null && node.IsRed; + } - /*************************************************************************************************/ - /*** - * Tree Rotations and Adjustements. - * - * The following are methods for rotating the tree (left/right) and for adjusting the - * ... tree after inserting or removing nodes. - */ + /*************************************************************************************************/ + /*** + * Tree Rotations and Adjustements. + * + * The following are methods for rotating the tree (left/right) and for adjusting the + * ... tree after inserting or removing nodes. + */ - /// - /// Rotates a node to the left in the Red-Black Tree. - /// - protected virtual void _rotateLeftAt(RedBlackTreeNode currentNode) - { - // We check the right child because it's going to be a pivot node for the rotation - if (currentNode == null || currentNode.HasRightChild == false) - return; + /// + /// Rotates a node to the left in the Red-Black Tree. + /// + protected virtual void _rotateLeftAt(RedBlackTreeNode currentNode) + { + // We check the right child because it's going to be a pivot node for the rotation + if (currentNode == null || currentNode.HasRightChild == false) + return; - // Pivot on *right* child - RedBlackTreeNode pivotNode = currentNode.RightChild; + // Pivot on *right* child + RedBlackTreeNode pivotNode = currentNode.RightChild; - // Parent of currentNode - RedBlackTreeNode parent = currentNode.Parent; + // Parent of currentNode + RedBlackTreeNode parent = currentNode.Parent; - // Check if currentNode is it's parent's left child. - bool isLeftChild = currentNode.IsLeftChild; + // Check if currentNode is it's parent's left child. + bool isLeftChild = currentNode.IsLeftChild; - // Check if currentNode is the Root - bool isRootNode = currentNode == Root; + // Check if currentNode is the Root + bool isRootNode = currentNode == Root; - // Perform the rotation - currentNode.RightChild = pivotNode.LeftChild; - pivotNode.LeftChild = currentNode; + // Perform the rotation + currentNode.RightChild = pivotNode.LeftChild; + pivotNode.LeftChild = currentNode; - // Update parents references - currentNode.Parent = pivotNode; - pivotNode.Parent = parent; + // Update parents references + currentNode.Parent = pivotNode; + pivotNode.Parent = parent; - if (currentNode.HasRightChild) - currentNode.RightChild.Parent = currentNode; + if (currentNode.HasRightChild) + currentNode.RightChild.Parent = currentNode; - //Update the entire tree's Root if necessary - if (isRootNode) - Root = pivotNode; + //Update the entire tree's Root if necessary + if (isRootNode) + Root = pivotNode; - // Update the original parent's child node - if (isLeftChild) - parent.LeftChild = pivotNode; - else if (parent != null) - parent.RightChild = pivotNode; - } + // Update the original parent's child node + if (isLeftChild) + parent.LeftChild = pivotNode; + else if (parent != null) + parent.RightChild = pivotNode; + } - /// - /// Rotates a node to the right in the Red-Black Tree. - /// - protected virtual void _rotateRightAt(RedBlackTreeNode currentNode) - { - // We check the right child because it's going to be a pivot node for the rotation - if (currentNode == null || currentNode.HasLeftChild == false) - return; + /// + /// Rotates a node to the right in the Red-Black Tree. + /// + protected virtual void _rotateRightAt(RedBlackTreeNode currentNode) + { + // We check the right child because it's going to be a pivot node for the rotation + if (currentNode == null || currentNode.HasLeftChild == false) + return; - // Pivot on *left* child - var pivotNode = currentNode.LeftChild; + // Pivot on *left* child + var pivotNode = currentNode.LeftChild; - // Parent of currentNode - var parent = currentNode.Parent; + // Parent of currentNode + var parent = currentNode.Parent; - // Check if currentNode is it's parent's left child. - bool isLeftChild = currentNode.IsLeftChild; + // Check if currentNode is it's parent's left child. + bool isLeftChild = currentNode.IsLeftChild; - // Check if currentNode is the Root - bool isRootNode = currentNode == Root; + // Check if currentNode is the Root + bool isRootNode = currentNode == Root; - // Perform the rotation - currentNode.LeftChild = pivotNode.RightChild; - pivotNode.RightChild = currentNode; + // Perform the rotation + currentNode.LeftChild = pivotNode.RightChild; + pivotNode.RightChild = currentNode; - // Update parents references - currentNode.Parent = pivotNode; - pivotNode.Parent = parent; + // Update parents references + currentNode.Parent = pivotNode; + pivotNode.Parent = parent; - if (currentNode.HasLeftChild) - currentNode.LeftChild.Parent = currentNode; + if (currentNode.HasLeftChild) + currentNode.LeftChild.Parent = currentNode; - // Update the entire tree's Root if necessary - if (isRootNode) - Root = pivotNode; + // Update the entire tree's Root if necessary + if (isRootNode) + Root = pivotNode; - // Update the original parent's child node - if (isLeftChild) - parent.LeftChild = pivotNode; - else if (parent != null) - parent.RightChild = pivotNode; - } + // Update the original parent's child node + if (isLeftChild) + parent.LeftChild = pivotNode; + else if (parent != null) + parent.RightChild = pivotNode; + } - /// - /// After insertion tree-adjustement helper. - /// - protected virtual void _adjustTreeAfterInsertion(RedBlackTreeNode currentNode) + /// + /// After insertion tree-adjustement helper. + /// + protected virtual void _adjustTreeAfterInsertion(RedBlackTreeNode currentNode) + { + // + // STEP 1: + // Color the currentNode as red + _safeUpdateColor(currentNode, RedBlackTreeColors.Red); + + // + // STEP 2: + // Fix the double red-consecutive-nodes problems, if there exists any. + if (currentNode != null && currentNode != Root && _safeCheckIsRed(_safeGetParent(currentNode))) { // - // STEP 1: - // Color the currentNode as red - _safeUpdateColor(currentNode, RedBlackTreeColors.Red); - - // - // STEP 2: - // Fix the double red-consecutive-nodes problems, if there exists any. - if (currentNode != null && currentNode != Root && _safeCheckIsRed(_safeGetParent(currentNode))) + // STEP 2.A: + // This is the simplest step: Basically recolor, and bubble up to see if more work is needed. + if (_safeCheckIsRed(_safeGetSibling(currentNode.Parent))) { - // - // STEP 2.A: - // This is the simplest step: Basically recolor, and bubble up to see if more work is needed. - if (_safeCheckIsRed(_safeGetSibling(currentNode.Parent))) - { - // If it has a sibling and it is black, then then it has a parent - currentNode.Parent.Color = RedBlackTreeColors.Black; + // If it has a sibling and it is black, then then it has a parent + currentNode.Parent.Color = RedBlackTreeColors.Black; - // Color sibling of parent as black - _safeUpdateColor(_safeGetSibling(currentNode.Parent), RedBlackTreeColors.Black); + // Color sibling of parent as black + _safeUpdateColor(_safeGetSibling(currentNode.Parent), RedBlackTreeColors.Black); - // Color grandparent as red - _safeUpdateColor(_safeGetGrandParent(currentNode), RedBlackTreeColors.Red); + // Color grandparent as red + _safeUpdateColor(_safeGetGrandParent(currentNode), RedBlackTreeColors.Red); - // Adjust on the grandparent of currentNode - _adjustTreeAfterInsertion(_safeGetGrandParent(currentNode)); - } + // Adjust on the grandparent of currentNode + _adjustTreeAfterInsertion(_safeGetGrandParent(currentNode)); + } - // - // STEP 2.B: - // Restructure the tree if the parent of currentNode is a left child to the grandparent of currentNode - // (parent is a left child to its own parent). - // If currentNode is also a left child, then do a single right rotation; otherwise, a left-right rotation. - // - // using the safe methods to check: currentNode.Parent.IsLeftChild == true - else if (_safeGetParent(currentNode) == _safeGetLeftChild(_safeGetGrandParent(currentNode))) + // + // STEP 2.B: + // Restructure the tree if the parent of currentNode is a left child to the grandparent of currentNode + // (parent is a left child to its own parent). + // If currentNode is also a left child, then do a single right rotation; otherwise, a left-right rotation. + // + // using the safe methods to check: currentNode.Parent.IsLeftChild == true + else if (_safeGetParent(currentNode) == _safeGetLeftChild(_safeGetGrandParent(currentNode))) + { + if (currentNode.IsRightChild) { - if (currentNode.IsRightChild) - { - currentNode = _safeGetParent(currentNode); - _rotateLeftAt(currentNode); - } + currentNode = _safeGetParent(currentNode); + _rotateLeftAt(currentNode); + } - // Color parent as black - _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); + // Color parent as black + _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); - // Color grandparent as red - _safeUpdateColor(_safeGetGrandParent(currentNode), RedBlackTreeColors.Red); + // Color grandparent as red + _safeUpdateColor(_safeGetGrandParent(currentNode), RedBlackTreeColors.Red); - // Right Rotate tree around the currentNode's grand parent - _rotateRightAt(_safeGetGrandParent(currentNode)); - } + // Right Rotate tree around the currentNode's grand parent + _rotateRightAt(_safeGetGrandParent(currentNode)); + } - // - // STEP 2.C: - // Restructure the tree if the parent of currentNode is a right child to the grandparent of currentNode - // (parent is a right child to its own parent). - // If currentNode is a right-child in it's parent, then do a single left rotation; otherwise a right-left rotation. - // - // using the safe methods to check: currentNode.Parent.IsRightChild == true - else if (_safeGetParent(currentNode) == _safeGetRightChild(_safeGetGrandParent(currentNode))) + // + // STEP 2.C: + // Restructure the tree if the parent of currentNode is a right child to the grandparent of currentNode + // (parent is a right child to its own parent). + // If currentNode is a right-child in it's parent, then do a single left rotation; otherwise a right-left rotation. + // + // using the safe methods to check: currentNode.Parent.IsRightChild == true + else if (_safeGetParent(currentNode) == _safeGetRightChild(_safeGetGrandParent(currentNode))) + { + if (currentNode.IsLeftChild) { - if (currentNode.IsLeftChild) - { - currentNode = _safeGetParent(currentNode); - _rotateRightAt(currentNode); - } + currentNode = _safeGetParent(currentNode); + _rotateRightAt(currentNode); + } - // Color parent as black - _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); + // Color parent as black + _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); - // Color grandparent as red - _safeUpdateColor(_safeGetGrandParent(currentNode), RedBlackTreeColors.Red); + // Color grandparent as red + _safeUpdateColor(_safeGetGrandParent(currentNode), RedBlackTreeColors.Red); - // Left Rotate tree around the currentNode's grand parent - _rotateLeftAt(_safeGetGrandParent(currentNode)); - } + // Left Rotate tree around the currentNode's grand parent + _rotateLeftAt(_safeGetGrandParent(currentNode)); } - - // STEP 3: - // Color the root node as black - _safeUpdateColor(Root, RedBlackTreeColors.Black); } - /// - /// After removal tree-adjustement helper. - /// - protected virtual void _adjustTreeAfterRemoval(RedBlackTreeNode currentNode) + // STEP 3: + // Color the root node as black + _safeUpdateColor(Root, RedBlackTreeColors.Black); + } + + /// + /// After removal tree-adjustement helper. + /// + protected virtual void _adjustTreeAfterRemoval(RedBlackTreeNode currentNode) + { + while (currentNode != null && currentNode != Root && currentNode.IsBlack) { - while (currentNode != null && currentNode != Root && currentNode.IsBlack) + if (currentNode.IsLeftChild) { - if (currentNode.IsLeftChild) + // Get sibling of currentNode + // Safe equivalent of currentNode.Sibling or currentNode.Parent.RightChild + var sibling = _safeGetRightChild(_safeGetParent(currentNode)); + + // Safely check sibling.IsRed property + if (_safeCheckIsRed(sibling)) + { + // Color currentNode.Sibling as black + _safeUpdateColor(sibling, RedBlackTreeColors.Black); + + // Color currentNode.Parent as red + _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Red); + + // Left Rotate on currentNode's parent + _rotateLeftAt(_safeGetParent(currentNode)); + + // Update sibling reference + // Might end be being set to null + sibling = _safeGetRightChild(_safeGetParent(currentNode)); + } + + // Check if the left and right children of the sibling node are black + // Use the safe methods to check for: (sibling.LeftChild.IsBlack && sibling.RightChild.IsBlack) + if (_safeCheckIsBlack(_safeGetLeftChild(sibling)) && _safeCheckIsBlack(_safeGetRightChild(sibling))) { - // Get sibling of currentNode - // Safe equivalent of currentNode.Sibling or currentNode.Parent.RightChild - var sibling = _safeGetRightChild(_safeGetParent(currentNode)); + // Color currentNode.Sibling as red + _safeUpdateColor(sibling, RedBlackTreeColors.Red); - // Safely check sibling.IsRed property - if (_safeCheckIsRed(sibling)) + // Assign currentNode.Parent to currentNode + currentNode = _safeGetParent(currentNode); + } + else + { + if (_safeCheckIsBlack(_safeGetRightChild(sibling))) { - // Color currentNode.Sibling as black - _safeUpdateColor(sibling, RedBlackTreeColors.Black); + // Color currentNode.Sibling.LeftChild as black + _safeUpdateColor(_safeGetLeftChild(sibling), RedBlackTreeColors.Black); - // Color currentNode.Parent as red - _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Red); + // Color currentNode.Sibling as red + _safeUpdateColor(sibling, RedBlackTreeColors.Red); - // Left Rotate on currentNode's parent - _rotateLeftAt(_safeGetParent(currentNode)); + // Right Rotate on sibling + _rotateRightAt(sibling); // Update sibling reference // Might end be being set to null sibling = _safeGetRightChild(_safeGetParent(currentNode)); } - // Check if the left and right children of the sibling node are black - // Use the safe methods to check for: (sibling.LeftChild.IsBlack && sibling.RightChild.IsBlack) - if (_safeCheckIsBlack(_safeGetLeftChild(sibling)) && _safeCheckIsBlack(_safeGetRightChild(sibling))) - { - // Color currentNode.Sibling as red - _safeUpdateColor(sibling, RedBlackTreeColors.Red); + // Color the Sibling node as currentNode.Parent.Color + _safeUpdateColor(sibling, _safeGetColor(_safeGetParent(currentNode))); - // Assign currentNode.Parent to currentNode - currentNode = _safeGetParent(currentNode); - } - else - { - if (_safeCheckIsBlack(_safeGetRightChild(sibling))) - { - // Color currentNode.Sibling.LeftChild as black - _safeUpdateColor(_safeGetLeftChild(sibling), RedBlackTreeColors.Black); + // Color currentNode.Parent as black + _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); + + // Color Sibling.RightChild as black + _safeUpdateColor(_safeGetRightChild(sibling), RedBlackTreeColors.Black); - // Color currentNode.Sibling as red - _safeUpdateColor(sibling, RedBlackTreeColors.Red); + // Rotate on currentNode's parent + _rotateLeftAt(_safeGetParent(currentNode)); - // Right Rotate on sibling - _rotateRightAt(sibling); + currentNode = Root; + } + } + else + { + // Get sibling of currentNode + // Safe equivalent of currentNode.Sibling or currentNode.Parent.LeftChild + var sibling = _safeGetLeftChild(_safeGetParent(currentNode)); - // Update sibling reference - // Might end be being set to null - sibling = _safeGetRightChild(_safeGetParent(currentNode)); - } + if (_safeCheckIsRed(sibling)) + { + // Color currentNode.Sibling as black + _safeUpdateColor(sibling, RedBlackTreeColors.Black); - // Color the Sibling node as currentNode.Parent.Color - _safeUpdateColor(sibling, _safeGetColor(_safeGetParent(currentNode))); + // Color currentNode.Parent as red + _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Red); - // Color currentNode.Parent as black - _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); + // Right Rotate tree around the parent of currentNode + _rotateRightAt(_safeGetParent(currentNode)); - // Color Sibling.RightChild as black - _safeUpdateColor(_safeGetRightChild(sibling), RedBlackTreeColors.Black); + // Update sibling reference + // Might end be being set to null + sibling = _safeGetLeftChild(_safeGetParent(currentNode)); + } - // Rotate on currentNode's parent - _rotateLeftAt(_safeGetParent(currentNode)); + // Check if the left and right children of the sibling node are black + // Use the safe methods to check for: (sibling.LeftChild.IsBlack && sibling.RightChild.IsBlack) + if (_safeCheckIsBlack(_safeGetLeftChild(sibling)) && _safeCheckIsBlack(_safeGetRightChild(sibling))) + { + _safeUpdateColor(sibling, RedBlackTreeColors.Red); - currentNode = Root; - } + // Assign currentNode.Parent to currentNode + currentNode = _safeGetParent(currentNode); } else { - // Get sibling of currentNode - // Safe equivalent of currentNode.Sibling or currentNode.Parent.LeftChild - var sibling = _safeGetLeftChild(_safeGetParent(currentNode)); - - if (_safeCheckIsRed(sibling)) + // Check if sibling.LeftChild.IsBlack == true + if (_safeCheckIsBlack(_safeGetLeftChild(sibling))) { - // Color currentNode.Sibling as black - _safeUpdateColor(sibling, RedBlackTreeColors.Black); + // Color currentNode.Sibling.RightChild as black + _safeUpdateColor(_safeGetRightChild(sibling), RedBlackTreeColors.Black); - // Color currentNode.Parent as red - _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Red); + // Color currentNode.Sibling as red + _safeUpdateColor(sibling, RedBlackTreeColors.Red); - // Right Rotate tree around the parent of currentNode - _rotateRightAt(_safeGetParent(currentNode)); + // Left rotate on sibling + _rotateLeftAt(sibling); // Update sibling reference // Might end be being set to null sibling = _safeGetLeftChild(_safeGetParent(currentNode)); } - // Check if the left and right children of the sibling node are black - // Use the safe methods to check for: (sibling.LeftChild.IsBlack && sibling.RightChild.IsBlack) - if (_safeCheckIsBlack(_safeGetLeftChild(sibling)) && _safeCheckIsBlack(_safeGetRightChild(sibling))) - { - _safeUpdateColor(sibling, RedBlackTreeColors.Red); - - // Assign currentNode.Parent to currentNode - currentNode = _safeGetParent(currentNode); - } - else - { - // Check if sibling.LeftChild.IsBlack == true - if (_safeCheckIsBlack(_safeGetLeftChild(sibling))) - { - // Color currentNode.Sibling.RightChild as black - _safeUpdateColor(_safeGetRightChild(sibling), RedBlackTreeColors.Black); - - // Color currentNode.Sibling as red - _safeUpdateColor(sibling, RedBlackTreeColors.Red); - - // Left rotate on sibling - _rotateLeftAt(sibling); + // Color the Sibling node as currentNode.Parent.Color + _safeUpdateColor(sibling, _safeGetColor(_safeGetParent(currentNode))); - // Update sibling reference - // Might end be being set to null - sibling = _safeGetLeftChild(_safeGetParent(currentNode)); - } - - // Color the Sibling node as currentNode.Parent.Color - _safeUpdateColor(sibling, _safeGetColor(_safeGetParent(currentNode))); - - // Color currentNode.Parent as black - _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); + // Color currentNode.Parent as black + _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); - // Color Sibling.RightChild as black - _safeUpdateColor(_safeGetLeftChild(sibling), RedBlackTreeColors.Black); + // Color Sibling.RightChild as black + _safeUpdateColor(_safeGetLeftChild(sibling), RedBlackTreeColors.Black); - // Right rotate on the parent of currentNode - _rotateRightAt(_safeGetParent(currentNode)); + // Right rotate on the parent of currentNode + _rotateRightAt(_safeGetParent(currentNode)); - currentNode = Root; - } + currentNode = Root; } } - - // Color currentNode as black - _safeUpdateColor(currentNode, RedBlackTreeColors.Black); } - /// - /// Remove node helpers. - /// - protected override bool _remove(BSTNode nodeToDelete) + // Color currentNode as black + _safeUpdateColor(currentNode, RedBlackTreeColors.Black); + } + + /// + /// Remove node helpers. + /// + protected override bool _remove(BSTNode nodeToDelete) + { + return _remove((RedBlackTreeNode)nodeToDelete); + } + + /// + /// The internal remove helper. + /// Separated from the overriden version to avoid casting the objects from BSTNode to RedBlackTreeNode. + /// This is called from the overriden _remove(BSTNode nodeToDelete) helper. + /// + protected bool _remove(RedBlackTreeNode nodeToDelete) + { + if (nodeToDelete == null) { - return _remove((RedBlackTreeNode)nodeToDelete); + return false; } - /// - /// The internal remove helper. - /// Separated from the overriden version to avoid casting the objects from BSTNode to RedBlackTreeNode. - /// This is called from the overriden _remove(BSTNode nodeToDelete) helper. - /// - protected bool _remove(RedBlackTreeNode nodeToDelete) + if (IsRoot(nodeToDelete) && !nodeToDelete.HasChildren) + { + Root = null; + } + else { - if (nodeToDelete == null) + // X is the node we will replace with the nodeToDelete in the tree once we remove it. + RedBlackTreeNode x; + + if (!nodeToDelete.HasChildren) { - return false; + x = nodeToDelete; + Transplant(nodeToDelete, null); } - - if (IsRoot(nodeToDelete) && !nodeToDelete.HasChildren) + else if (nodeToDelete.HasOnlyRightChild) + { + x = nodeToDelete.RightChild; + Transplant(nodeToDelete, nodeToDelete.RightChild); + } + else if (nodeToDelete.HasOnlyLeftChild) { - Root = null; + x = nodeToDelete.LeftChild; + Transplant(nodeToDelete, nodeToDelete.LeftChild); } else { - // X is the node we will replace with the nodeToDelete in the tree once we remove it. - RedBlackTreeNode x; + // Y is the node we will replace with the X in the tree once we move it to the nodeToDelete position. + var y = (RedBlackTreeNode)_findMinNode(nodeToDelete.RightChild); + x = y.RightChild; - if (!nodeToDelete.HasChildren) - { - x = nodeToDelete; - Transplant(nodeToDelete, null); - } - else if (nodeToDelete.HasOnlyRightChild) - { - x = nodeToDelete.RightChild; - Transplant(nodeToDelete, nodeToDelete.RightChild); - } - else if (nodeToDelete.HasOnlyLeftChild) + if (y.Parent == nodeToDelete) { - x = nodeToDelete.LeftChild; - Transplant(nodeToDelete, nodeToDelete.LeftChild); + if (x != null) + { + x.Parent = y; + } } else { - // Y is the node we will replace with the X in the tree once we move it to the nodeToDelete position. - var y = (RedBlackTreeNode)_findMinNode(nodeToDelete.RightChild); - x = y.RightChild; - - if (y.Parent == nodeToDelete) - { - if (x != null) - { - x.Parent = y; - } - } - else - { - Transplant(y, y.RightChild); - y.RightChild = nodeToDelete.RightChild; - y.RightChild.Parent = y; - } - - Transplant(nodeToDelete, y); - y.LeftChild = nodeToDelete.LeftChild; - y.LeftChild.Parent = y; - y.Color = nodeToDelete.Color; - - if (Root == nodeToDelete) - { - Root = y; - Root.Parent = null; - } + Transplant(y, y.RightChild); + y.RightChild = nodeToDelete.RightChild; + y.RightChild.Parent = y; } - if (nodeToDelete.Color == RedBlackTreeColors.Black) + Transplant(nodeToDelete, y); + y.LeftChild = nodeToDelete.LeftChild; + y.LeftChild.Parent = y; + y.Color = nodeToDelete.Color; + + if (Root == nodeToDelete) { - _adjustTreeAfterRemoval(x); + Root = y; + Root.Parent = null; } } - _count--; - - return true; + if (nodeToDelete.Color == RedBlackTreeColors.Black) + { + _adjustTreeAfterRemoval(x); + } } - /// - /// Insert one subtree in the place of the other in his parent. - /// - /// Subtree of node will be replaced by . - /// Subtree replaces . - private void Transplant(RedBlackTreeNode replaced, RedBlackTreeNode replacement) + _count--; + + return true; + } + + /// + /// Insert one subtree in the place of the other in his parent. + /// + /// Subtree of node will be replaced by . + /// Subtree replaces . + private void Transplant(RedBlackTreeNode replaced, RedBlackTreeNode replacement) + { + if (replaced.Parent == null) { - if (replaced.Parent == null) - { - Root = replacement; - } - else if (replaced == replaced.Parent.LeftChild) - { - replaced.Parent.LeftChild = replacement; - } - else - { - replaced.Parent.RightChild = replacement; - } + Root = replacement; + } + else if (replaced == replaced.Parent.LeftChild) + { + replaced.Parent.LeftChild = replacement; + } + else + { + replaced.Parent.RightChild = replacement; + } - if (replacement != null) - { - replacement.Parent = replaced.Parent; - } + if (replacement != null) + { + replacement.Parent = replaced.Parent; } - /*************************************************************************************************/ + } + /*************************************************************************************************/ - /// - /// Insert data item to tree - /// - public override void Insert(TKey item) - { - var newNode = new RedBlackTreeNode(item); + /// + /// Insert data item to tree + /// + public override void Insert(TKey item) + { + var newNode = new RedBlackTreeNode(item); - // Invoke the super BST insert node method. - // This insert node recursively starting from the root and checks for success status (related to allowDuplicates flag). - // The functions increments count on its own. - var success = base._insertNode(newNode); + // Invoke the super BST insert node method. + // This insert node recursively starting from the root and checks for success status (related to allowDuplicates flag). + // The functions increments count on its own. + var success = base._insertNode(newNode); - if (success == false && _allowDuplicates == false) - throw new InvalidOperationException("Tree does not allow inserting duplicate elements."); + if (success == false && _allowDuplicates == false) + throw new InvalidOperationException("Tree does not allow inserting duplicate elements."); - // Adjust Red-Black Tree rules - if (!newNode.IsEqualTo(Root)) - if (newNode.Parent.Color != RedBlackTreeColors.Black) // Case 0: Parent is not black and we have to restructure tree - _adjustTreeAfterInsertion(newNode); + // Adjust Red-Black Tree rules + if (!newNode.IsEqualTo(Root)) + if (newNode.Parent.Color != RedBlackTreeColors.Black) // Case 0: Parent is not black and we have to restructure tree + _adjustTreeAfterInsertion(newNode); - // Always color root as black - Root.Color = RedBlackTreeColors.Black; - } + // Always color root as black + Root.Color = RedBlackTreeColors.Black; + } - /// - /// Inserts an array of elements to the tree. - /// - public override void Insert(TKey[] collection) - { - if (collection == null) - throw new ArgumentNullException(); + /// + /// Inserts an array of elements to the tree. + /// + public override void Insert(TKey[] collection) + { + if (collection == null) + throw new ArgumentNullException(); - if (collection.Length > 0) - for (int i = 0; i < collection.Length; ++i) - Insert(collection[i]); - } + if (collection.Length > 0) + for (int i = 0; i < collection.Length; ++i) + Insert(collection[i]); + } - /// - /// Inserts a list of elements to the tree. - /// - public override void Insert(List collection) - { - if (collection == null) - throw new ArgumentNullException(); + /// + /// Inserts a list of elements to the tree. + /// + public override void Insert(List collection) + { + if (collection == null) + throw new ArgumentNullException(); - if (collection.Count > 0) - for (int i = 0; i < collection.Count; ++i) - Insert(collection[i]); - } + if (collection.Count > 0) + for (int i = 0; i < collection.Count; ++i) + Insert(collection[i]); + } - /// - /// Removes an item from the tree. - /// - public override void Remove(TKey item) - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Removes an item from the tree. + /// + public override void Remove(TKey item) + { + if (IsEmpty) + throw new Exception("Tree is empty."); - // Get the node from the tree - var node = (RedBlackTreeNode)base._findNode(Root, item); + // Get the node from the tree + var node = (RedBlackTreeNode)base._findNode(Root, item); - // Invoke the internal remove node method. - bool status = _remove(node); + // Invoke the internal remove node method. + bool status = _remove(node); - if (status == false) - throw new Exception("Item was not found."); - } + if (status == false) + throw new Exception("Item was not found."); + } - /// - /// Removes the min value from tree. - /// - public override void RemoveMin() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Removes the min value from tree. + /// + public override void RemoveMin() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - // Get the node from the tree - var node = (RedBlackTreeNode)base._findMinNode(Root); + // Get the node from the tree + var node = (RedBlackTreeNode)base._findMinNode(Root); - // Invoke the internal remove node method. - _remove(node); - } + // Invoke the internal remove node method. + _remove(node); + } - /// - /// Removes the max value from tree. - /// - public override void RemoveMax() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + /// + /// Removes the max value from tree. + /// + public override void RemoveMax() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - // Get the node from the tree - var node = (RedBlackTreeNode)base._findMaxNode(Root); + // Get the node from the tree + var node = (RedBlackTreeNode)base._findMaxNode(Root); - // Invoke the internal remove node method. - _remove(node); - } + // Invoke the internal remove node method. + _remove(node); } -} +} \ No newline at end of file diff --git a/DataStructures/Trees/RedBlackTreeMap.cs b/DataStructures/Trees/RedBlackTreeMap.cs index 9f4b8ed6..c5595af4 100644 --- a/DataStructures/Trees/RedBlackTreeMap.cs +++ b/DataStructures/Trees/RedBlackTreeMap.cs @@ -3,650 +3,648 @@ using DataStructures.Common; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// Red-Black Tree Data Structure. +/// +public class RedBlackTreeMap : BinarySearchTreeMap where TKey : IComparable { /// - /// Red-Black Tree Data Structure. + /// Root node accessors overriding /// - public class RedBlackTreeMap : BinarySearchTreeMap where TKey : IComparable + public new RedBlackTreeMapNode Root { - /// - /// Root node accessors overriding - /// - public new RedBlackTreeMapNode Root - { - get => (RedBlackTreeMapNode)base.Root; - internal set => base.Root = value; - } + get => (RedBlackTreeMapNode)base.Root; + internal set => base.Root = value; + } - /// - /// CONSTRUCTOR. - /// Allows duplicates by default. - /// - public RedBlackTreeMap() : base() { } + /// + /// CONSTRUCTOR. + /// Allows duplicates by default. + /// + public RedBlackTreeMap() : base() { } - /// - /// CONSTRUCTOR. - /// If allowDuplictes is set to false, no duplicate items will be inserted. - /// - public RedBlackTreeMap(bool allowDuplicates) : base(allowDuplicates) { } + /// + /// CONSTRUCTOR. + /// If allowDuplictes is set to false, no duplicate items will be inserted. + /// + public RedBlackTreeMap(bool allowDuplicates) : base(allowDuplicates) { } - /*************************************************************************************************/ - /*** - * Safety Checks/Getters/Setters. - * - * The following are helper methods for safely checking, getting and updating possibly-null objects. - * These helpers make the algorithms of adjusting the tree after insertion and removal more readable. - */ + /*************************************************************************************************/ + /*** + * Safety Checks/Getters/Setters. + * + * The following are helper methods for safely checking, getting and updating possibly-null objects. + * These helpers make the algorithms of adjusting the tree after insertion and removal more readable. + */ - protected RedBlackTreeMapNode _safeGetGrandParent(RedBlackTreeMapNode node) - { - if (node == null || node.Parent == null) - return null; + protected RedBlackTreeMapNode _safeGetGrandParent(RedBlackTreeMapNode node) + { + if (node == null || node.Parent == null) + return null; - return node.GrandParent; - } + return node.GrandParent; + } - protected RedBlackTreeMapNode _safeGetParent(RedBlackTreeMapNode node) - { - if (node == null || node.Parent == null) - return null; + protected RedBlackTreeMapNode _safeGetParent(RedBlackTreeMapNode node) + { + if (node == null || node.Parent == null) + return null; - return node.Parent; - } + return node.Parent; + } - protected RedBlackTreeMapNode _safeGetSibling(RedBlackTreeMapNode node) - { - if (node == null || node.Parent == null) - return null; + protected RedBlackTreeMapNode _safeGetSibling(RedBlackTreeMapNode node) + { + if (node == null || node.Parent == null) + return null; - return node.Sibling; - } + return node.Sibling; + } - protected RedBlackTreeMapNode _safeGetLeftChild(RedBlackTreeMapNode node) - { - if (node == null) - return null; + protected RedBlackTreeMapNode _safeGetLeftChild(RedBlackTreeMapNode node) + { + if (node == null) + return null; - return node.LeftChild; - } + return node.LeftChild; + } - protected RedBlackTreeMapNode _safeGetRightChild(RedBlackTreeMapNode node) - { - if (node == null) - return null; + protected RedBlackTreeMapNode _safeGetRightChild(RedBlackTreeMapNode node) + { + if (node == null) + return null; - return node.RightChild; - } + return node.RightChild; + } - protected virtual RedBlackTreeColors _safeGetColor(RedBlackTreeMapNode node) - { - if (node == null) - return RedBlackTreeColors.Black; + protected virtual RedBlackTreeColors _safeGetColor(RedBlackTreeMapNode node) + { + if (node == null) + return RedBlackTreeColors.Black; - return node.Color; - } + return node.Color; + } - protected virtual void _safeUpdateColor(RedBlackTreeMapNode node, RedBlackTreeColors color) - { - if (node == null) - return; + protected virtual void _safeUpdateColor(RedBlackTreeMapNode node, RedBlackTreeColors color) + { + if (node == null) + return; - node.Color = color; - } + node.Color = color; + } - protected virtual bool _safeCheckIsBlack(RedBlackTreeMapNode node) - { - return node == null || (node != null && node.IsBlack); - } + protected virtual bool _safeCheckIsBlack(RedBlackTreeMapNode node) + { + return node == null || (node != null && node.IsBlack); + } - protected virtual bool _safeCheckIsRed(RedBlackTreeMapNode node) - { - return node != null && node.IsRed; - } + protected virtual bool _safeCheckIsRed(RedBlackTreeMapNode node) + { + return node != null && node.IsRed; + } - /*************************************************************************************************/ - /*** - * Tree Rotations and Adjustements. - * - * The following are methods for rotating the tree (left/right) and for adjusting the - * ... tree after inserting or removing nodes. - */ + /*************************************************************************************************/ + /*** + * Tree Rotations and Adjustements. + * + * The following are methods for rotating the tree (left/right) and for adjusting the + * ... tree after inserting or removing nodes. + */ - /// - /// Rotates a node to the left in the Red-Black Tree. - /// - protected virtual void _rotateLeftAt(RedBlackTreeMapNode currentNode) - { - // We check the right child because it's going to be a pivot node for the rotation - if (currentNode == null || currentNode.HasRightChild == false) - return; + /// + /// Rotates a node to the left in the Red-Black Tree. + /// + protected virtual void _rotateLeftAt(RedBlackTreeMapNode currentNode) + { + // We check the right child because it's going to be a pivot node for the rotation + if (currentNode == null || currentNode.HasRightChild == false) + return; - // Pivot on *right* child - RedBlackTreeMapNode pivotNode = currentNode.RightChild; + // Pivot on *right* child + RedBlackTreeMapNode pivotNode = currentNode.RightChild; - // Parent of currentNode - RedBlackTreeMapNode parent = currentNode.Parent; + // Parent of currentNode + RedBlackTreeMapNode parent = currentNode.Parent; - // Check if currentNode is it's parent's left child. - bool isLeftChild = currentNode.IsLeftChild; + // Check if currentNode is it's parent's left child. + bool isLeftChild = currentNode.IsLeftChild; - // Check if currentNode is the Root - bool isRootNode = currentNode == Root; + // Check if currentNode is the Root + bool isRootNode = currentNode == Root; - // Perform the rotation - currentNode.RightChild = pivotNode.LeftChild; - pivotNode.LeftChild = currentNode; + // Perform the rotation + currentNode.RightChild = pivotNode.LeftChild; + pivotNode.LeftChild = currentNode; - // Update parents references - currentNode.Parent = pivotNode; - pivotNode.Parent = parent; + // Update parents references + currentNode.Parent = pivotNode; + pivotNode.Parent = parent; - if (currentNode.HasRightChild) - currentNode.RightChild.Parent = currentNode; + if (currentNode.HasRightChild) + currentNode.RightChild.Parent = currentNode; - //Update the entire tree's Root if necessary - if (isRootNode) - Root = pivotNode; + //Update the entire tree's Root if necessary + if (isRootNode) + Root = pivotNode; - // Update the original parent's child node - if (isLeftChild) - parent.LeftChild = pivotNode; - else if (parent != null) - parent.RightChild = pivotNode; - } + // Update the original parent's child node + if (isLeftChild) + parent.LeftChild = pivotNode; + else if (parent != null) + parent.RightChild = pivotNode; + } - /// - /// Rotates a node to the right in the Red-Black Tree. - /// - protected virtual void _rotateRightAt(RedBlackTreeMapNode currentNode) - { - // We check the right child because it's going to be a pivot node for the rotation - if (currentNode == null || currentNode.HasLeftChild == false) - return; + /// + /// Rotates a node to the right in the Red-Black Tree. + /// + protected virtual void _rotateRightAt(RedBlackTreeMapNode currentNode) + { + // We check the right child because it's going to be a pivot node for the rotation + if (currentNode == null || currentNode.HasLeftChild == false) + return; - // Pivot on *left* child - var pivotNode = currentNode.LeftChild; + // Pivot on *left* child + var pivotNode = currentNode.LeftChild; - // Parent of currentNode - var parent = currentNode.Parent; + // Parent of currentNode + var parent = currentNode.Parent; - // Check if currentNode is it's parent's left child. - bool isLeftChild = currentNode.IsLeftChild; + // Check if currentNode is it's parent's left child. + bool isLeftChild = currentNode.IsLeftChild; - // Check if currentNode is the Root - bool isRootNode = currentNode == Root; + // Check if currentNode is the Root + bool isRootNode = currentNode == Root; - // Perform the rotation - currentNode.LeftChild = pivotNode.RightChild; - pivotNode.RightChild = currentNode; + // Perform the rotation + currentNode.LeftChild = pivotNode.RightChild; + pivotNode.RightChild = currentNode; - // Update parents references - currentNode.Parent = pivotNode; - pivotNode.Parent = parent; + // Update parents references + currentNode.Parent = pivotNode; + pivotNode.Parent = parent; - if (currentNode.HasLeftChild) - currentNode.LeftChild.Parent = currentNode; + if (currentNode.HasLeftChild) + currentNode.LeftChild.Parent = currentNode; - // Update the entire tree's Root if necessary - if (isRootNode) - Root = pivotNode; + // Update the entire tree's Root if necessary + if (isRootNode) + Root = pivotNode; - // Update the original parent's child node - if (isLeftChild) - parent.LeftChild = pivotNode; - else if (parent != null) - parent.RightChild = pivotNode; - } + // Update the original parent's child node + if (isLeftChild) + parent.LeftChild = pivotNode; + else if (parent != null) + parent.RightChild = pivotNode; + } - /// - /// After insertion tree-adjustement helper. - /// - protected virtual void _adjustTreeAfterInsertion(RedBlackTreeMapNode currentNode) + /// + /// After insertion tree-adjustement helper. + /// + protected virtual void _adjustTreeAfterInsertion(RedBlackTreeMapNode currentNode) + { + // + // STEP 1: + // Color the currentNode as red + _safeUpdateColor(currentNode, RedBlackTreeColors.Red); + + // + // STEP 2: + // Fix the double red-consecutive-nodes problems, if there exists any. + if (currentNode != null && currentNode != Root && _safeCheckIsRed(_safeGetParent(currentNode))) { // - // STEP 1: - // Color the currentNode as red - _safeUpdateColor(currentNode, RedBlackTreeColors.Red); - - // - // STEP 2: - // Fix the double red-consecutive-nodes problems, if there exists any. - if (currentNode != null && currentNode != Root && _safeCheckIsRed(_safeGetParent(currentNode))) + // STEP 2.A: + // This is the simplest step: Basically recolor, and bubble up to see if more work is needed. + if (_safeCheckIsRed(_safeGetSibling(currentNode.Parent))) { - // - // STEP 2.A: - // This is the simplest step: Basically recolor, and bubble up to see if more work is needed. - if (_safeCheckIsRed(_safeGetSibling(currentNode.Parent))) - { - // If it has a sibling and it is red, then then it has a parent - currentNode.Parent.Color = RedBlackTreeColors.Red; + // If it has a sibling and it is red, then then it has a parent + currentNode.Parent.Color = RedBlackTreeColors.Red; - // Color sibling of parent as black - _safeUpdateColor(_safeGetSibling(currentNode.Parent), RedBlackTreeColors.Black); + // Color sibling of parent as black + _safeUpdateColor(_safeGetSibling(currentNode.Parent), RedBlackTreeColors.Black); - // Color grandparent as red - _safeUpdateColor(_safeGetGrandParent(currentNode), RedBlackTreeColors.Red); + // Color grandparent as red + _safeUpdateColor(_safeGetGrandParent(currentNode), RedBlackTreeColors.Red); - // Adjust on the grandparent of currentNode - _adjustTreeAfterInsertion(_safeGetGrandParent(currentNode)); - } + // Adjust on the grandparent of currentNode + _adjustTreeAfterInsertion(_safeGetGrandParent(currentNode)); + } - // - // STEP 2.B: - // Restructure the tree if the parent of currentNode is a left child to the grandparent of currentNode - // (parent is a left child to its own parent). - // If currentNode is also a left child, then do a single right rotation; otherwise, a left-right rotation. - // - // using the safe methods to check: currentNode.Parent.IsLeftChild == true - else if (_safeGetParent(currentNode) == _safeGetLeftChild(_safeGetGrandParent(currentNode))) + // + // STEP 2.B: + // Restructure the tree if the parent of currentNode is a left child to the grandparent of currentNode + // (parent is a left child to its own parent). + // If currentNode is also a left child, then do a single right rotation; otherwise, a left-right rotation. + // + // using the safe methods to check: currentNode.Parent.IsLeftChild == true + else if (_safeGetParent(currentNode) == _safeGetLeftChild(_safeGetGrandParent(currentNode))) + { + if (currentNode.IsRightChild) { - if (currentNode.IsRightChild) - { - currentNode = _safeGetParent(currentNode); - _rotateLeftAt(currentNode); - } + currentNode = _safeGetParent(currentNode); + _rotateLeftAt(currentNode); + } - // Color parent as black - _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); + // Color parent as black + _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); - // Color grandparent as red - _safeUpdateColor(_safeGetGrandParent(currentNode), RedBlackTreeColors.Red); + // Color grandparent as red + _safeUpdateColor(_safeGetGrandParent(currentNode), RedBlackTreeColors.Red); - // Right Rotate tree around the currentNode's grand parent - _rotateRightAt(_safeGetGrandParent(currentNode)); - } + // Right Rotate tree around the currentNode's grand parent + _rotateRightAt(_safeGetGrandParent(currentNode)); + } - // - // STEP 2.C: - // Restructure the tree if the parent of currentNode is a right child to the grandparent of currentNode - // (parent is a right child to its own parent). - // If currentNode is a right-child in it's parent, then do a single left rotation; otherwise a right-left rotation. - // - // using the safe methods to check: currentNode.Parent.IsRightChild == true - else if (_safeGetParent(currentNode) == _safeGetRightChild(_safeGetGrandParent(currentNode))) + // + // STEP 2.C: + // Restructure the tree if the parent of currentNode is a right child to the grandparent of currentNode + // (parent is a right child to its own parent). + // If currentNode is a right-child in it's parent, then do a single left rotation; otherwise a right-left rotation. + // + // using the safe methods to check: currentNode.Parent.IsRightChild == true + else if (_safeGetParent(currentNode) == _safeGetRightChild(_safeGetGrandParent(currentNode))) + { + if (currentNode.IsLeftChild) { - if (currentNode.IsLeftChild) - { - currentNode = _safeGetParent(currentNode); - _rotateRightAt(currentNode); - } + currentNode = _safeGetParent(currentNode); + _rotateRightAt(currentNode); + } - // Color parent as black - _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); + // Color parent as black + _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); - // Color grandparent as red - _safeUpdateColor(_safeGetGrandParent(currentNode), RedBlackTreeColors.Red); + // Color grandparent as red + _safeUpdateColor(_safeGetGrandParent(currentNode), RedBlackTreeColors.Red); - // Left Rotate tree around the currentNode's grand parent - _rotateLeftAt(_safeGetGrandParent(currentNode)); - } + // Left Rotate tree around the currentNode's grand parent + _rotateLeftAt(_safeGetGrandParent(currentNode)); } - - // STEP 3: - // Color the root node as black - _safeUpdateColor(Root, RedBlackTreeColors.Black); } - /// - /// After removal tree-adjustement helper. - /// - protected virtual void _adjustTreeAfterRemoval(RedBlackTreeMapNode currentNode) + // STEP 3: + // Color the root node as black + _safeUpdateColor(Root, RedBlackTreeColors.Black); + } + + /// + /// After removal tree-adjustement helper. + /// + protected virtual void _adjustTreeAfterRemoval(RedBlackTreeMapNode currentNode) + { + while (currentNode != null && currentNode != Root && currentNode.IsBlack) { - while (currentNode != null && currentNode != Root && currentNode.IsBlack) + if (currentNode.IsLeftChild) { - if (currentNode.IsLeftChild) + // Get sibling of currentNode + // Safe equivalent of currentNode.Sibling or currentNode.Parent.RightChild + var sibling = _safeGetRightChild(_safeGetParent(currentNode)); + + // Safely check sibling.IsRed property + if (_safeCheckIsRed(sibling)) + { + // Color currentNode.Sibling as black + _safeUpdateColor(sibling, RedBlackTreeColors.Black); + + // Color currentNode.Parent as red + _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Red); + + // Left Rotate on currentNode's parent + _rotateLeftAt(_safeGetParent(currentNode)); + + // Update sibling reference + // Might end be being set to null + sibling = _safeGetRightChild(_safeGetParent(currentNode)); + } + + // Check if the left and right children of the sibling node are black + // Use the safe methods to check for: (sibling.LeftChild.IsBlack && sibling.RightChild.IsBlack) + if (_safeCheckIsBlack(_safeGetLeftChild(sibling)) && _safeCheckIsBlack(_safeGetRightChild(sibling))) { - // Get sibling of currentNode - // Safe equivalent of currentNode.Sibling or currentNode.Parent.RightChild - var sibling = _safeGetRightChild(_safeGetParent(currentNode)); + // Color currentNode.Sibling as red + _safeUpdateColor(sibling, RedBlackTreeColors.Red); - // Safely check sibling.IsRed property - if (_safeCheckIsRed(sibling)) + // Assign currentNode.Parent to currentNode + currentNode = _safeGetParent(currentNode); + } + else + { + if (_safeCheckIsBlack(_safeGetRightChild(sibling))) { - // Color currentNode.Sibling as black - _safeUpdateColor(sibling, RedBlackTreeColors.Black); + // Color currentNode.Sibling.LeftChild as black + _safeUpdateColor(_safeGetLeftChild(sibling), RedBlackTreeColors.Black); - // Color currentNode.Parent as red - _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Red); + // Color currentNode.Sibling as red + _safeUpdateColor(sibling, RedBlackTreeColors.Red); - // Left Rotate on currentNode's parent - _rotateLeftAt(_safeGetParent(currentNode)); + // Right Rotate on sibling + _rotateRightAt(sibling); // Update sibling reference // Might end be being set to null sibling = _safeGetRightChild(_safeGetParent(currentNode)); } - // Check if the left and right children of the sibling node are black - // Use the safe methods to check for: (sibling.LeftChild.IsBlack && sibling.RightChild.IsBlack) - if (_safeCheckIsBlack(_safeGetLeftChild(sibling)) && _safeCheckIsBlack(_safeGetRightChild(sibling))) - { - // Color currentNode.Sibling as red - _safeUpdateColor(sibling, RedBlackTreeColors.Red); + // Color the Sibling node as currentNode.Parent.Color + _safeUpdateColor(sibling, _safeGetColor(_safeGetParent(currentNode))); - // Assign currentNode.Parent to currentNode - currentNode = _safeGetParent(currentNode); - } - else - { - if (_safeCheckIsBlack(_safeGetRightChild(sibling))) - { - // Color currentNode.Sibling.LeftChild as black - _safeUpdateColor(_safeGetLeftChild(sibling), RedBlackTreeColors.Black); + // Color currentNode.Parent as black + _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); - // Color currentNode.Sibling as red - _safeUpdateColor(sibling, RedBlackTreeColors.Red); + // Color Sibling.RightChild as black + _safeUpdateColor(_safeGetRightChild(sibling), RedBlackTreeColors.Black); - // Right Rotate on sibling - _rotateRightAt(sibling); + // Rotate on currentNode's parent + _rotateLeftAt(_safeGetParent(currentNode)); - // Update sibling reference - // Might end be being set to null - sibling = _safeGetRightChild(_safeGetParent(currentNode)); - } + currentNode = Root; + } + } + else + { + // Get sibling of currentNode + // Safe equivalent of currentNode.Sibling or currentNode.Parent.LeftChild + var sibling = _safeGetLeftChild(_safeGetParent(currentNode)); - // Color the Sibling node as currentNode.Parent.Color - _safeUpdateColor(sibling, _safeGetColor(_safeGetParent(currentNode))); + if (_safeCheckIsRed(sibling)) + { + // Color currentNode.Sibling as black + _safeUpdateColor(sibling, RedBlackTreeColors.Black); - // Color currentNode.Parent as black - _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); + // Color currentNode.Parent as red + _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Red); - // Color Sibling.RightChild as black - _safeUpdateColor(_safeGetRightChild(sibling), RedBlackTreeColors.Black); + // Right Rotate tree around the parent of currentNode + _rotateRightAt(_safeGetParent(currentNode)); + + // Update sibling reference + // Might end be being set to null + sibling = _safeGetLeftChild(_safeGetParent(currentNode)); + } - // Rotate on currentNode's parent - _rotateLeftAt(_safeGetParent(currentNode)); + // Check if the left and right children of the sibling node are black + // Use the safe methods to check for: (sibling.LeftChild.IsBlack && sibling.RightChild.IsBlack) + if (_safeCheckIsBlack(_safeGetLeftChild(sibling)) && _safeCheckIsBlack(_safeGetRightChild(sibling))) + { + _safeUpdateColor(sibling, RedBlackTreeColors.Red); - currentNode = Root; - } + // Assign currentNode.Parent to currentNode + currentNode = _safeGetParent(currentNode); } else { - // Get sibling of currentNode - // Safe equivalent of currentNode.Sibling or currentNode.Parent.LeftChild - var sibling = _safeGetLeftChild(_safeGetParent(currentNode)); - - if (_safeCheckIsRed(sibling)) + // Check if sibling.LeftChild.IsBlack == true + if (_safeCheckIsBlack(_safeGetLeftChild(sibling))) { - // Color currentNode.Sibling as black - _safeUpdateColor(sibling, RedBlackTreeColors.Black); + // Color currentNode.Sibling.RightChild as black + _safeUpdateColor(_safeGetRightChild(sibling), RedBlackTreeColors.Black); - // Color currentNode.Parent as red - _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Red); + // Color currentNode.Sibling as red + _safeUpdateColor(sibling, RedBlackTreeColors.Red); - // Right Rotate tree around the parent of currentNode - _rotateRightAt(_safeGetParent(currentNode)); + // Left rotate on sibling + _rotateLeftAt(sibling); // Update sibling reference // Might end be being set to null sibling = _safeGetLeftChild(_safeGetParent(currentNode)); } - // Check if the left and right children of the sibling node are black - // Use the safe methods to check for: (sibling.LeftChild.IsBlack && sibling.RightChild.IsBlack) - if (_safeCheckIsBlack(_safeGetLeftChild(sibling)) && _safeCheckIsBlack(_safeGetRightChild(sibling))) - { - _safeUpdateColor(sibling, RedBlackTreeColors.Red); - - // Assign currentNode.Parent to currentNode - currentNode = _safeGetParent(currentNode); - } - else - { - // Check if sibling.LeftChild.IsBlack == true - if (_safeCheckIsBlack(_safeGetLeftChild(sibling))) - { - // Color currentNode.Sibling.RightChild as black - _safeUpdateColor(_safeGetRightChild(sibling), RedBlackTreeColors.Black); + // Color the Sibling node as currentNode.Parent.Color + _safeUpdateColor(sibling, _safeGetColor(_safeGetParent(currentNode))); - // Color currentNode.Sibling as red - _safeUpdateColor(sibling, RedBlackTreeColors.Red); + // Color currentNode.Parent as black + _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); - // Left rotate on sibling - _rotateLeftAt(sibling); + // Color Sibling.RightChild as black + _safeUpdateColor(_safeGetLeftChild(sibling), RedBlackTreeColors.Black); - // Update sibling reference - // Might end be being set to null - sibling = _safeGetLeftChild(_safeGetParent(currentNode)); - } + // Right rotate on the parent of currentNode + _rotateRightAt(_safeGetParent(currentNode)); - // Color the Sibling node as currentNode.Parent.Color - _safeUpdateColor(sibling, _safeGetColor(_safeGetParent(currentNode))); + currentNode = Root; + } + } + } - // Color currentNode.Parent as black - _safeUpdateColor(_safeGetParent(currentNode), RedBlackTreeColors.Black); + // Color currentNode as black + _safeUpdateColor(currentNode, RedBlackTreeColors.Black); + } - // Color Sibling.RightChild as black - _safeUpdateColor(_safeGetLeftChild(sibling), RedBlackTreeColors.Black); + /// + /// Remove node helpers. + /// + protected override bool _remove(BSTMapNode nodeToDelete) + { + return _remove((RedBlackTreeMapNode)nodeToDelete); + } - // Right rotate on the parent of currentNode - _rotateRightAt(_safeGetParent(currentNode)); + /// + /// The internal remove helper. + /// Separated from the overriden version to avoid casting the objects from BSTMapNode to RedBlackTreeMapNode. + /// This is called from the overriden _remove(BSTMapNode nodeToDelete) helper. + /// + protected bool _remove(RedBlackTreeMapNode nodeToDelete) + { + if (nodeToDelete == null) + return false; - currentNode = Root; - } - } - } + // Temporary nodes + RedBlackTreeMapNode node1, node2; - // Color currentNode as black - _safeUpdateColor(currentNode, RedBlackTreeColors.Black); + // If nodeToDelete has either one child or no children at all + if (!nodeToDelete.HasLeftChild || !nodeToDelete.HasRightChild) + { + node1 = nodeToDelete; } - - /// - /// Remove node helpers. - /// - protected override bool _remove(BSTMapNode nodeToDelete) + else { - return _remove((RedBlackTreeMapNode)nodeToDelete); + // nodeToDelete has two children + node1 = (RedBlackTreeMapNode)base._findNextLarger(nodeToDelete); } - /// - /// The internal remove helper. - /// Separated from the overriden version to avoid casting the objects from BSTMapNode to RedBlackTreeMapNode. - /// This is called from the overriden _remove(BSTMapNode nodeToDelete) helper. - /// - protected bool _remove(RedBlackTreeMapNode nodeToDelete) + // Left child case + if (node1.HasLeftChild) { - if (nodeToDelete == null) - return false; - - // Temporary nodes - RedBlackTreeMapNode node1, node2; - - // If nodeToDelete has either one child or no children at all - if (!nodeToDelete.HasLeftChild || !nodeToDelete.HasRightChild) - { - node1 = nodeToDelete; - } - else - { - // nodeToDelete has two children - node1 = (RedBlackTreeMapNode)base._findNextLarger(nodeToDelete); - } - - // Left child case - if (node1.HasLeftChild) - { - node2 = node1.LeftChild; - } - else - { - node2 = node1.RightChild; - } + node2 = node1.LeftChild; + } + else + { + node2 = node1.RightChild; + } - // If node2 is not null, copy parent references - if (node2 != null) - node2.Parent = node1.Parent; + // If node2 is not null, copy parent references + if (node2 != null) + node2.Parent = node1.Parent; - if (node1.Parent != null) + if (node1.Parent != null) + { + if (node1.IsLeftChild) { - if (node1.IsLeftChild) - { - node1.Parent.LeftChild = node2; - } - else - { - node1.Parent.RightChild = node2; - } + node1.Parent.LeftChild = node2; } else { - Root = node2; - Root.Parent = null; + node1.Parent.RightChild = node2; } + } + else + { + Root = node2; + Root.Parent = null; + } - // Swap values - if (!node1.IsEqualTo(nodeToDelete)) - { - nodeToDelete.Key = node1.Key; - nodeToDelete.Value = node1.Value; - } + // Swap values + if (!node1.IsEqualTo(nodeToDelete)) + { + nodeToDelete.Key = node1.Key; + nodeToDelete.Value = node1.Value; + } - // Adjust the Red-Black Tree rules - if (node1.Color == RedBlackTreeColors.Black && node2 != null) - { - _adjustTreeAfterRemoval(node2); - Root.Color = RedBlackTreeColors.Black; - } + // Adjust the Red-Black Tree rules + if (node1.Color == RedBlackTreeColors.Black && node2 != null) + { + _adjustTreeAfterRemoval(node2); + Root.Color = RedBlackTreeColors.Black; + } - // Decrement the count - _count--; + // Decrement the count + _count--; - return true; - } + return true; + } - /*************************************************************************************************/ + /*************************************************************************************************/ - /// - /// Insert data item to tree - /// - public override void Insert(TKey key, TValue value) - { - var newNode = new RedBlackTreeMapNode(key, value); + /// + /// Insert data item to tree + /// + public override void Insert(TKey key, TValue value) + { + var newNode = new RedBlackTreeMapNode(key, value); - // Invoke the super BST insert node method. - // This insert node recursively starting from the root and checks for success status (related to allowDuplicates flag). - // The functions increments count on its own. - var success = base._insertNode(newNode); + // Invoke the super BST insert node method. + // This insert node recursively starting from the root and checks for success status (related to allowDuplicates flag). + // The functions increments count on its own. + var success = base._insertNode(newNode); - if (success == false && _allowDuplicates == false) - throw new InvalidOperationException("Tree does not allow inserting duplicate elements."); + if (success == false && _allowDuplicates == false) + throw new InvalidOperationException("Tree does not allow inserting duplicate elements."); - // Adjust Red-Black Tree rules - if (!newNode.IsEqualTo(Root)) + // Adjust Red-Black Tree rules + if (!newNode.IsEqualTo(Root)) if (newNode.Parent.Color != RedBlackTreeColors.Black) // Case 0: Parent is not black and we have to restructure tree _adjustTreeAfterInsertion(newNode); - // Always color root as black - Root.Color = RedBlackTreeColors.Black; - } - - /// - /// Inserts an array of elements to the tree. - /// - public override void Insert(TKey[] collection) - { - if (collection == null) - throw new ArgumentNullException(); + // Always color root as black + Root.Color = RedBlackTreeColors.Black; + } - if (collection.Length > 0) - for (int i = 0; i < collection.Length; ++i) - Insert(collection[i], default); - } + /// + /// Inserts an array of elements to the tree. + /// + public override void Insert(TKey[] collection) + { + if (collection == null) + throw new ArgumentNullException(); - /// - /// Inserts an array of key-value pairs to the tree. - /// - public override void Insert(KeyValuePair[] collection) - { - if (collection == null) - throw new ArgumentNullException(); + if (collection.Length > 0) + for (int i = 0; i < collection.Length; ++i) + Insert(collection[i], default); + } - if (collection.Length > 0) - for (int i = 0; i < collection.Length; ++i) - Insert(collection[i].Key, collection[i].Value); - } + /// + /// Inserts an array of key-value pairs to the tree. + /// + public override void Insert(KeyValuePair[] collection) + { + if (collection == null) + throw new ArgumentNullException(); - /// - /// Inserts a list of elements to the tree. - /// - public override void Insert(List collection) - { - if (collection == null) - throw new ArgumentNullException(); + if (collection.Length > 0) + for (int i = 0; i < collection.Length; ++i) + Insert(collection[i].Key, collection[i].Value); + } - if (collection.Count > 0) - for (int i = 0; i < collection.Count; ++i) - Insert(collection[i], default); - } + /// + /// Inserts a list of elements to the tree. + /// + public override void Insert(List collection) + { + if (collection == null) + throw new ArgumentNullException(); - /// - /// Inserts a list of key-value pairs to the tree. - /// - public override void Insert(List> collection) - { - if (collection == null) - throw new ArgumentNullException(); + if (collection.Count > 0) + for (int i = 0; i < collection.Count; ++i) + Insert(collection[i], default); + } - if (collection.Count > 0) - for (int i = 0; i < collection.Count; ++i) - Insert(collection[i].Key, collection[i].Value); - } + /// + /// Inserts a list of key-value pairs to the tree. + /// + public override void Insert(List> collection) + { + if (collection == null) + throw new ArgumentNullException(); - /// - /// Removes an item from the tree. - /// - public override void Remove(TKey key) - { - if (IsEmpty) - throw new Exception("Tree is empty."); + if (collection.Count > 0) + for (int i = 0; i < collection.Count; ++i) + Insert(collection[i].Key, collection[i].Value); + } - // Get the node from the tree - var node = (RedBlackTreeMapNode)base._findNode(Root, key); + /// + /// Removes an item from the tree. + /// + public override void Remove(TKey key) + { + if (IsEmpty) + throw new Exception("Tree is empty."); - // Invoke the internal remove node method. - bool status = _remove(node); + // Get the node from the tree + var node = (RedBlackTreeMapNode)base._findNode(Root, key); - if (status == false) - throw new Exception("Item was not found."); - } + // Invoke the internal remove node method. + bool status = _remove(node); - /// - /// Removes the min value from tree. - /// - public override void RemoveMin() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + if (status == false) + throw new Exception("Item was not found."); + } - // Get the node from the tree - var node = (RedBlackTreeMapNode)base._findMinNode(Root); + /// + /// Removes the min value from tree. + /// + public override void RemoveMin() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - // Invoke the internal remove node method. - _remove(node); - } + // Get the node from the tree + var node = (RedBlackTreeMapNode)base._findMinNode(Root); - /// - /// Removes the max value from tree. - /// - public override void RemoveMax() - { - if (IsEmpty) - throw new Exception("Tree is empty."); + // Invoke the internal remove node method. + _remove(node); + } - // Get the node from the tree - var node = (RedBlackTreeMapNode)base._findMaxNode(Root); + /// + /// Removes the max value from tree. + /// + public override void RemoveMax() + { + if (IsEmpty) + throw new Exception("Tree is empty."); - // Invoke the internal remove node method. - _remove(node); - } + // Get the node from the tree + var node = (RedBlackTreeMapNode)base._findMaxNode(Root); + // Invoke the internal remove node method. + _remove(node); } -} +} \ No newline at end of file diff --git a/DataStructures/Trees/RedBlackTreeMapNode.cs b/DataStructures/Trees/RedBlackTreeMapNode.cs index 57f7f4ee..0c8d7ebb 100644 --- a/DataStructures/Trees/RedBlackTreeMapNode.cs +++ b/DataStructures/Trees/RedBlackTreeMapNode.cs @@ -1,68 +1,66 @@ -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// Red-Black Tree Map Node. +/// +public class RedBlackTreeMapNode : BSTMapNode where TKey : System.IComparable { /// - /// Red-Black Tree Map Node. + /// CONSTRUCTORS /// - public class RedBlackTreeMapNode : BSTMapNode where TKey : System.IComparable + public RedBlackTreeMapNode(TKey key) : this(key, default, 0, null, null, null) { } + public RedBlackTreeMapNode(TKey key, TValue value) : this(key, value, 0, null, null, null) { } + public RedBlackTreeMapNode(TKey key, TValue value, int height, RedBlackTreeMapNode parent, RedBlackTreeMapNode left, RedBlackTreeMapNode right) { - /// - /// CONSTRUCTORS - /// - public RedBlackTreeMapNode(TKey key) : this(key, default, 0, null, null, null) { } - public RedBlackTreeMapNode(TKey key, TValue value) : this(key, value, 0, null, null, null) { } - public RedBlackTreeMapNode(TKey key, TValue value, int height, RedBlackTreeMapNode parent, RedBlackTreeMapNode left, RedBlackTreeMapNode right) - { - Key = key; - Value = value; - Color = RedBlackTreeColors.Red; - Parent = parent; - LeftChild = left; - RightChild = right; - } - - public virtual RedBlackTreeColors Color { get; set; } + Key = key; + Value = value; + Color = RedBlackTreeColors.Red; + Parent = parent; + LeftChild = left; + RightChild = right; + } - public new RedBlackTreeMapNode Parent - { - get => (RedBlackTreeMapNode)base.Parent; - set => base.Parent = value; - } + public virtual RedBlackTreeColors Color { get; set; } - public new RedBlackTreeMapNode LeftChild - { - get => (RedBlackTreeMapNode)base.LeftChild; - set => base.LeftChild = value; - } + public new RedBlackTreeMapNode Parent + { + get => (RedBlackTreeMapNode)base.Parent; + set => base.Parent = value; + } - public new RedBlackTreeMapNode RightChild - { - get => (RedBlackTreeMapNode)base.RightChild; - set => base.RightChild = value; - } + public new RedBlackTreeMapNode LeftChild + { + get => (RedBlackTreeMapNode)base.LeftChild; + set => base.LeftChild = value; + } + public new RedBlackTreeMapNode RightChild + { + get => (RedBlackTreeMapNode)base.RightChild; + set => base.RightChild = value; + } - /******************************************************************************/ + /******************************************************************************/ - /// - /// Returns if this node is colored red. - /// - public virtual bool IsRed => Color == RedBlackTreeColors.Red; - /// - /// Checks whether this node is colored black. - /// - public virtual bool IsBlack => Color == RedBlackTreeColors.Black; + /// + /// Returns if this node is colored red. + /// + public virtual bool IsRed => Color == RedBlackTreeColors.Red; - /// - /// Returns the sibling of this node. - /// - public virtual RedBlackTreeMapNode Sibling => Parent == null ? null : IsLeftChild ? Parent.RightChild : Parent.LeftChild; + /// + /// Checks whether this node is colored black. + /// + public virtual bool IsBlack => Color == RedBlackTreeColors.Black; - /// - /// Returns the grandparent of this node. - /// - public virtual RedBlackTreeMapNode GrandParent => Parent == null ? null : Parent.Parent; - } + /// + /// Returns the sibling of this node. + /// + public virtual RedBlackTreeMapNode Sibling => Parent == null ? null : IsLeftChild ? Parent.RightChild : Parent.LeftChild; -} + /// + /// Returns the grandparent of this node. + /// + public virtual RedBlackTreeMapNode GrandParent => Parent == null ? null : Parent.Parent; +} \ No newline at end of file diff --git a/DataStructures/Trees/RedBlackTreeNode.cs b/DataStructures/Trees/RedBlackTreeNode.cs index 2bece0a5..f5c31590 100644 --- a/DataStructures/Trees/RedBlackTreeNode.cs +++ b/DataStructures/Trees/RedBlackTreeNode.cs @@ -1,67 +1,65 @@ -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// Red-Black Tree Node. +/// +public class RedBlackTreeNode : BSTNode where TKey : System.IComparable { /// - /// Red-Black Tree Node. + /// CONSTRUCTORS /// - public class RedBlackTreeNode : BSTNode where TKey : System.IComparable + public RedBlackTreeNode() : this(default, 0, null, null, null) { } + public RedBlackTreeNode(TKey value) : this(value, 0, null, null, null) { } + public RedBlackTreeNode(TKey value, int height, RedBlackTreeNode parent, RedBlackTreeNode left, RedBlackTreeNode right) { - /// - /// CONSTRUCTORS - /// - public RedBlackTreeNode() : this(default, 0, null, null, null) { } - public RedBlackTreeNode(TKey value) : this(value, 0, null, null, null) { } - public RedBlackTreeNode(TKey value, int height, RedBlackTreeNode parent, RedBlackTreeNode left, RedBlackTreeNode right) - { - base.Value = value; - Color = RedBlackTreeColors.Red; - Parent = parent; - LeftChild = left; - RightChild = right; - } - - public virtual RedBlackTreeColors Color { get; set; } + base.Value = value; + Color = RedBlackTreeColors.Red; + Parent = parent; + LeftChild = left; + RightChild = right; + } - public new RedBlackTreeNode Parent - { - get => (RedBlackTreeNode)base.Parent; - set => base.Parent = value; - } + public virtual RedBlackTreeColors Color { get; set; } - public new RedBlackTreeNode LeftChild - { - get => (RedBlackTreeNode)base.LeftChild; - set => base.LeftChild = value; - } + public new RedBlackTreeNode Parent + { + get => (RedBlackTreeNode)base.Parent; + set => base.Parent = value; + } - public new RedBlackTreeNode RightChild - { - get => (RedBlackTreeNode)base.RightChild; - set => base.RightChild = value; - } + public new RedBlackTreeNode LeftChild + { + get => (RedBlackTreeNode)base.LeftChild; + set => base.LeftChild = value; + } + public new RedBlackTreeNode RightChild + { + get => (RedBlackTreeNode)base.RightChild; + set => base.RightChild = value; + } - /******************************************************************************/ + /******************************************************************************/ - /// - /// Returns if this node is colored red. - /// - public virtual bool IsRed => Color == RedBlackTreeColors.Red; - /// - /// Checks whether this node is colored black. - /// - public virtual bool IsBlack => Color == RedBlackTreeColors.Black; + /// + /// Returns if this node is colored red. + /// + public virtual bool IsRed => Color == RedBlackTreeColors.Red; - /// - /// Returns the sibling of this node. - /// - public virtual RedBlackTreeNode Sibling => Parent == null ? null : IsLeftChild ? Parent.RightChild : Parent.LeftChild; + /// + /// Checks whether this node is colored black. + /// + public virtual bool IsBlack => Color == RedBlackTreeColors.Black; - /// - /// Returns the grandparent of this node. - /// - public virtual RedBlackTreeNode GrandParent => Parent == null ? null : Parent.Parent; - } + /// + /// Returns the sibling of this node. + /// + public virtual RedBlackTreeNode Sibling => Parent == null ? null : IsLeftChild ? Parent.RightChild : Parent.LeftChild; -} + /// + /// Returns the grandparent of this node. + /// + public virtual RedBlackTreeNode GrandParent => Parent == null ? null : Parent.Parent; +} \ No newline at end of file diff --git a/DataStructures/Trees/TernarySearchTree.cs b/DataStructures/Trees/TernarySearchTree.cs index e9a4a430..82f61346 100644 --- a/DataStructures/Trees/TernarySearchTree.cs +++ b/DataStructures/Trees/TernarySearchTree.cs @@ -2,81 +2,80 @@ using System.Collections.Generic; using System.Text; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +public class TernarySearchTree { - public class TernarySearchTree - { - public TernaryTreeNode Root { get; private set; } + public TernaryTreeNode Root { get; private set; } - public void Insert(string word) - { - if (string.IsNullOrWhiteSpace(word)) - throw new Exception("Inputted value is empty"); + public void Insert(string word) + { + if (string.IsNullOrWhiteSpace(word)) + throw new Exception("Inputted value is empty"); - if (Root == null) - Root = new TernaryTreeNode(null, word[0], word.Length == 1); + if (Root == null) + Root = new TernaryTreeNode(null, word[0], word.Length == 1); - WordInsertion(word); - } + WordInsertion(word); + } - public void Insert(string[] words) + public void Insert(string[] words) + { + foreach (var word in words) { - foreach (var word in words) - { - Insert(word); - } + Insert(word); } + } - void WordInsertion(string word) - { - int index = 0; - TernaryTreeNode currentNode = Root; + void WordInsertion(string word) + { + int index = 0; + TernaryTreeNode currentNode = Root; - while (index < word.Length) - currentNode = ChooseNode(currentNode, word, ref index); - } + while (index < word.Length) + currentNode = ChooseNode(currentNode, word, ref index); + } - TernaryTreeNode ChooseNode(TernaryTreeNode currentNode, string word, ref int index) + TernaryTreeNode ChooseNode(TernaryTreeNode currentNode, string word, ref int index) + { + //Center Branch + if (word[index] == currentNode.Value) { - //Center Branch - if (word[index] == currentNode.Value) - { - index++; + index++; - if (currentNode.GetMiddleChild == null) - InsertInTree(currentNode.AddMiddleChild(word[index], word.Length == index + 1), word, ref index); + if (currentNode.GetMiddleChild == null) + InsertInTree(currentNode.AddMiddleChild(word[index], word.Length == index + 1), word, ref index); - return currentNode.GetMiddleChild; - } - //Right Branch - else if (word[index] > currentNode.Value) - { - if (currentNode.GetRightChild == null) - InsertInTree(currentNode.AddRightChild(word[index], word.Length == index + 1), word, ref index); - - return currentNode.GetRightChild; - } - //Left Branch - else - { - if (currentNode.GetLeftChild == null) - InsertInTree(currentNode.AddLeftChild(word[index], word.Length == index + 1), word, ref index); - - return currentNode.GetLeftChild; - } + return currentNode.GetMiddleChild; } - - void InsertInTree(TernaryTreeNode currentNode, string word, ref int currentIndex) + //Right Branch + else if (word[index] > currentNode.Value) { - int length = word.Length; + if (currentNode.GetRightChild == null) + InsertInTree(currentNode.AddRightChild(word[index], word.Length == index + 1), word, ref index); - currentIndex++; - var currNode = currentNode; - for (int i = currentIndex; i < length; i++) - currNode = currNode.AddMiddleChild(word[i], word.Length == currentIndex + 1); + return currentNode.GetRightChild; + } + //Left Branch + else + { + if (currentNode.GetLeftChild == null) + InsertInTree(currentNode.AddLeftChild(word[index], word.Length == index + 1), word, ref index); - currentIndex = length; + return currentNode.GetLeftChild; } } -} + + void InsertInTree(TernaryTreeNode currentNode, string word, ref int currentIndex) + { + int length = word.Length; + + currentIndex++; + var currNode = currentNode; + for (int i = currentIndex; i < length; i++) + currNode = currNode.AddMiddleChild(word[i], word.Length == currentIndex + 1); + + currentIndex = length; + } +} \ No newline at end of file diff --git a/DataStructures/Trees/TernaryTreeNode.cs b/DataStructures/Trees/TernaryTreeNode.cs index 3c08c662..eb70a081 100644 --- a/DataStructures/Trees/TernaryTreeNode.cs +++ b/DataStructures/Trees/TernaryTreeNode.cs @@ -2,48 +2,47 @@ using System.Collections.Generic; using System.Text; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +public class TernaryTreeNode { - public class TernaryTreeNode - { - public virtual TernaryTreeNode Parent { get; private set; } - protected virtual TernaryTreeNode[] childs { get; set; } + public virtual TernaryTreeNode Parent { get; private set; } + protected virtual TernaryTreeNode[] childs { get; set; } - public virtual TernaryTreeNode GetLeftChild => childs[0]; - public virtual TernaryTreeNode GetMiddleChild => childs[1]; - public virtual TernaryTreeNode GetRightChild => childs[2]; + public virtual TernaryTreeNode GetLeftChild => childs[0]; + public virtual TernaryTreeNode GetMiddleChild => childs[1]; + public virtual TernaryTreeNode GetRightChild => childs[2]; - public virtual bool FinalLetter { get; set; } - public virtual char Value { get; set; } + public virtual bool FinalLetter { get; set; } + public virtual char Value { get; set; } - public TernaryTreeNode(TernaryTreeNode parent) - { - Parent = parent; - childs = new TernaryTreeNode[3]; - } + public TernaryTreeNode(TernaryTreeNode parent) + { + Parent = parent; + childs = new TernaryTreeNode[3]; + } - public TernaryTreeNode(TernaryTreeNode parent, char value, bool isFinal) - { - Parent = parent; - Value = value; - FinalLetter = isFinal; - childs = new TernaryTreeNode[3]; - } + public TernaryTreeNode(TernaryTreeNode parent, char value, bool isFinal) + { + Parent = parent; + Value = value; + FinalLetter = isFinal; + childs = new TernaryTreeNode[3]; + } - public virtual TernaryTreeNode AddLeftChild(char value, bool isFinal) - { - childs[0] = new TernaryTreeNode(this, value, isFinal); - return childs[0]; - } - public virtual TernaryTreeNode AddRightChild(char value, bool isFinal) - { - childs[2] = new TernaryTreeNode(this, value, isFinal); - return childs[2]; - } - public virtual TernaryTreeNode AddMiddleChild(char value, bool isFinal) - { - childs[1] = new TernaryTreeNode(this, value, isFinal); - return childs[1]; - } + public virtual TernaryTreeNode AddLeftChild(char value, bool isFinal) + { + childs[0] = new TernaryTreeNode(this, value, isFinal); + return childs[0]; + } + public virtual TernaryTreeNode AddRightChild(char value, bool isFinal) + { + childs[2] = new TernaryTreeNode(this, value, isFinal); + return childs[2]; + } + public virtual TernaryTreeNode AddMiddleChild(char value, bool isFinal) + { + childs[1] = new TernaryTreeNode(this, value, isFinal); + return childs[1]; } -} +} \ No newline at end of file diff --git a/DataStructures/Trees/TreeDrawer.cs b/DataStructures/Trees/TreeDrawer.cs index 518935ca..6f2e6e58 100644 --- a/DataStructures/Trees/TreeDrawer.cs +++ b/DataStructures/Trees/TreeDrawer.cs @@ -3,219 +3,218 @@ using System.Linq; using DataStructures.Common; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +public static class TreeDrawer { - public static class TreeDrawer + /// + /// Public API. + /// Extension method for BinarySearchTree. + /// Returns a visualized binary search tree text. + /// + public static string DrawTree(this IBinarySearchTree tree) where T : IComparable { - /// - /// Public API. - /// Extension method for BinarySearchTree. - /// Returns a visualized binary search tree text. - /// - public static string DrawTree(this IBinarySearchTree tree) where T : IComparable - { - int position, width; - return String.Join("\n", _recursivelyDrawTree(tree.Root, out position, out width)); - } + int position, width; + return String.Join("\n", _recursivelyDrawTree(tree.Root, out position, out width)); + } - public static string DrawTree(this IBinarySearchTree tree, bool includeValues = false) where TKey : IComparable + public static string DrawTree(this IBinarySearchTree tree, bool includeValues = false) where TKey : IComparable + { + int position, width; + return String.Join("\n", _recursivelyDrawTree(tree.Root, out position, out width, includeValues)); + } + + + /// + /// /// Recusively draws the tree starting from node. + /// To construct a full tree representation concatenate the returned list of strings by '\n'. + /// + /// Example: + /// int position, width; + /// var fullTree = String.Join("\n", _recursivelyDrawTree(this.Root, out position, out width)); + /// + /// Algorithm developed by MIT OCW. + /// http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/readings/binary-search-trees/bstsize_r.py + /// + /// + /// + /// + /// List of tree levels as strings. + private static List _recursivelyDrawTree + (BSTNode node, out int positionOutput, out int widthOutput) + where T : IComparable + { + widthOutput = 0; + positionOutput = 0; + + if (node == null) { - int position, width; - return String.Join("\n", _recursivelyDrawTree(tree.Root, out position, out width, includeValues)); + return new List(); } + // + // Variables + int leftPosition, rightPosition, leftWidth, rightWidth; - /// - /// /// Recusively draws the tree starting from node. - /// To construct a full tree representation concatenate the returned list of strings by '\n'. - /// - /// Example: - /// int position, width; - /// var fullTree = String.Join("\n", _recursivelyDrawTree(this.Root, out position, out width)); - /// - /// Algorithm developed by MIT OCW. - /// http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/readings/binary-search-trees/bstsize_r.py - /// - /// - /// - /// - /// List of tree levels as strings. - private static List _recursivelyDrawTree - (BSTNode node, out int positionOutput, out int widthOutput) - where T : IComparable - { - widthOutput = 0; - positionOutput = 0; + // + // Start drawing + var nodeLabel = Convert.ToString(node.Value); - if (node == null) - { - return new List(); - } + // Visit the left child + List leftLines = _recursivelyDrawTree(node.LeftChild, out leftPosition, out leftWidth); - // - // Variables - int leftPosition, rightPosition, leftWidth, rightWidth; + // Visit the right child + List rightLines = _recursivelyDrawTree(node.RightChild, out rightPosition, out rightWidth); - // - // Start drawing - var nodeLabel = Convert.ToString(node.Value); + // Calculate pads + int middle = Math.Max(Math.Max(2, nodeLabel.Length), rightPosition + leftWidth - leftPosition + 1); + int position_out = leftPosition + middle / 2; + int width_out = leftPosition + middle + rightWidth - rightPosition; - // Visit the left child - List leftLines = _recursivelyDrawTree(node.LeftChild, out leftPosition, out leftWidth); + while (leftLines.Count < rightLines.Count) + leftLines.Add(new String(' ', leftWidth)); - // Visit the right child - List rightLines = _recursivelyDrawTree(node.RightChild, out rightPosition, out rightWidth); + while (rightLines.Count < leftLines.Count) + rightLines.Add(new String(' ', rightWidth)); - // Calculate pads - int middle = Math.Max(Math.Max(2, nodeLabel.Length), rightPosition + leftWidth - leftPosition + 1); - int position_out = leftPosition + middle / 2; - int width_out = leftPosition + middle + rightWidth - rightPosition; + if (middle - nodeLabel.Length % 2 == 1 && nodeLabel.Length < middle && node.Parent != null && node.IsLeftChild) + nodeLabel += "."; - while (leftLines.Count < rightLines.Count) - leftLines.Add(new String(' ', leftWidth)); + // Format the node's label + nodeLabel = nodeLabel.PadCenter(middle, '.'); - while (rightLines.Count < leftLines.Count) - rightLines.Add(new String(' ', rightWidth)); + var nodeLabelChars = nodeLabel.ToCharArray(); - if (middle - nodeLabel.Length % 2 == 1 && nodeLabel.Length < middle && node.Parent != null && node.IsLeftChild) - nodeLabel += "."; + if (nodeLabelChars[0] == '.') + nodeLabelChars[0] = ' '; - // Format the node's label - nodeLabel = nodeLabel.PadCenter(middle, '.'); + if (nodeLabelChars[nodeLabelChars.Length - 1] == '.') + nodeLabelChars[nodeLabelChars.Length - 1] = ' '; - var nodeLabelChars = nodeLabel.ToCharArray(); + nodeLabel = String.Join("", nodeLabelChars); - if (nodeLabelChars[0] == '.') - nodeLabelChars[0] = ' '; + // + // Construct the list of lines. + string leftBranch = node.HasLeftChild ? "/" : " "; + string rightBranch = node.HasRightChild ? "\\" : " "; + + List listOfLines = new List() + { + // 0 + new String(' ', leftPosition ) + nodeLabel + new String(' ', rightWidth - rightPosition), + + // 1 + new String(' ', leftPosition) + leftBranch + new String(' ', middle - 2) + rightBranch + new String(' ', rightWidth - rightPosition) + }; + + // + // Add the right lines and left lines to the final list of lines. + listOfLines.AddRange(leftLines.Zip(rightLines, (leftLine, rightLine) => + leftLine + new String(' ', width_out - leftWidth - rightWidth) + rightLine)); + + // + // Return + widthOutput = width_out; + positionOutput = position_out; + return listOfLines; + } - if (nodeLabelChars[nodeLabelChars.Length - 1] == '.') - nodeLabelChars[nodeLabelChars.Length - 1] = ' '; - nodeLabel = String.Join("", nodeLabelChars); + private static List _recursivelyDrawTree + (BSTMapNode node, out int positionOutput, out int widthOutput, bool includeValues = false) + where TKey : IComparable + { + widthOutput = 0; + positionOutput = 0; + List listOfLines = new List(); - // - // Construct the list of lines. - string leftBranch = node.HasLeftChild ? "/" : " "; - string rightBranch = node.HasRightChild ? "\\" : " "; + if (node == null) + { + return listOfLines; + } - List listOfLines = new List() - { - // 0 - new String(' ', leftPosition ) + nodeLabel + new String(' ', rightWidth - rightPosition), + // + // Variables + string nodeLabel = ""; + int padValue = 0; - // 1 - new String(' ', leftPosition) + leftBranch + new String(' ', middle - 2) + rightBranch + new String(' ', rightWidth - rightPosition) - }; + List leftLines, rightLines; + leftLines = rightLines = new List(); - // - // Add the right lines and left lines to the final list of lines. - listOfLines.AddRange(leftLines.Zip(rightLines, (leftLine, rightLine) => - leftLine + new String(' ', width_out - leftWidth - rightWidth) + rightLine)); + int leftPosition = 0, rightPosition = 0; + int leftWidth = 0, rightWidth = 0; + int middle, position_out, width_out; - // - // Return - widthOutput = width_out; - positionOutput = position_out; - return listOfLines; + // + // Start drawing + if (includeValues == true) + { + nodeLabel = String.Format("<{0}: {1}>", Convert.ToString(node.Key), Convert.ToString(node.Value)); + padValue = 4; + } + else + { + nodeLabel = Convert.ToString(node.Key); + padValue = 2; } + // Visit the left child + leftLines = _recursivelyDrawTree(node.LeftChild, out leftPosition, out leftWidth, includeValues); + + // Visit the right child + rightLines = _recursivelyDrawTree(node.RightChild, out rightPosition, out rightWidth, includeValues); + + // Calculate pads + middle = Math.Max(Math.Max(padValue, nodeLabel.Length), rightPosition + leftWidth - leftPosition + 1); + position_out = leftPosition + middle; + width_out = leftPosition + middle + rightWidth - rightPosition; + + while (leftLines.Count < rightLines.Count) + leftLines.Add(new String(' ', leftWidth)); + + while (rightLines.Count < leftLines.Count) + rightLines.Add(new String(' ', rightWidth)); - private static List _recursivelyDrawTree - (BSTMapNode node, out int positionOutput, out int widthOutput, bool includeValues = false) - where TKey : IComparable + if (middle - nodeLabel.Length % padValue == 1 && nodeLabel.Length < middle && node.Parent != null && node.IsLeftChild) + nodeLabel += "."; + + // Format the node's label + nodeLabel = nodeLabel.PadCenter(middle, '.'); + + var nodeLabelChars = nodeLabel.ToCharArray(); + + if (nodeLabelChars[0] == '.') + nodeLabelChars[0] = ' '; + + if (nodeLabelChars[nodeLabelChars.Length - 1] == '.') + nodeLabelChars[nodeLabelChars.Length - 1] = ' '; + + nodeLabel = String.Join("", nodeLabelChars); + + // + // Construct the list of lines. + listOfLines = new List() { - widthOutput = 0; - positionOutput = 0; - List listOfLines = new List(); - - if (node == null) - { - return listOfLines; - } - - // - // Variables - string nodeLabel = ""; - int padValue = 0; - - List leftLines, rightLines; - leftLines = rightLines = new List(); - - int leftPosition = 0, rightPosition = 0; - int leftWidth = 0, rightWidth = 0; - int middle, position_out, width_out; - - // - // Start drawing - if (includeValues == true) - { - nodeLabel = String.Format("<{0}: {1}>", Convert.ToString(node.Key), Convert.ToString(node.Value)); - padValue = 4; - } - else - { - nodeLabel = Convert.ToString(node.Key); - padValue = 2; - } - - // Visit the left child - leftLines = _recursivelyDrawTree(node.LeftChild, out leftPosition, out leftWidth, includeValues); - - // Visit the right child - rightLines = _recursivelyDrawTree(node.RightChild, out rightPosition, out rightWidth, includeValues); - - // Calculate pads - middle = Math.Max(Math.Max(padValue, nodeLabel.Length), rightPosition + leftWidth - leftPosition + 1); - position_out = leftPosition + middle; - width_out = leftPosition + middle + rightWidth - rightPosition; - - while (leftLines.Count < rightLines.Count) - leftLines.Add(new String(' ', leftWidth)); - - while (rightLines.Count < leftLines.Count) - rightLines.Add(new String(' ', rightWidth)); - - if (middle - nodeLabel.Length % padValue == 1 && nodeLabel.Length < middle && node.Parent != null && node.IsLeftChild) - nodeLabel += "."; - - // Format the node's label - nodeLabel = nodeLabel.PadCenter(middle, '.'); - - var nodeLabelChars = nodeLabel.ToCharArray(); - - if (nodeLabelChars[0] == '.') - nodeLabelChars[0] = ' '; - - if (nodeLabelChars[nodeLabelChars.Length - 1] == '.') - nodeLabelChars[nodeLabelChars.Length - 1] = ' '; - - nodeLabel = String.Join("", nodeLabelChars); - - // - // Construct the list of lines. - listOfLines = new List() - { - // 0 - new String(' ', leftPosition ) + nodeLabel + new String(' ', rightWidth - rightPosition), - - // 1 - new String(' ', leftPosition) + "/" + new String(' ', middle - padValue) + "\\" + new String(' ', rightWidth - rightPosition) - }; - - // - // Add the right lines and left lines to the final list of lines. - listOfLines = - listOfLines.Concat( - leftLines.Zip( - rightLines, (left_line, right_line) => + // 0 + new String(' ', leftPosition ) + nodeLabel + new String(' ', rightWidth - rightPosition), + + // 1 + new String(' ', leftPosition) + "/" + new String(' ', middle - padValue) + "\\" + new String(' ', rightWidth - rightPosition) + }; + + // + // Add the right lines and left lines to the final list of lines. + listOfLines = + listOfLines.Concat( + leftLines.Zip( + rightLines, (left_line, right_line) => left_line + new String(' ', width_out - leftWidth - rightWidth) + right_line) - ).ToList(); + ).ToList(); - // - // Return - widthOutput = width_out; - positionOutput = position_out; - return listOfLines; - } + // + // Return + widthOutput = width_out; + positionOutput = position_out; + return listOfLines; } -} +} \ No newline at end of file diff --git a/DataStructures/Trees/Trie.cs b/DataStructures/Trees/Trie.cs index 641068b8..58fbbfd3 100644 --- a/DataStructures/Trees/Trie.cs +++ b/DataStructures/Trees/Trie.cs @@ -10,182 +10,180 @@ using System.Linq; using System.Collections.Generic; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// The vanila Trie implementation. +/// +public class Trie : IEnumerable { + private int _count { get; set; } + private TrieNode _root { get; set; } + /// - /// The vanila Trie implementation. + /// CONSTRUCTOR /// - public class Trie : IEnumerable + public Trie() { - private int _count { get; set; } - private TrieNode _root { get; set; } - - /// - /// CONSTRUCTOR - /// - public Trie() - { - _count = 0; - _root = new TrieNode(' ', false); - } + _count = 0; + _root = new TrieNode(' ', false); + } - /// - /// Return count of words. - /// - public int Count => _count; + /// + /// Return count of words. + /// + public int Count => _count; - /// - /// Checks if element is empty. - /// - public bool IsEmpty => _count == 0; + /// + /// Checks if element is empty. + /// + public bool IsEmpty => _count == 0; - /// - /// Add word to trie - /// - public void Add(string word) - { - if (string.IsNullOrEmpty(word)) - throw new ArgumentException("Word is empty or null."); + /// + /// Add word to trie + /// + public void Add(string word) + { + if (string.IsNullOrEmpty(word)) + throw new ArgumentException("Word is empty or null."); - var current = _root; + var current = _root; - for (int i = 0; i < word.Length; ++i) + for (int i = 0; i < word.Length; ++i) + { + if (!current.Children.ContainsKey(word[i])) { - if (!current.Children.ContainsKey(word[i])) - { - var newTrieNode = new TrieNode(word[i]); - newTrieNode.Parent = current; - current.Children.Add(word[i], newTrieNode); - } - - current = current.Children[word[i]]; + var newTrieNode = new TrieNode(word[i]); + newTrieNode.Parent = current; + current.Children.Add(word[i], newTrieNode); } - if (current.IsTerminal) - throw new InvalidOperationException("Word already exists in Trie."); - - ++_count; - current.IsTerminal = true; + current = current.Children[word[i]]; } - /// - /// Removes a word from the trie. - /// - public void Remove(string word) - { - if (string.IsNullOrEmpty(word)) - throw new ArgumentException("Word is empty or null."); + if (current.IsTerminal) + throw new InvalidOperationException("Word already exists in Trie."); - var current = _root; + ++_count; + current.IsTerminal = true; + } - for (int i = 0; i < word.Length; ++i) - { - if (!current.Children.ContainsKey(word[i])) - throw new KeyNotFoundException("Word doesn't belong to trie."); + /// + /// Removes a word from the trie. + /// + public void Remove(string word) + { + if (string.IsNullOrEmpty(word)) + throw new ArgumentException("Word is empty or null."); - current = current.Children[word[i]]; - } + var current = _root; - if (!current.IsTerminal) + for (int i = 0; i < word.Length; ++i) + { + if (!current.Children.ContainsKey(word[i])) throw new KeyNotFoundException("Word doesn't belong to trie."); - --_count; - current.Remove(); + current = current.Children[word[i]]; } - /// - /// Checks whether the trie has a specific word. - /// - public bool ContainsWord(string word) - { - if (string.IsNullOrEmpty(word)) - throw new InvalidOperationException("Word is either null or empty."); - - var current = _root; + if (!current.IsTerminal) + throw new KeyNotFoundException("Word doesn't belong to trie."); - for (int i = 0; i < word.Length; ++i) - { - if (!current.Children.ContainsKey(word[i])) - return false; + --_count; + current.Remove(); + } - current = current.Children[word[i]]; - } + /// + /// Checks whether the trie has a specific word. + /// + public bool ContainsWord(string word) + { + if (string.IsNullOrEmpty(word)) + throw new InvalidOperationException("Word is either null or empty."); - return current.IsTerminal; - } + var current = _root; - /// - /// Checks whether the trie has a specific prefix. - /// - public bool ContainsPrefix(string prefix) + for (int i = 0; i < word.Length; ++i) { - if (string.IsNullOrEmpty(prefix)) - throw new InvalidOperationException("Prefix is either null or empty."); + if (!current.Children.ContainsKey(word[i])) + return false; - var current = _root; + current = current.Children[word[i]]; + } - for (int i = 0; i < prefix.Length; ++i) - { - if (!current.Children.ContainsKey(prefix[i])) - return false; + return current.IsTerminal; + } - current = current.Children[prefix[i]]; - } + /// + /// Checks whether the trie has a specific prefix. + /// + public bool ContainsPrefix(string prefix) + { + if (string.IsNullOrEmpty(prefix)) + throw new InvalidOperationException("Prefix is either null or empty."); - return true; - } + var current = _root; - /// - /// Searches the entire trie for words that has a specific prefix. - /// - public IEnumerable SearchByPrefix(string prefix) + for (int i = 0; i < prefix.Length; ++i) { - if (string.IsNullOrEmpty(prefix)) - throw new InvalidOperationException("Prefix is either null or empty."); + if (!current.Children.ContainsKey(prefix[i])) + return false; - var current = _root; + current = current.Children[prefix[i]]; + } - for (int i = 0; i < prefix.Length; ++i) - { - if (!current.Children.ContainsKey(prefix[i])) - return null; + return true; + } - current = current.Children[prefix[i]]; - } + /// + /// Searches the entire trie for words that has a specific prefix. + /// + public IEnumerable SearchByPrefix(string prefix) + { + if (string.IsNullOrEmpty(prefix)) + throw new InvalidOperationException("Prefix is either null or empty."); - return current.GetByPrefix(); - } + var current = _root; - /// - /// Clears this insance. - /// - public void Clear() + for (int i = 0; i < prefix.Length; ++i) { - _count = 0; - _root.Clear(); - _root = new TrieNode(' ', false); + if (!current.Children.ContainsKey(prefix[i])) + return null; + + current = current.Children[prefix[i]]; } + return current.GetByPrefix(); + } - #region IEnumerable Implementation - /// - /// IEnumerable\.IEnumerator implementation. - /// - public IEnumerator GetEnumerator() - { - return _root.GetTerminalChildren().Select(node => node.Word).GetEnumerator(); - } + /// + /// Clears this insance. + /// + public void Clear() + { + _count = 0; + _root.Clear(); + _root = new TrieNode(' ', false); + } - /// - /// IEnumerable\.IEnumerator implementation. - /// - /// - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - #endregion IEnumerable Implementation + #region IEnumerable Implementation + /// + /// IEnumerable\.IEnumerator implementation. + /// + public IEnumerator GetEnumerator() + { + return _root.GetTerminalChildren().Select(node => node.Word).GetEnumerator(); + } + + /// + /// IEnumerable\.IEnumerator implementation. + /// + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); } + #endregion IEnumerable Implementation -} +} \ No newline at end of file diff --git a/DataStructures/Trees/TrieMap.cs b/DataStructures/Trees/TrieMap.cs index e872c16b..1488dce1 100644 --- a/DataStructures/Trees/TrieMap.cs +++ b/DataStructures/Trees/TrieMap.cs @@ -12,345 +12,342 @@ using System.Collections; using System.Collections.Generic; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// The Trie Map Data Structure (a.k.a Prefix Tree). +/// +/// The type of records attached to words +public class TrieMap : IDictionary, IEnumerable> { + private int _count { get; set; } + private TrieMapNode _root { get; set; } + private EqualityComparer _recordsComparer = EqualityComparer.Default; + /// - /// The Trie Map Data Structure (a.k.a Prefix Tree). + /// CONSTRUCTOR /// - /// The type of records attached to words - - public class TrieMap : IDictionary, IEnumerable> + public TrieMap() { - private int _count { get; set; } - private TrieMapNode _root { get; set; } - private EqualityComparer _recordsComparer = EqualityComparer.Default; - - /// - /// CONSTRUCTOR - /// - public TrieMap() - { - _count = 0; - _root = new TrieMapNode(' ', default, false); - } + _count = 0; + _root = new TrieMapNode(' ', default, false); + } - /// - /// Return count of words. - /// - public int Count => _count; + /// + /// Return count of words. + /// + public int Count => _count; - /// - /// Checks if element is empty. - /// - public bool IsEmpty => _count == 0; + /// + /// Checks if element is empty. + /// + public bool IsEmpty => _count == 0; - /// - /// Add word to trie - /// - public void Add(string word, TRecord record) - { - if (string.IsNullOrEmpty(word)) - throw new ArgumentException("Word is empty or null."); + /// + /// Add word to trie + /// + public void Add(string word, TRecord record) + { + if (string.IsNullOrEmpty(word)) + throw new ArgumentException("Word is empty or null."); - var current = _root; + var current = _root; - for (int i = 0; i < word.Length; ++i) + for (int i = 0; i < word.Length; ++i) + { + if (!current.Children.ContainsKey(word[i])) { - if (!current.Children.ContainsKey(word[i])) - { - var newTrieNode = new TrieMapNode(word[i], default); - newTrieNode.Parent = current; - current.Children.Add(word[i], newTrieNode); - } - - current = current.Children[word[i]]; + var newTrieNode = new TrieMapNode(word[i], default); + newTrieNode.Parent = current; + current.Children.Add(word[i], newTrieNode); } - if (current.IsTerminal) - throw new InvalidOperationException("Word already exists in Trie."); - - ++_count; - current.IsTerminal = true; - current.Record = record; + current = current.Children[word[i]]; } - /// - /// Updates a terminal word with a new record. Throws an exception if word was not found or if it is not a terminal word. - /// - public void UpdateWord(string word, TRecord newRecord) - { - if (string.IsNullOrEmpty(word)) - throw new InvalidOperationException("Word is either null or empty."); + if (current.IsTerminal) + throw new InvalidOperationException("Word already exists in Trie."); - var current = _root; + ++_count; + current.IsTerminal = true; + current.Record = record; + } - for (int i = 0; i < word.Length; ++i) - { - if (!current.Children.ContainsKey(word[i])) - throw new KeyNotFoundException("Word doesn't belong to trie."); + /// + /// Updates a terminal word with a new record. Throws an exception if word was not found or if it is not a terminal word. + /// + public void UpdateWord(string word, TRecord newRecord) + { + if (string.IsNullOrEmpty(word)) + throw new InvalidOperationException("Word is either null or empty."); - current = current.Children[word[i]]; - } + var current = _root; - if (!current.IsTerminal) + for (int i = 0; i < word.Length; ++i) + { + if (!current.Children.ContainsKey(word[i])) throw new KeyNotFoundException("Word doesn't belong to trie."); - current.Record = newRecord; + current = current.Children[word[i]]; } - /// - /// Removes a word from the trie. - /// - public void Remove(string word) - { - if (string.IsNullOrEmpty(word)) - throw new ArgumentException("Word is empty or null."); + if (!current.IsTerminal) + throw new KeyNotFoundException("Word doesn't belong to trie."); - var current = _root; + current.Record = newRecord; + } - for (int i = 0; i < word.Length; ++i) - { - if (!current.Children.ContainsKey(word[i])) - throw new KeyNotFoundException("Word doesn't belong to trie."); + /// + /// Removes a word from the trie. + /// + public void Remove(string word) + { + if (string.IsNullOrEmpty(word)) + throw new ArgumentException("Word is empty or null."); - current = current.Children[word[i]]; - } + var current = _root; - if (!current.IsTerminal) + for (int i = 0; i < word.Length; ++i) + { + if (!current.Children.ContainsKey(word[i])) throw new KeyNotFoundException("Word doesn't belong to trie."); - --_count; - current.Remove(); + current = current.Children[word[i]]; } - /// - /// Checks whether the trie has a specific word. - /// - public bool ContainsWord(string word) - { - TRecord record; - return SearchByWord(word, out record); - } + if (!current.IsTerminal) + throw new KeyNotFoundException("Word doesn't belong to trie."); - /// - /// Checks whether the trie has a specific prefix. - /// - public bool ContainsPrefix(string prefix) - { - if (string.IsNullOrEmpty(prefix)) - throw new InvalidOperationException("Prefix is either null or empty."); - - var current = _root; + --_count; + current.Remove(); + } - for (int i = 0; i < prefix.Length; ++i) - { - if (!current.Children.ContainsKey(prefix[i])) - return false; + /// + /// Checks whether the trie has a specific word. + /// + public bool ContainsWord(string word) + { + TRecord record; + return SearchByWord(word, out record); + } - current = current.Children[prefix[i]]; - } + /// + /// Checks whether the trie has a specific prefix. + /// + public bool ContainsPrefix(string prefix) + { + if (string.IsNullOrEmpty(prefix)) + throw new InvalidOperationException("Prefix is either null or empty."); - return true; - } + var current = _root; - /// - /// Searchs the trie for a word and returns the associated record, if found; otherwise returns false. - /// - public bool SearchByWord(string word, out TRecord record) + for (int i = 0; i < prefix.Length; ++i) { - if (string.IsNullOrEmpty(word)) - throw new InvalidOperationException("Word is either null or empty."); + if (!current.Children.ContainsKey(prefix[i])) + return false; - record = default; - var current = _root; + current = current.Children[prefix[i]]; + } - for (int i = 0; i < word.Length; ++i) - { - if (!current.Children.ContainsKey(word[i])) - return false; + return true; + } - current = current.Children[word[i]]; - } + /// + /// Searchs the trie for a word and returns the associated record, if found; otherwise returns false. + /// + public bool SearchByWord(string word, out TRecord record) + { + if (string.IsNullOrEmpty(word)) + throw new InvalidOperationException("Word is either null or empty."); + + record = default; + var current = _root; - if (!current.IsTerminal) + for (int i = 0; i < word.Length; ++i) + { + if (!current.Children.ContainsKey(word[i])) return false; - record = current.Record; - return true; + current = current.Children[word[i]]; } - /// - /// Searches the entire trie for words that has a specific prefix. - /// - public IEnumerable> SearchByPrefix(string prefix) - { - if (string.IsNullOrEmpty(prefix)) - throw new InvalidOperationException("Prefix is either null or empty."); + if (!current.IsTerminal) + return false; - var current = _root; + record = current.Record; + return true; + } - for (int i = 0; i < prefix.Length; ++i) - { - if (!current.Children.ContainsKey(prefix[i])) - return null; + /// + /// Searches the entire trie for words that has a specific prefix. + /// + public IEnumerable> SearchByPrefix(string prefix) + { + if (string.IsNullOrEmpty(prefix)) + throw new InvalidOperationException("Prefix is either null or empty."); - current = current.Children[prefix[i]]; - } + var current = _root; - return current.GetByPrefix(); - } - - /// - /// Clears this insance. - /// - public void Clear() + for (int i = 0; i < prefix.Length; ++i) { - _count = 0; - _root.Clear(); - _root = new TrieMapNode(' ', default, false); + if (!current.Children.ContainsKey(prefix[i])) + return null; + + current = current.Children[prefix[i]]; } + return current.GetByPrefix(); + } - #region IDictionary implementation - bool ICollection>.IsReadOnly => false; + /// + /// Clears this insance. + /// + public void Clear() + { + _count = 0; + _root.Clear(); + _root = new TrieMapNode(' ', default, false); + } - /// - /// Checks whether a specific key exists in trie as a word (terminal word). - /// - bool IDictionary.ContainsKey(string key) - { - TRecord record; - return SearchByWord(key, out record); - } - /// - /// Return all terminal words in trie. - /// - ICollection IDictionary.Keys + #region IDictionary implementation + bool ICollection>.IsReadOnly => false; + + /// + /// Checks whether a specific key exists in trie as a word (terminal word). + /// + bool IDictionary.ContainsKey(string key) + { + TRecord record; + return SearchByWord(key, out record); + } + + /// + /// Return all terminal words in trie. + /// + ICollection IDictionary.Keys + { + get { - get - { - var collection = new List(Count); + var collection = new List(Count); - var terminalNodes = _root.GetTerminalChildren(); - foreach (var node in terminalNodes) - collection.Add(node.Word); + var terminalNodes = _root.GetTerminalChildren(); + foreach (var node in terminalNodes) + collection.Add(node.Word); - return collection; - } + return collection; } + } - /// - /// Return all the associated records to terminal words. - /// - ICollection IDictionary.Values + /// + /// Return all the associated records to terminal words. + /// + ICollection IDictionary.Values + { + get { - get - { - var collection = new List(Count); + var collection = new List(Count); - var terminalNodes = _root.GetTerminalChildren(); - foreach (var node in terminalNodes) - collection.Add(node.Record); + var terminalNodes = _root.GetTerminalChildren(); + foreach (var node in terminalNodes) + collection.Add(node.Record); - return collection; - } + return collection; } + } - /// - /// Tries to get the associated record of a terminal word from trie. Returns false if key was not found. - /// - bool IDictionary.TryGetValue(string key, out TRecord value) - { - return SearchByWord(key, out value); - } + /// + /// Tries to get the associated record of a terminal word from trie. Returns false if key was not found. + /// + bool IDictionary.TryGetValue(string key, out TRecord value) + { + return SearchByWord(key, out value); + } - /// - /// Checks whether a specific word-record pair exists in trie. The key of item must be a terminal word not a prefix. - /// - bool ICollection>.Contains(KeyValuePair item) - { - TRecord record; - var status = SearchByWord(item.Key, out record); - return status == true && _recordsComparer.Equals(item.Value, record); - } + /// + /// Checks whether a specific word-record pair exists in trie. The key of item must be a terminal word not a prefix. + /// + bool ICollection>.Contains(KeyValuePair item) + { + TRecord record; + var status = SearchByWord(item.Key, out record); + return status == true && _recordsComparer.Equals(item.Value, record); + } - void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) - { - var tempArray = _root.GetTerminalChildren() - .Select, KeyValuePair>(item => new KeyValuePair(item.Word, item.Record)) - .ToArray(); + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + { + var tempArray = _root.GetTerminalChildren() + .Select, KeyValuePair>(item => new KeyValuePair(item.Word, item.Record)) + .ToArray(); - Array.Copy(tempArray, 0, array, arrayIndex, Count); - } + Array.Copy(tempArray, 0, array, arrayIndex, Count); + } - /// - /// Get/Set the associated record of a terminal word in trie. - /// - TRecord IDictionary.this[string key] + /// + /// Get/Set the associated record of a terminal word in trie. + /// + TRecord IDictionary.this[string key] + { + get { - get - { - TRecord record; - if (SearchByWord(key, out record)) - return record; - throw new KeyNotFoundException(); - } - set => UpdateWord(key, value); + TRecord record; + if (SearchByWord(key, out record)) + return record; + throw new KeyNotFoundException(); } + set => UpdateWord(key, value); + } - void ICollection>.Add(KeyValuePair item) - { - Add(item.Key, item.Value); - } + void ICollection>.Add(KeyValuePair item) + { + Add(item.Key, item.Value); + } - /// - /// Remove a word from trie. - /// - bool IDictionary.Remove(string key) + /// + /// Remove a word from trie. + /// + bool IDictionary.Remove(string key) + { + try { - try - { - Remove(word: key); - return true; - } - catch - { - return false; - } + Remove(word: key); + return true; } - - /// - /// Removes a word from trie. - /// - bool ICollection>.Remove(KeyValuePair item) + catch { - try - { - Remove(word: item.Key); - return true; - } - catch - { - return false; - } + return false; } - #endregion IDictionary implementation - + } - #region IEnumerable implementation - public IEnumerator> GetEnumerator() + /// + /// Removes a word from trie. + /// + bool ICollection>.Remove(KeyValuePair item) + { + try { - return _root.GetTerminalChildren() - .Select, KeyValuePair>(item => new KeyValuePair(item.Word, item.Record)) - .GetEnumerator(); + Remove(word: item.Key); + return true; } - - IEnumerator IEnumerable.GetEnumerator() + catch { - return GetEnumerator(); + return false; } - #endregion IEnumerable implementation } + #endregion IDictionary implementation -} + + #region IEnumerable implementation + public IEnumerator> GetEnumerator() + { + return _root.GetTerminalChildren() + .Select, KeyValuePair>(item => new KeyValuePair(item.Word, item.Record)) + .GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + #endregion IEnumerable implementation +} \ No newline at end of file diff --git a/DataStructures/Trees/TrieMapNode.cs b/DataStructures/Trees/TrieMapNode.cs index 6387da08..0172231c 100644 --- a/DataStructures/Trees/TrieMapNode.cs +++ b/DataStructures/Trees/TrieMapNode.cs @@ -1,128 +1,126 @@ using System; using System.Collections.Generic; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +public class TrieMapNode : IComparable> { - public class TrieMapNode : IComparable> - { - // Node key - public virtual char Key { get; set; } + // Node key + public virtual char Key { get; set; } - // Associated record with this node - public virtual TRecord Record { get; set; } + // Associated record with this node + public virtual TRecord Record { get; set; } - // Is Terminal node flag - public virtual bool IsTerminal { get; set; } + // Is Terminal node flag + public virtual bool IsTerminal { get; set; } - // Parent pointer - public virtual TrieMapNode Parent { get; set; } + // Parent pointer + public virtual TrieMapNode Parent { get; set; } - // Dictionary of child-nodes - public virtual Dictionary> Children { get; set; } + // Dictionary of child-nodes + public virtual Dictionary> Children { get; set; } - /// - /// CONSTRUCTORS - /// - public TrieMapNode(char key, TRecord record) : this(key, record, false) { } + /// + /// CONSTRUCTORS + /// + public TrieMapNode(char key, TRecord record) : this(key, record, false) { } - public TrieMapNode(char key, TRecord record, bool isTerminal) - { - Key = key; - Record = record; - IsTerminal = isTerminal; - Children = new Dictionary>(); - } + public TrieMapNode(char key, TRecord record, bool isTerminal) + { + Key = key; + Record = record; + IsTerminal = isTerminal; + Children = new Dictionary>(); + } - /// - /// Return the word at this node if the node is terminal; otherwise, return null - /// - public virtual string Word + /// + /// Return the word at this node if the node is terminal; otherwise, return null + /// + public virtual string Word + { + get { - get - { - if (!IsTerminal) - return null; - - var curr = this; - var stack = new Stack(); + if (!IsTerminal) + return null; - while(curr.Parent != null) - { - stack.Push(curr.Key); - curr = curr.Parent; - } + var curr = this; + var stack = new Stack(); - return new String(stack.ToArray()); + while(curr.Parent != null) + { + stack.Push(curr.Key); + curr = curr.Parent; } + return new String(stack.ToArray()); } - /// - /// Returns an enumerable list of key-value pairs of all the words that start - /// with the prefix that maps from the root node until this node. - /// - public virtual IEnumerable> GetByPrefix() - { - if (IsTerminal) - yield return new KeyValuePair(Word, Record); + } - foreach (var childKeyVal in Children) - foreach(var terminalNode in childKeyVal.Value.GetByPrefix()) - yield return terminalNode; - } + /// + /// Returns an enumerable list of key-value pairs of all the words that start + /// with the prefix that maps from the root node until this node. + /// + public virtual IEnumerable> GetByPrefix() + { + if (IsTerminal) + yield return new KeyValuePair(Word, Record); - /// - /// Returns an enumerable collection of terminal child nodes. - /// - public virtual IEnumerable> GetTerminalChildren() - { - foreach (var child in Children.Values) { - if(child.IsTerminal) - yield return child; + foreach (var childKeyVal in Children) + foreach(var terminalNode in childKeyVal.Value.GetByPrefix()) + yield return terminalNode; + } - foreach (var grandChild in child.GetTerminalChildren()) - if (grandChild.IsTerminal) - yield return grandChild; - } + /// + /// Returns an enumerable collection of terminal child nodes. + /// + public virtual IEnumerable> GetTerminalChildren() + { + foreach (var child in Children.Values) { + if(child.IsTerminal) + yield return child; + + foreach (var grandChild in child.GetTerminalChildren()) + if (grandChild.IsTerminal) + yield return grandChild; } + } - /// - /// Remove this element upto its parent. - /// - public virtual void Remove() - { - IsTerminal = false; + /// + /// Remove this element upto its parent. + /// + public virtual void Remove() + { + IsTerminal = false; - if(Children.Count == 0 && Parent != null) - { - Parent.Children.Remove(Key); + if(Children.Count == 0 && Parent != null) + { + Parent.Children.Remove(Key); - if (!Parent.IsTerminal) - Parent.Remove(); - } + if (!Parent.IsTerminal) + Parent.Remove(); } + } - /// - /// IComparer interface implementation - /// - public int CompareTo(TrieMapNode other) - { - if (other == null) - return -1; - - return Key.CompareTo(other.Key); + /// + /// IComparer interface implementation + /// + public int CompareTo(TrieMapNode other) + { + if (other == null) + return -1; - } + return Key.CompareTo(other.Key); - /// - /// Clears this node instance - /// - public void Clear() - { - Children.Clear(); - Children = null; - } } -} + /// + /// Clears this node instance + /// + public void Clear() + { + Children.Clear(); + Children = null; + } +} \ No newline at end of file diff --git a/DataStructures/Trees/TrieNode.cs b/DataStructures/Trees/TrieNode.cs index 5b43eb9a..56ffb7d3 100644 --- a/DataStructures/Trees/TrieNode.cs +++ b/DataStructures/Trees/TrieNode.cs @@ -1,121 +1,120 @@ using System; using System.Collections.Generic; -namespace DataStructures.Trees +namespace DataStructures.Trees; + +/// +/// The Trie Node. +/// +public class TrieNode { /// - /// The Trie Node. + /// Instance variables. + /// + public virtual char Key { get; set; } + public virtual bool IsTerminal { get; set; } + public virtual TrieNode Parent { get; set; } + public virtual Dictionary Children { get; set; } + + /// + /// CONSTRUCTORS /// - public class TrieNode + public TrieNode(char key) : this(key, false) { } + + public TrieNode(char key, bool isTerminal) { - /// - /// Instance variables. - /// - public virtual char Key { get; set; } - public virtual bool IsTerminal { get; set; } - public virtual TrieNode Parent { get; set; } - public virtual Dictionary Children { get; set; } - - /// - /// CONSTRUCTORS - /// - public TrieNode(char key) : this(key, false) { } - - public TrieNode(char key, bool isTerminal) - { - Key = key; - IsTerminal = isTerminal; - Children = new Dictionary(); - } + Key = key; + IsTerminal = isTerminal; + Children = new Dictionary(); + } - /// - /// Return the word at this node if the node is terminal; otherwise, return null - /// - public virtual string Word + /// + /// Return the word at this node if the node is terminal; otherwise, return null + /// + public virtual string Word + { + get { - get - { - if (!IsTerminal) - return null; + if (!IsTerminal) + return null; - var curr = this; - var stack = new Stack(); + var curr = this; + var stack = new Stack(); - while(curr.Parent != null) - { - stack.Push(curr.Key); - curr = curr.Parent; - } - - return new String(stack.ToArray()); + while(curr.Parent != null) + { + stack.Push(curr.Key); + curr = curr.Parent; } + return new String(stack.ToArray()); } - /// - /// Returns an enumerable list of key-value pairs of all the words that start - /// with the prefix that maps from the root node until this node. - /// - public virtual IEnumerable GetByPrefix() - { - if (IsTerminal) - yield return Word; + } - foreach (var childKeyVal in Children) - foreach(var terminalNode in childKeyVal.Value.GetByPrefix()) - yield return terminalNode; - } + /// + /// Returns an enumerable list of key-value pairs of all the words that start + /// with the prefix that maps from the root node until this node. + /// + public virtual IEnumerable GetByPrefix() + { + if (IsTerminal) + yield return Word; - /// - /// Returns an enumerable collection of terminal child nodes. - /// - public virtual IEnumerable GetTerminalChildren() - { - foreach (var child in Children.Values) { - if(child.IsTerminal) - yield return child; + foreach (var childKeyVal in Children) + foreach(var terminalNode in childKeyVal.Value.GetByPrefix()) + yield return terminalNode; + } - foreach (var grandChild in child.GetTerminalChildren()) - if (grandChild.IsTerminal) - yield return grandChild; - } + /// + /// Returns an enumerable collection of terminal child nodes. + /// + public virtual IEnumerable GetTerminalChildren() + { + foreach (var child in Children.Values) { + if(child.IsTerminal) + yield return child; + + foreach (var grandChild in child.GetTerminalChildren()) + if (grandChild.IsTerminal) + yield return grandChild; } + } - /// - /// Remove this element upto its parent. - /// - public virtual void Remove() - { - IsTerminal = false; + /// + /// Remove this element upto its parent. + /// + public virtual void Remove() + { + IsTerminal = false; - if(Children.Count == 0 && Parent != null) - { - Parent.Children.Remove(Key); + if(Children.Count == 0 && Parent != null) + { + Parent.Children.Remove(Key); - if (!Parent.IsTerminal) - Parent.Remove(); - } + if (!Parent.IsTerminal) + Parent.Remove(); } + } - /// - /// IComparer interface implementation - /// - public int CompareTo(TrieNode other) - { - if (other == null) - return -1; + /// + /// IComparer interface implementation + /// + public int CompareTo(TrieNode other) + { + if (other == null) + return -1; - return Key.CompareTo(other.Key); + return Key.CompareTo(other.Key); - } + } - /// - /// Clears this node instance - /// - public void Clear() - { - Children.Clear(); - Children = null; - } + /// + /// Clears this node instance + /// + public void Clear() + { + Children.Clear(); + Children = null; } -} +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/BinarySearchTreeSorterTest.cs b/UnitTest/AlgorithmsTests/BinarySearchTreeSorterTest.cs index 83193bb5..dc735300 100644 --- a/UnitTest/AlgorithmsTests/BinarySearchTreeSorterTest.cs +++ b/UnitTest/AlgorithmsTests/BinarySearchTreeSorterTest.cs @@ -3,18 +3,17 @@ using System.Linq; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public class BinarySearchTreeSorterTest { - public class BinarySearchTreeSorterTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - var expectedSort = new List { 0, 2, 3, 4, 8, 9, 12, 15, 16, 23, 25, 34, 42, 46, 55 }; - var numbers = new List { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; - numbers.UnbalancedBSTSort(); + var expectedSort = new List { 0, 2, 3, 4, 8, 9, 12, 15, 16, 23, 25, 34, 42, 46, 55 }; + var numbers = new List { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; + numbers.UnbalancedBSTSort(); - Assert.True(numbers.SequenceEqual(expectedSort)); - } + Assert.True(numbers.SequenceEqual(expectedSort)); } } \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/BinarySearcherTest.cs b/UnitTest/AlgorithmsTests/BinarySearcherTest.cs index 1bd7f318..97f136e2 100644 --- a/UnitTest/AlgorithmsTests/BinarySearcherTest.cs +++ b/UnitTest/AlgorithmsTests/BinarySearcherTest.cs @@ -2,80 +2,79 @@ using Xunit; using Algorithms.Search; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class BinarySearcherTest { - public static class BinarySearcherTest + [Fact] + public static void IntBinarySearchTest() { - [Fact] - public static void IntBinarySearchTest() - { - //list of ints - IList list = new List { 9, 3, 7, 1, 6, 10 }; - IList sortedList = new List { 1, 3, 6, 7, 9, 10 }; - int numToSearch = 6; - BinarySearcher intSearcher = new BinarySearcher(list, Comparer.Default); - int actualIndex = intSearcher.BinarySearch(numToSearch); - int expectedIndex = sortedList.IndexOf(numToSearch); + //list of ints + IList list = new List { 9, 3, 7, 1, 6, 10 }; + IList sortedList = new List { 1, 3, 6, 7, 9, 10 }; + int numToSearch = 6; + BinarySearcher intSearcher = new BinarySearcher(list, Comparer.Default); + int actualIndex = intSearcher.BinarySearch(numToSearch); + int expectedIndex = sortedList.IndexOf(numToSearch); - Assert.Equal(expectedIndex, actualIndex); - Assert.Equal(numToSearch, intSearcher.Current); + Assert.Equal(expectedIndex, actualIndex); + Assert.Equal(numToSearch, intSearcher.Current); - numToSearch = 20; - int itemNotExists = intSearcher.BinarySearch(numToSearch); - Assert.Equal(-1, itemNotExists); - } + numToSearch = 20; + int itemNotExists = intSearcher.BinarySearch(numToSearch); + Assert.Equal(-1, itemNotExists); + } - [Fact] - public static void StringBinarySearchTest() - { - //list of strings - IList animals = new List { "lion", "cat", "tiger", "bee", "sparrow" }; - IList sortedAnimals = new List { "bee", "cat", "lion", "sparrow", "tiger" }; - string itemToSearch = "bee"; - BinarySearcher strSearcher = new BinarySearcher(animals, Comparer.Default); - int actualIndex = strSearcher.BinarySearch(itemToSearch); - int expectedAnimalIndex = sortedAnimals.IndexOf(itemToSearch); + [Fact] + public static void StringBinarySearchTest() + { + //list of strings + IList animals = new List { "lion", "cat", "tiger", "bee", "sparrow" }; + IList sortedAnimals = new List { "bee", "cat", "lion", "sparrow", "tiger" }; + string itemToSearch = "bee"; + BinarySearcher strSearcher = new BinarySearcher(animals, Comparer.Default); + int actualIndex = strSearcher.BinarySearch(itemToSearch); + int expectedAnimalIndex = sortedAnimals.IndexOf(itemToSearch); - Assert.Equal(expectedAnimalIndex, actualIndex); - Assert.Equal(itemToSearch, strSearcher.Current); + Assert.Equal(expectedAnimalIndex, actualIndex); + Assert.Equal(itemToSearch, strSearcher.Current); - itemToSearch = "shark"; - int itemNotExist = strSearcher.BinarySearch(itemToSearch); - Assert.Equal(-1, itemNotExist); - } + itemToSearch = "shark"; + int itemNotExist = strSearcher.BinarySearch(itemToSearch); + Assert.Equal(-1, itemNotExist); + } - [Fact] - public static void MoveNextTest() + [Fact] + public static void MoveNextTest() + { + IList items = new List {3, 5, 2, 6, 1, 4}; + BinarySearcher searcher = new BinarySearcher(items, Comparer.Default); + searcher.BinarySearch(1); + //reset indices to test MoveNext() + searcher.Reset(); + IList leftEnumeratedValues = new List {3, 2, 1}; + int i = 0; + while (searcher.MoveNext()) { - IList items = new List {3, 5, 2, 6, 1, 4}; - BinarySearcher searcher = new BinarySearcher(items, Comparer.Default); - searcher.BinarySearch(1); - //reset indices to test MoveNext() - searcher.Reset(); - IList leftEnumeratedValues = new List {3, 2, 1}; - int i = 0; - while (searcher.MoveNext()) - { - Assert.Equal(leftEnumeratedValues[i++], searcher.Current); - } - - searcher.BinarySearch(6); - //reset indices to test MoveNext() - searcher.Reset(); - IList rightEnumeratedValues = new List {3, 5, 6}; - i = 0; - while (searcher.MoveNext()) - { - Assert.Equal(rightEnumeratedValues[i++], searcher.Current); - } - + Assert.Equal(leftEnumeratedValues[i++], searcher.Current); } - [Fact] - public static void NullCollectionExceptionTest() + searcher.BinarySearch(6); + //reset indices to test MoveNext() + searcher.Reset(); + IList rightEnumeratedValues = new List {3, 5, 6}; + i = 0; + while (searcher.MoveNext()) { - IList list = null; - Assert.Throws(() => new BinarySearcher(list, Comparer.Default)); + Assert.Equal(rightEnumeratedValues[i++], searcher.Current); } + + } + + [Fact] + public static void NullCollectionExceptionTest() + { + IList list = null; + Assert.Throws(() => new BinarySearcher(list, Comparer.Default)); } } \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/BinaryTreeRecursiveWalkerTests.cs b/UnitTest/AlgorithmsTests/BinaryTreeRecursiveWalkerTests.cs index 15024860..cc90331c 100644 --- a/UnitTest/AlgorithmsTests/BinaryTreeRecursiveWalkerTests.cs +++ b/UnitTest/AlgorithmsTests/BinaryTreeRecursiveWalkerTests.cs @@ -5,183 +5,182 @@ using System.Linq; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class BinaryTreeRecursiveWalkerTests { - public static class BinaryTreeRecursiveWalkerTests + // Construct a Simple Binary Search Tree + private static readonly BSTNode Root = new BSTNode(10) { - // Construct a Simple Binary Search Tree - private static readonly BSTNode Root = new BSTNode(10) + LeftChild = new BSTNode(5) { - LeftChild = new BSTNode(5) - { - LeftChild = new BSTNode(3), - RightChild = new BSTNode(7) - }, - RightChild = new BSTNode(15) - { - LeftChild = new BSTNode(13), - RightChild = new BSTNode(17) - } - }; + LeftChild = new BSTNode(3), + RightChild = new BSTNode(7) + }, + RightChild = new BSTNode(15) + { + LeftChild = new BSTNode(13), + RightChild = new BSTNode(17) + } + }; - #region <> + #region <> - [Fact] - private static void TestPreOrderTraversal() - { - var preOrder = BinaryTreeRecursiveWalker.TraversalMode.PreOrder; + [Fact] + private static void TestPreOrderTraversal() + { + var preOrder = BinaryTreeRecursiveWalker.TraversalMode.PreOrder; - // List to contain items - List list = new List(); + // List to contain items + List list = new List(); - // ForEach Action - var addToList = new Action(list.Add); + // ForEach Action + var addToList = new Action(list.Add); - // Assert the fact that adding items PRE-ORDER will result in [3, 5, 7, 10, 13, 15, 17] - BinaryTreeRecursiveWalker.ForEach(Root, addToList, preOrder); - var expectedArray = new[] { 10, 5, 3, 7, 15, 13, 17 }; - for (int i = 0; i < list.Count; i++) + // Assert the fact that adding items PRE-ORDER will result in [3, 5, 7, 10, 13, 15, 17] + BinaryTreeRecursiveWalker.ForEach(Root, addToList, preOrder); + var expectedArray = new[] { 10, 5, 3, 7, 15, 13, 17 }; + for (int i = 0; i < list.Count; i++) + { + if (list[i] != expectedArray[i]) { - if (list[i] != expectedArray[i]) - { - throw new InvalidOperationException("Wrong traversal, expected PreOrder enumeration of tree!"); - } + throw new InvalidOperationException("Wrong traversal, expected PreOrder enumeration of tree!"); } } + } - [Fact] - private static void TestInOrderTraversal() - { - var inOrder = BinaryTreeRecursiveWalker.TraversalMode.InOrder; + [Fact] + private static void TestInOrderTraversal() + { + var inOrder = BinaryTreeRecursiveWalker.TraversalMode.InOrder; - // List to contain items - var list = new List(); + // List to contain items + var list = new List(); - // ForEach Action - var addToList = new Action(list.Add); + // ForEach Action + var addToList = new Action(list.Add); - // Assert the fact that adding items IN-ORDER will result in [10, 5, 3, 7, 15, 13, 17] - BinaryTreeRecursiveWalker.ForEach(Root, addToList, inOrder); + // Assert the fact that adding items IN-ORDER will result in [10, 5, 3, 7, 15, 13, 17] + BinaryTreeRecursiveWalker.ForEach(Root, addToList, inOrder); - var expectedArray = new[] { 3, 5, 7, 10, 13, 15, 17 }; - for (int i = 0; i < list.Count; i++) + var expectedArray = new[] { 3, 5, 7, 10, 13, 15, 17 }; + for (int i = 0; i < list.Count; i++) + { + if (list[i] != expectedArray[i]) { - if (list[i] != expectedArray[i]) - { - throw new InvalidOperationException("Wrong traversal, expected InOrder enumeration of tree!"); - } + throw new InvalidOperationException("Wrong traversal, expected InOrder enumeration of tree!"); } } + } - [Fact] - private static void TestPostOrderTraversal() - { - var postOrder = BinaryTreeRecursiveWalker.TraversalMode.PostOrder; - - // List to contain items - List list = new List(); + [Fact] + private static void TestPostOrderTraversal() + { + var postOrder = BinaryTreeRecursiveWalker.TraversalMode.PostOrder; - // ForEach Action - var addToList = new Action(list.Add); + // List to contain items + List list = new List(); - // Assert the fact that adding items POST-ORDER will result in [3, 7, 5, 13, 17, 15, 10] - BinaryTreeRecursiveWalker.ForEach(Root, addToList, postOrder); - Assert.True(list.SequenceEqual(new[] { 3, 7, 5, 13, 17, 15, 10 }), - "Wrong traversal, expected InOrder enumeration of tree!"); - } + // ForEach Action + var addToList = new Action(list.Add); - #endregion + // Assert the fact that adding items POST-ORDER will result in [3, 7, 5, 13, 17, 15, 10] + BinaryTreeRecursiveWalker.ForEach(Root, addToList, postOrder); + Assert.True(list.SequenceEqual(new[] { 3, 7, 5, 13, 17, 15, 10 }), + "Wrong traversal, expected InOrder enumeration of tree!"); + } - #region <> + #endregion - [Fact] - private static void TestContainReturnsTrue() - { - var values = new[] { 10, 5, 3, 7, 15, 13, 17 }; - var preOrder = BinaryTreeRecursiveWalker.TraversalMode.PreOrder; - var inOrder = BinaryTreeRecursiveWalker.TraversalMode.InOrder; - var postOrder = BinaryTreeRecursiveWalker.TraversalMode.PostOrder; - - foreach (var value in values) - Assert.True(BinaryTreeRecursiveWalker.Contains(Root, value, preOrder), - "Wrong boolean returned, expected True from Contains"); - - foreach (var value in values) - Assert.True(BinaryTreeRecursiveWalker.Contains(Root, value, inOrder), - "Wrong boolean returned, expected True from Contains"); - - foreach (var value in values) - Assert.True(BinaryTreeRecursiveWalker.Contains(Root, value, postOrder), - "Wrong boolean returned, expected True from Contains"); - } + #region <> - [Fact] - private static void TestContainReturnsFalse() - { - var values = new[] { 0, 20, 30, 40, 50 }; - var preOrder = BinaryTreeRecursiveWalker.TraversalMode.PreOrder; - var inOrder = BinaryTreeRecursiveWalker.TraversalMode.InOrder; - var postOrder = BinaryTreeRecursiveWalker.TraversalMode.PostOrder; - - foreach (var value in values) - Assert.False(BinaryTreeRecursiveWalker.Contains(Root, value, preOrder), - "Wrong boolean returned, expected False from Contains"); - - foreach (var value in values) - Assert.False(BinaryTreeRecursiveWalker.Contains(Root, value, inOrder), - "Wrong boolean returned, expected False from Contains"); - - foreach (var value in values) - Assert.False(BinaryTreeRecursiveWalker.Contains(Root, value, postOrder), - "Wrong boolean returned, expected False from Contains"); - } + [Fact] + private static void TestContainReturnsTrue() + { + var values = new[] { 10, 5, 3, 7, 15, 13, 17 }; + var preOrder = BinaryTreeRecursiveWalker.TraversalMode.PreOrder; + var inOrder = BinaryTreeRecursiveWalker.TraversalMode.InOrder; + var postOrder = BinaryTreeRecursiveWalker.TraversalMode.PostOrder; + + foreach (var value in values) + Assert.True(BinaryTreeRecursiveWalker.Contains(Root, value, preOrder), + "Wrong boolean returned, expected True from Contains"); + + foreach (var value in values) + Assert.True(BinaryTreeRecursiveWalker.Contains(Root, value, inOrder), + "Wrong boolean returned, expected True from Contains"); + + foreach (var value in values) + Assert.True(BinaryTreeRecursiveWalker.Contains(Root, value, postOrder), + "Wrong boolean returned, expected True from Contains"); + } - #endregion + [Fact] + private static void TestContainReturnsFalse() + { + var values = new[] { 0, 20, 30, 40, 50 }; + var preOrder = BinaryTreeRecursiveWalker.TraversalMode.PreOrder; + var inOrder = BinaryTreeRecursiveWalker.TraversalMode.InOrder; + var postOrder = BinaryTreeRecursiveWalker.TraversalMode.PostOrder; + + foreach (var value in values) + Assert.False(BinaryTreeRecursiveWalker.Contains(Root, value, preOrder), + "Wrong boolean returned, expected False from Contains"); + + foreach (var value in values) + Assert.False(BinaryTreeRecursiveWalker.Contains(Root, value, inOrder), + "Wrong boolean returned, expected False from Contains"); + + foreach (var value in values) + Assert.False(BinaryTreeRecursiveWalker.Contains(Root, value, postOrder), + "Wrong boolean returned, expected False from Contains"); + } - #region <> + #endregion - [Fact] - private static void TestBinarySearchReturnsTrue() - { - var values = new[] { 10, 5, 3, 7, 15, 13, 17 }; - var preOrder = BinaryTreeRecursiveWalker.TraversalMode.PreOrder; - var inOrder = BinaryTreeRecursiveWalker.TraversalMode.InOrder; - var postOrder = BinaryTreeRecursiveWalker.TraversalMode.PostOrder; - - foreach (var value in values) - Assert.True(BinaryTreeRecursiveWalker.BinarySearch(Root, value, preOrder), - "Wrong boolean returned, expected True from Contains"); - - foreach (var value in values) - Assert.True(BinaryTreeRecursiveWalker.BinarySearch(Root, value, inOrder), - "Wrong boolean returned, expected True from Contains"); - - foreach (var value in values) - Assert.True(BinaryTreeRecursiveWalker.BinarySearch(Root, value, postOrder), - "Wrong boolean returned, expected True from Contains"); - } + #region <> - [Fact] - private static void TestBinarySearchReturnsFalse() - { - var values = new[] { 0, 20, 30, 40, 50 }; - var preOrder = BinaryTreeRecursiveWalker.TraversalMode.PreOrder; - var inOrder = BinaryTreeRecursiveWalker.TraversalMode.InOrder; - var postOrder = BinaryTreeRecursiveWalker.TraversalMode.PostOrder; - - foreach (var value in values) - Assert.False(BinaryTreeRecursiveWalker.BinarySearch(Root, value, preOrder), - "Wrong boolean returned, expected False from Contains"); - - foreach (var value in values) - Assert.False(BinaryTreeRecursiveWalker.BinarySearch(Root, value, inOrder), - "Wrong boolean returned, expected False from Contains"); - - foreach (var value in values) - Assert.False(BinaryTreeRecursiveWalker.BinarySearch(Root, value, postOrder), - "Wrong boolean returned, expected False from Contains"); - } + [Fact] + private static void TestBinarySearchReturnsTrue() + { + var values = new[] { 10, 5, 3, 7, 15, 13, 17 }; + var preOrder = BinaryTreeRecursiveWalker.TraversalMode.PreOrder; + var inOrder = BinaryTreeRecursiveWalker.TraversalMode.InOrder; + var postOrder = BinaryTreeRecursiveWalker.TraversalMode.PostOrder; + + foreach (var value in values) + Assert.True(BinaryTreeRecursiveWalker.BinarySearch(Root, value, preOrder), + "Wrong boolean returned, expected True from Contains"); + + foreach (var value in values) + Assert.True(BinaryTreeRecursiveWalker.BinarySearch(Root, value, inOrder), + "Wrong boolean returned, expected True from Contains"); + + foreach (var value in values) + Assert.True(BinaryTreeRecursiveWalker.BinarySearch(Root, value, postOrder), + "Wrong boolean returned, expected True from Contains"); + } - #endregion + [Fact] + private static void TestBinarySearchReturnsFalse() + { + var values = new[] { 0, 20, 30, 40, 50 }; + var preOrder = BinaryTreeRecursiveWalker.TraversalMode.PreOrder; + var inOrder = BinaryTreeRecursiveWalker.TraversalMode.InOrder; + var postOrder = BinaryTreeRecursiveWalker.TraversalMode.PostOrder; + + foreach (var value in values) + Assert.False(BinaryTreeRecursiveWalker.BinarySearch(Root, value, preOrder), + "Wrong boolean returned, expected False from Contains"); + + foreach (var value in values) + Assert.False(BinaryTreeRecursiveWalker.BinarySearch(Root, value, inOrder), + "Wrong boolean returned, expected False from Contains"); + + foreach (var value in values) + Assert.False(BinaryTreeRecursiveWalker.BinarySearch(Root, value, postOrder), + "Wrong boolean returned, expected False from Contains"); } + + #endregion } \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/BubbleSorterTest.cs b/UnitTest/AlgorithmsTests/BubbleSorterTest.cs index 9dfbcf3c..09d23e16 100644 --- a/UnitTest/AlgorithmsTests/BubbleSorterTest.cs +++ b/UnitTest/AlgorithmsTests/BubbleSorterTest.cs @@ -3,19 +3,18 @@ using System.Linq; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class BubbleSorterTest { - public static class BubbleSorterTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - var list = new List() { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; - list.BubbleSort(); - Assert.True(list.SequenceEqual(list.OrderBy(x => x)), "Wrong BubbleSort ascending"); + var list = new List() { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; + list.BubbleSort(); + Assert.True(list.SequenceEqual(list.OrderBy(x => x)), "Wrong BubbleSort ascending"); - list.BubbleSortDescending(Comparer.Default); - Assert.True(list.SequenceEqual(list.OrderByDescending(x => x)), "Wrong BubbleSort descending"); - } + list.BubbleSortDescending(Comparer.Default); + Assert.True(list.SequenceEqual(list.OrderByDescending(x => x)), "Wrong BubbleSort descending"); } -} +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/CatalanNumbersTest.cs b/UnitTest/AlgorithmsTests/CatalanNumbersTest.cs index 8726422c..7b26d009 100644 --- a/UnitTest/AlgorithmsTests/CatalanNumbersTest.cs +++ b/UnitTest/AlgorithmsTests/CatalanNumbersTest.cs @@ -3,67 +3,66 @@ using Algorithms.Numeric; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public class CatalanNumbersTest { - public class CatalanNumbersTest + [Fact] + public void DoTest() { - [Fact] - public void DoTest() - { - var list = CatalanNumbers.GetRange(0, 100); - var list2 = new List(); + var list = CatalanNumbers.GetRange(0, 100); + var list2 = new List(); - // TRY CALCULATING FROM Bin.Coeff. - for (uint i = 0; i < list.Count; ++i) - { - var catalanNumber = CatalanNumbers.GetNumberByBinomialCoefficients(i); - list2.Add(catalanNumber); + // TRY CALCULATING FROM Bin.Coeff. + for (uint i = 0; i < list.Count; ++i) + { + var catalanNumber = CatalanNumbers.GetNumberByBinomialCoefficients(i); + list2.Add(catalanNumber); - Assert.True(list[(int)i] == list2[(int)i], "Wrong calculation."); - } + Assert.True(list[(int)i] == list2[(int)i], "Wrong calculation."); } + } - // Values retrieved from https://oeis.org/A000108/list. - [Theory] - [InlineData(0, "1")] - [InlineData(1, "1")] - [InlineData(2, "2")] - [InlineData(3, "5")] - [InlineData(4, "14")] - [InlineData(5, "42")] - [InlineData(6, "132")] - [InlineData(7, "429")] - [InlineData(8, "1430")] - [InlineData(9, "4862")] - [InlineData(10, "16796")] - [InlineData(11, "58786")] - [InlineData(12, "208012")] - [InlineData(13, "742900")] - [InlineData(14, "2674440")] - [InlineData(15, "9694845")] - [InlineData(16, "35357670")] - [InlineData(17, "129644790")] - [InlineData(18, "477638700")] - [InlineData(19, "1767263190")] - [InlineData(20, "6564120420")] - [InlineData(21, "24466267020")] - [InlineData(22, "91482563640")] - [InlineData(23, "343059613650")] - [InlineData(24, "1289904147324")] - [InlineData(25, "4861946401452")] - [InlineData(26, "18367353072152")] - [InlineData(27, "69533550916004")] - [InlineData(28, "263747951750360")] - [InlineData(29, "1002242216651368")] - [InlineData(30, "3814986502092304")] - public void ManuallyVerifyCatalanNumber(uint rank, string value) - { - // This conversion seems to be necessary because as of this - // writing xunit doesn't behave well with BigInteger inline - // data values. - var bigint = BigInteger.Parse(value); + // Values retrieved from https://oeis.org/A000108/list. + [Theory] + [InlineData(0, "1")] + [InlineData(1, "1")] + [InlineData(2, "2")] + [InlineData(3, "5")] + [InlineData(4, "14")] + [InlineData(5, "42")] + [InlineData(6, "132")] + [InlineData(7, "429")] + [InlineData(8, "1430")] + [InlineData(9, "4862")] + [InlineData(10, "16796")] + [InlineData(11, "58786")] + [InlineData(12, "208012")] + [InlineData(13, "742900")] + [InlineData(14, "2674440")] + [InlineData(15, "9694845")] + [InlineData(16, "35357670")] + [InlineData(17, "129644790")] + [InlineData(18, "477638700")] + [InlineData(19, "1767263190")] + [InlineData(20, "6564120420")] + [InlineData(21, "24466267020")] + [InlineData(22, "91482563640")] + [InlineData(23, "343059613650")] + [InlineData(24, "1289904147324")] + [InlineData(25, "4861946401452")] + [InlineData(26, "18367353072152")] + [InlineData(27, "69533550916004")] + [InlineData(28, "263747951750360")] + [InlineData(29, "1002242216651368")] + [InlineData(30, "3814986502092304")] + public void ManuallyVerifyCatalanNumber(uint rank, string value) + { + // This conversion seems to be necessary because as of this + // writing xunit doesn't behave well with BigInteger inline + // data values. + var bigint = BigInteger.Parse(value); - Assert.True(CatalanNumbers.GetNumber(rank) == bigint); - } + Assert.True(CatalanNumbers.GetNumber(rank) == bigint); } } \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/CountingSortTest.cs b/UnitTest/AlgorithmsTests/CountingSortTest.cs index 79e159e5..d21f04cd 100644 --- a/UnitTest/AlgorithmsTests/CountingSortTest.cs +++ b/UnitTest/AlgorithmsTests/CountingSortTest.cs @@ -2,16 +2,15 @@ using System.Linq; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class CountingSortTest { - public static class CountingSortTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - int[] numbersList1 = { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; - numbersList1.CountingSort(); - Assert.True(numbersList1.SequenceEqual(new[] { 0, 2, 3, 4, 8, 9, 12, 15, 16, 23, 25, 34, 42, 46, 55 })); - } + int[] numbersList1 = { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; + numbersList1.CountingSort(); + Assert.True(numbersList1.SequenceEqual(new[] { 0, 2, 3, 4, 8, 9, 12, 15, 16, 23, 25, 34, 42, 46, 55 })); } -} +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/GraphsBipartiteColoringTest.cs b/UnitTest/AlgorithmsTests/GraphsBipartiteColoringTest.cs index 57c47a45..86b8f599 100644 --- a/UnitTest/AlgorithmsTests/GraphsBipartiteColoringTest.cs +++ b/UnitTest/AlgorithmsTests/GraphsBipartiteColoringTest.cs @@ -2,148 +2,147 @@ using DataStructures.Graphs; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class GraphsBipartiteColoringTest { - public static class GraphsBipartiteColoringTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - // The graph - IGraph graph = new UndirectedSparseGraph(); + // The graph + IGraph graph = new UndirectedSparseGraph(); - // The bipartite wrapper - BipartiteColoring, string> bipartiteGraph; + // The bipartite wrapper + BipartiteColoring, string> bipartiteGraph; - // The status for checking bipartiteness - bool initBipartiteStatus; + // The status for checking bipartiteness + bool initBipartiteStatus; - // Prepare the graph for the first case of testing - _initializeFirstCaseGraph(ref graph); + // Prepare the graph for the first case of testing + _initializeFirstCaseGraph(ref graph); - // Test initializing the bipartite - // This initialization must fail. The graph contains an odd cycle + // Test initializing the bipartite + // This initialization must fail. The graph contains an odd cycle - try - { - bipartiteGraph = new BipartiteColoring, string>(graph); - initBipartiteStatus = bipartiteGraph.IsBipartite(); - } - catch - { - initBipartiteStatus = false; - } + try + { + bipartiteGraph = new BipartiteColoring, string>(graph); + initBipartiteStatus = bipartiteGraph.IsBipartite(); + } + catch + { + initBipartiteStatus = false; + } - Assert.True(initBipartiteStatus == false, "Graph should not be bipartite."); + Assert.True(initBipartiteStatus == false, "Graph should not be bipartite."); - /************************************************************/ + /************************************************************/ - // - // Prepare the graph for the second case of testing - _initializeSecondCaseGraph(ref graph); + // + // Prepare the graph for the second case of testing + _initializeSecondCaseGraph(ref graph); - // - // Test initializing the bipartite - // This initialization must fail. The graph contains an odd cycle - bipartiteGraph = null; + // + // Test initializing the bipartite + // This initialization must fail. The graph contains an odd cycle + bipartiteGraph = null; - try - { - bipartiteGraph = new BipartiteColoring, string>(graph); - initBipartiteStatus = bipartiteGraph.IsBipartite(); - } - catch - { - initBipartiteStatus = false; - } + try + { + bipartiteGraph = new BipartiteColoring, string>(graph); + initBipartiteStatus = bipartiteGraph.IsBipartite(); + } + catch + { + initBipartiteStatus = false; + } - Assert.True(initBipartiteStatus == false, "Graph should not be bipartite."); + Assert.True(initBipartiteStatus == false, "Graph should not be bipartite."); - // - // Remove Odd Cycle and try to initialize again. - graph.RemoveEdge("c", "v"); - graph.RemoveEdge("f", "b"); + // + // Remove Odd Cycle and try to initialize again. + graph.RemoveEdge("c", "v"); + graph.RemoveEdge("f", "b"); - // - // This initialization must pass. The graph doesn't contain any odd cycle - try - { - bipartiteGraph = new BipartiteColoring, string>(graph); - initBipartiteStatus = bipartiteGraph.IsBipartite(); - } - catch - { - initBipartiteStatus = false; - } + // + // This initialization must pass. The graph doesn't contain any odd cycle + try + { + bipartiteGraph = new BipartiteColoring, string>(graph); + initBipartiteStatus = bipartiteGraph.IsBipartite(); + } + catch + { + initBipartiteStatus = false; + } - Assert.True(initBipartiteStatus, "Graph should be bipartite."); + Assert.True(initBipartiteStatus, "Graph should be bipartite."); - Assert.True(bipartiteGraph.ColorOf("a") == BipartiteColor.Red); - Assert.True(bipartiteGraph.ColorOf("s") == BipartiteColor.Blue); - Assert.True(bipartiteGraph.ColorOf("b") == BipartiteColor.Red); - Assert.True(bipartiteGraph.ColorOf("f") == BipartiteColor.Red); - Assert.True(bipartiteGraph.ColorOf("z") == BipartiteColor.Blue); - } + Assert.True(bipartiteGraph.ColorOf("a") == BipartiteColor.Red); + Assert.True(bipartiteGraph.ColorOf("s") == BipartiteColor.Blue); + Assert.True(bipartiteGraph.ColorOf("b") == BipartiteColor.Red); + Assert.True(bipartiteGraph.ColorOf("f") == BipartiteColor.Red); + Assert.True(bipartiteGraph.ColorOf("z") == BipartiteColor.Blue); + } + // + // Second Case Initialization + private static void _initializeFirstCaseGraph(ref IGraph graph) + { + // Clear the graph + graph.Clear(); + // - // Second Case Initialization - private static void _initializeFirstCaseGraph(ref IGraph graph) - { - // Clear the graph - graph.Clear(); - - // - // Add vertices - var verticesSet = new[] {"a", "b", "c"}; - graph.AddVertices(verticesSet); - - // - // Add Edges - graph.AddEdge("a", "b"); - graph.AddEdge("b", "c"); - graph.AddEdge("c", "a"); - } + // Add vertices + var verticesSet = new[] {"a", "b", "c"}; + graph.AddVertices(verticesSet); + + // + // Add Edges + graph.AddEdge("a", "b"); + graph.AddEdge("b", "c"); + graph.AddEdge("c", "a"); + } + + // + // Second Case Initialization + private static void _initializeSecondCaseGraph(ref IGraph graph) + { + // Clear the graph + graph.Clear(); // - // Second Case Initialization - private static void _initializeSecondCaseGraph(ref IGraph graph) - { - // Clear the graph - graph.Clear(); - - // - // Add vertices - var verticesSet = new[] {"a", "b", "c", "d", "e", "f", "s", "v", "x", "y", "z"}; - graph.AddVertices(verticesSet); - - // - // Add edges - - // Connected Component #1 - // the vertex "e" won't be connected to any other vertex - - // Connected Component #2 - graph.AddEdge("a", "s"); - graph.AddEdge("a", "d"); - graph.AddEdge("s", "x"); - graph.AddEdge("s", "a"); - graph.AddEdge("x", "d"); - - // Connected Component #3 - graph.AddEdge("b", "c"); - graph.AddEdge("b", "v"); - graph.AddEdge("c", "f"); - graph.AddEdge("c", "v"); - graph.AddEdge("f", "b"); - - // Connected Component #4 - graph.AddEdge("y", "z"); - } + // Add vertices + var verticesSet = new[] {"a", "b", "c", "d", "e", "f", "s", "v", "x", "y", "z"}; + graph.AddVertices(verticesSet); + + // + // Add edges + + // Connected Component #1 + // the vertex "e" won't be connected to any other vertex + + // Connected Component #2 + graph.AddEdge("a", "s"); + graph.AddEdge("a", "d"); + graph.AddEdge("s", "x"); + graph.AddEdge("s", "a"); + graph.AddEdge("x", "d"); + + // Connected Component #3 + graph.AddEdge("b", "c"); + graph.AddEdge("b", "v"); + graph.AddEdge("c", "f"); + graph.AddEdge("c", "v"); + graph.AddEdge("f", "b"); + + // Connected Component #4 + graph.AddEdge("y", "z"); } } \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/GraphsBreadthFirstPathsTest.cs b/UnitTest/AlgorithmsTests/GraphsBreadthFirstPathsTest.cs index 888762eb..c5f9eb93 100644 --- a/UnitTest/AlgorithmsTests/GraphsBreadthFirstPathsTest.cs +++ b/UnitTest/AlgorithmsTests/GraphsBreadthFirstPathsTest.cs @@ -5,66 +5,63 @@ using Xunit; using System.Diagnostics; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class GraphsBreadthFirstPathsTest { - public static class GraphsBreadthFirstPathsTest + private static string PrintPath(IEnumerable path) { - private static string PrintPath(IEnumerable path) - { - string output = string.Empty; - - foreach (var node in path) - output = String.Format("{0}({1}) -> ", output, node); + string output = string.Empty; - output += "/TERMINATE/"; + foreach (var node in path) + output = String.Format("{0}({1}) -> ", output, node); - return output; - } + output += "/TERMINATE/"; - [Fact] - public static void DoTest() - { - IGraph graph = new UndirectedSparseGraph(); + return output; + } - // Add vertices - var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v", "w", "m" }; - graph.AddVertices(verticesSet1); + [Fact] + public static void DoTest() + { + IGraph graph = new UndirectedSparseGraph(); - // Add edges - graph.AddEdge("a", "s"); - graph.AddEdge("a", "z"); - graph.AddEdge("s", "x"); - graph.AddEdge("x", "d"); - graph.AddEdge("x", "c"); - graph.AddEdge("x", "w"); - graph.AddEdge("x", "m"); - graph.AddEdge("d", "f"); - graph.AddEdge("d", "c"); - graph.AddEdge("c", "f"); - graph.AddEdge("c", "v"); - graph.AddEdge("v", "f"); - graph.AddEdge("w", "m"); + // Add vertices + var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v", "w", "m" }; + graph.AddVertices(verticesSet1); - var sourceNode = "f"; - var bfsPaths = new BreadthFirstShortestPaths(graph, sourceNode); + // Add edges + graph.AddEdge("a", "s"); + graph.AddEdge("a", "z"); + graph.AddEdge("s", "x"); + graph.AddEdge("x", "d"); + graph.AddEdge("x", "c"); + graph.AddEdge("x", "w"); + graph.AddEdge("x", "m"); + graph.AddEdge("d", "f"); + graph.AddEdge("d", "c"); + graph.AddEdge("c", "f"); + graph.AddEdge("c", "v"); + graph.AddEdge("v", "f"); + graph.AddEdge("w", "m"); - // TODO: - // - Assert distances - // - Assert ShortestPathTo a node + var sourceNode = "f"; + var bfsPaths = new BreadthFirstShortestPaths(graph, sourceNode); - var distance = bfsPaths.DistanceTo("a"); + // TODO: + // - Assert distances + // - Assert ShortestPathTo a node - Trace.WriteLine("Distance from '" + sourceNode + "' to 'a' is: " + bfsPaths.DistanceTo("a")); - Trace.WriteLine("Path from '" + sourceNode + "' to 'a' is : " + PrintPath(bfsPaths.ShortestPathTo("a"))); + var distance = bfsPaths.DistanceTo("a"); - Trace.WriteLine(string.Empty); + Trace.WriteLine("Distance from '" + sourceNode + "' to 'a' is: " + bfsPaths.DistanceTo("a")); + Trace.WriteLine("Path from '" + sourceNode + "' to 'a' is : " + PrintPath(bfsPaths.ShortestPathTo("a"))); - Trace.WriteLine("Distance from '" + sourceNode + "' to 'w' is: " + bfsPaths.DistanceTo("w")); - Trace.WriteLine("Path from '" + sourceNode + "' to 'w' is : " + PrintPath(bfsPaths.ShortestPathTo("w"))); + Trace.WriteLine(string.Empty); - } + Trace.WriteLine("Distance from '" + sourceNode + "' to 'w' is: " + bfsPaths.DistanceTo("w")); + Trace.WriteLine("Path from '" + sourceNode + "' to 'w' is : " + PrintPath(bfsPaths.ShortestPathTo("w"))); } -} - +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/GraphsBreadthFirstSearchTest.cs b/UnitTest/AlgorithmsTests/GraphsBreadthFirstSearchTest.cs index 414c0158..bb1d9e6a 100644 --- a/UnitTest/AlgorithmsTests/GraphsBreadthFirstSearchTest.cs +++ b/UnitTest/AlgorithmsTests/GraphsBreadthFirstSearchTest.cs @@ -5,66 +5,63 @@ using Algorithms.Graphs; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class GraphsBreadthFirstSearchTest { - public static class GraphsBreadthFirstSearchTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - IGraph graph = new UndirectedSparseGraph(); + IGraph graph = new UndirectedSparseGraph(); - // Add vertices - var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }; - graph.AddVertices(verticesSet1); + // Add vertices + var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }; + graph.AddVertices(verticesSet1); - // Add edges - graph.AddEdge("a", "s"); - graph.AddEdge("a", "z"); - graph.AddEdge("s", "x"); - graph.AddEdge("x", "d"); - graph.AddEdge("x", "c"); - graph.AddEdge("d", "f"); - graph.AddEdge("d", "c"); - graph.AddEdge("c", "f"); - graph.AddEdge("c", "v"); - graph.AddEdge("v", "f"); + // Add edges + graph.AddEdge("a", "s"); + graph.AddEdge("a", "z"); + graph.AddEdge("s", "x"); + graph.AddEdge("x", "d"); + graph.AddEdge("x", "c"); + graph.AddEdge("d", "f"); + graph.AddEdge("d", "c"); + graph.AddEdge("c", "f"); + graph.AddEdge("c", "v"); + graph.AddEdge("v", "f"); - // Print the nodes in graph - // [*] BFS PrintAll: - BreadthFirstSearcher.PrintAll(graph, "d"); - string searchResult = null; - string startFromNode = "d"; - Action writeToConsole = (node) => Trace.Write(String.Format("({0}) ", node)); - Predicate searchPredicate = (node) => node == "f" || node == "c"; + // Print the nodes in graph + // [*] BFS PrintAll: + BreadthFirstSearcher.PrintAll(graph, "d"); + string searchResult = null; + string startFromNode = "d"; + Action writeToConsole = (node) => Trace.Write(String.Format("({0}) ", node)); + Predicate searchPredicate = (node) => node == "f" || node == "c"; - Trace.WriteLine("[*] BFS Visit All Nodes:"); - Trace.WriteLine("Graph traversal started at node: '" + startFromNode + "'"); + Trace.WriteLine("[*] BFS Visit All Nodes:"); + Trace.WriteLine("Graph traversal started at node: '" + startFromNode + "'"); - BreadthFirstSearcher.VisitAll(ref graph, startFromNode, writeToConsole); + BreadthFirstSearcher.VisitAll(ref graph, startFromNode, writeToConsole); - try - { - searchResult = BreadthFirstSearcher.FindFirstMatch(graph, startFromNode, searchPredicate); - - Assert.True(searchResult == "c" || searchResult == "f"); + try + { + searchResult = BreadthFirstSearcher.FindFirstMatch(graph, startFromNode, searchPredicate); - Trace.WriteLine("[*] BFS Find First Match:"); - Trace.WriteLine( - String.Format( - "Search result: '{0}'. The search started from node: '{1}'." - , searchResult - , startFromNode)); - } - catch (Exception) - { - Trace.WriteLine("Search predicate was not matched by any node in the graph."); - } + Assert.True(searchResult == "c" || searchResult == "f"); - Console.WriteLine("\r\n"); + Trace.WriteLine("[*] BFS Find First Match:"); + Trace.WriteLine( + String.Format( + "Search result: '{0}'. The search started from node: '{1}'." + , searchResult + , startFromNode)); + } + catch (Exception) + { + Trace.WriteLine("Search predicate was not matched by any node in the graph."); } + Console.WriteLine("\r\n"); } -} - +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/GraphsConnectedComponents.cs b/UnitTest/AlgorithmsTests/GraphsConnectedComponents.cs index 5535d446..c87424a0 100644 --- a/UnitTest/AlgorithmsTests/GraphsConnectedComponents.cs +++ b/UnitTest/AlgorithmsTests/GraphsConnectedComponents.cs @@ -3,58 +3,56 @@ using System.Diagnostics; using System.Linq; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class GraphsConnectedComponents { - public static class GraphsConnectedComponents + public static void DoTest() { - public static void DoTest() - { - var graph = new UndirectedSparseGraph(); - - // Add vertices - var verticesSet1 = new string[] { "a", "b", "c", "d", "e", "f", "s", "v", "x", "y", "z" }; - graph.AddVertices (verticesSet1); - - // Add edges - // Connected Component #1 - // the vertex "e" won't be connected to any other vertex - - // Connected Component #2 - graph.AddEdge("a", "s"); - graph.AddEdge("a", "d"); - graph.AddEdge("s", "x"); - graph.AddEdge("x", "d"); - - // Connected Component #3 - graph.AddEdge("b", "c"); - graph.AddEdge("b", "v"); - graph.AddEdge("c", "f"); - graph.AddEdge("c", "v"); - graph.AddEdge("f", "b"); - - // Connected Component #4 - graph.AddEdge("y", "z"); - - - // Get connected components - var connectedComponents = ConnectedComponents.Compute(graph); - connectedComponents = connectedComponents.OrderBy(item => item.Count).ToList(); - - Debug.Assert(connectedComponents.Count == 4); - - // the case of the (e) vertex - Debug.Assert(connectedComponents[0].Count == 1); - Debug.Assert(connectedComponents[0][0] == "e"); - - // the case of (y) and (z) vertices - Debug.Assert(connectedComponents[1].Count == 2); - Debug.Assert(connectedComponents[1].Contains("y")); - Debug.Assert(connectedComponents[1].Contains("z")); - - // the case of the rest - Debug.Assert(connectedComponents[2].Count == 4); - Debug.Assert(connectedComponents[3].Count == 4); - } - } -} + var graph = new UndirectedSparseGraph(); + + // Add vertices + var verticesSet1 = new string[] { "a", "b", "c", "d", "e", "f", "s", "v", "x", "y", "z" }; + graph.AddVertices (verticesSet1); + + // Add edges + // Connected Component #1 + // the vertex "e" won't be connected to any other vertex + + // Connected Component #2 + graph.AddEdge("a", "s"); + graph.AddEdge("a", "d"); + graph.AddEdge("s", "x"); + graph.AddEdge("x", "d"); + + // Connected Component #3 + graph.AddEdge("b", "c"); + graph.AddEdge("b", "v"); + graph.AddEdge("c", "f"); + graph.AddEdge("c", "v"); + graph.AddEdge("f", "b"); + + // Connected Component #4 + graph.AddEdge("y", "z"); + + // Get connected components + var connectedComponents = ConnectedComponents.Compute(graph); + connectedComponents = connectedComponents.OrderBy(item => item.Count).ToList(); + + Debug.Assert(connectedComponents.Count == 4); + + // the case of the (e) vertex + Debug.Assert(connectedComponents[0].Count == 1); + Debug.Assert(connectedComponents[0][0] == "e"); + + // the case of (y) and (z) vertices + Debug.Assert(connectedComponents[1].Count == 2); + Debug.Assert(connectedComponents[1].Contains("y")); + Debug.Assert(connectedComponents[1].Contains("z")); + + // the case of the rest + Debug.Assert(connectedComponents[2].Count == 4); + Debug.Assert(connectedComponents[3].Count == 4); + } +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/GraphsCyclesDetectorTests.cs b/UnitTest/AlgorithmsTests/GraphsCyclesDetectorTests.cs index 91cefaee..9f2a8e60 100644 --- a/UnitTest/AlgorithmsTests/GraphsCyclesDetectorTests.cs +++ b/UnitTest/AlgorithmsTests/GraphsCyclesDetectorTests.cs @@ -2,77 +2,75 @@ using DataStructures.Graphs; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class GraphsCyclesDetectorTests { - public static class GraphsCyclesDetectorTests + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - // Init graph object - var digraphWithCycles = new DirectedSparseGraph(); - - // Init V - var v = new string[6] { "r", "s", "t", "x", "y", "z" }; - - // Insert V - digraphWithCycles.AddVertices(v); - - // Insert E - digraphWithCycles.AddEdge("r", "s"); - digraphWithCycles.AddEdge("r", "t"); - digraphWithCycles.AddEdge("s", "t"); - digraphWithCycles.AddEdge("s", "x"); - digraphWithCycles.AddEdge("t", "x"); - digraphWithCycles.AddEdge("t", "y"); - digraphWithCycles.AddEdge("t", "z"); - digraphWithCycles.AddEdge("x", "y"); - digraphWithCycles.AddEdge("x", "z"); - digraphWithCycles.AddEdge("y", "z"); - digraphWithCycles.AddEdge("z", "r"); - digraphWithCycles.AddEdge("z", "s"); - - var isCyclic = CyclesDetector.IsCyclic(digraphWithCycles); - Assert.True(isCyclic == true, "Wrong status! The graph has cycles."); - - var cyclicGraph = new UndirectedSparseGraph(); - - v = new string[] { "A", "B", "C", "D", "E" }; - - // Insert new values of V - cyclicGraph.AddVertices(v); - - // Insert new value for edges - cyclicGraph.AddEdge("A", "C"); - cyclicGraph.AddEdge("B", "A"); - cyclicGraph.AddEdge("B", "C"); - cyclicGraph.AddEdge("C", "E"); - cyclicGraph.AddEdge("C", "D"); - cyclicGraph.AddEdge("D", "B"); - cyclicGraph.AddEdge("E", "D"); - - isCyclic = CyclesDetector.IsCyclic(cyclicGraph); - Assert.True(isCyclic == true, "Wrong status! The graph has cycles."); - - var dag = new DirectedSparseGraph(); - - v = new string[] { "A", "B", "C", "D", "E", "X" }; - - // Insert new values of V - dag.AddVertices(v); - - // Insert new value for edges - dag.AddEdge("A", "B"); - dag.AddEdge("A", "X"); - dag.AddEdge("B", "C"); - dag.AddEdge("C", "D"); - dag.AddEdge("D", "E"); - dag.AddEdge("E", "X"); - - isCyclic = CyclesDetector.IsCyclic(dag); - Assert.True(isCyclic == false, "Wrong status! The graph has no cycles."); - } - + // Init graph object + var digraphWithCycles = new DirectedSparseGraph(); + + // Init V + var v = new string[6] { "r", "s", "t", "x", "y", "z" }; + + // Insert V + digraphWithCycles.AddVertices(v); + + // Insert E + digraphWithCycles.AddEdge("r", "s"); + digraphWithCycles.AddEdge("r", "t"); + digraphWithCycles.AddEdge("s", "t"); + digraphWithCycles.AddEdge("s", "x"); + digraphWithCycles.AddEdge("t", "x"); + digraphWithCycles.AddEdge("t", "y"); + digraphWithCycles.AddEdge("t", "z"); + digraphWithCycles.AddEdge("x", "y"); + digraphWithCycles.AddEdge("x", "z"); + digraphWithCycles.AddEdge("y", "z"); + digraphWithCycles.AddEdge("z", "r"); + digraphWithCycles.AddEdge("z", "s"); + + var isCyclic = CyclesDetector.IsCyclic(digraphWithCycles); + Assert.True(isCyclic == true, "Wrong status! The graph has cycles."); + + var cyclicGraph = new UndirectedSparseGraph(); + + v = new string[] { "A", "B", "C", "D", "E" }; + + // Insert new values of V + cyclicGraph.AddVertices(v); + + // Insert new value for edges + cyclicGraph.AddEdge("A", "C"); + cyclicGraph.AddEdge("B", "A"); + cyclicGraph.AddEdge("B", "C"); + cyclicGraph.AddEdge("C", "E"); + cyclicGraph.AddEdge("C", "D"); + cyclicGraph.AddEdge("D", "B"); + cyclicGraph.AddEdge("E", "D"); + + isCyclic = CyclesDetector.IsCyclic(cyclicGraph); + Assert.True(isCyclic == true, "Wrong status! The graph has cycles."); + + var dag = new DirectedSparseGraph(); + + v = new string[] { "A", "B", "C", "D", "E", "X" }; + + // Insert new values of V + dag.AddVertices(v); + + // Insert new value for edges + dag.AddEdge("A", "B"); + dag.AddEdge("A", "X"); + dag.AddEdge("B", "C"); + dag.AddEdge("C", "D"); + dag.AddEdge("D", "E"); + dag.AddEdge("E", "X"); + + isCyclic = CyclesDetector.IsCyclic(dag); + Assert.True(isCyclic == false, "Wrong status! The graph has no cycles."); } -} +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/GraphsDepthFirstSearchTest.cs b/UnitTest/AlgorithmsTests/GraphsDepthFirstSearchTest.cs index 354a2979..e947ac24 100644 --- a/UnitTest/AlgorithmsTests/GraphsDepthFirstSearchTest.cs +++ b/UnitTest/AlgorithmsTests/GraphsDepthFirstSearchTest.cs @@ -4,67 +4,65 @@ using DataStructures.Graphs; using Algorithms.Graphs; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class GraphsDepthFirstSearchTest { - public static class GraphsDepthFirstSearchTest + public static void DoTest () { - public static void DoTest () - { - IGraph graph = new UndirectedSparseGraph(); + IGraph graph = new UndirectedSparseGraph(); - // Add vertices - var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }; - graph.AddVertices (verticesSet1); + // Add vertices + var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }; + graph.AddVertices (verticesSet1); - // Add edges - graph.AddEdge("a", "s"); - graph.AddEdge("a", "z"); - graph.AddEdge("s", "x"); - graph.AddEdge("x", "d"); - graph.AddEdge("x", "c"); - graph.AddEdge("d", "f"); - graph.AddEdge("d", "c"); - graph.AddEdge("c", "f"); - graph.AddEdge("c", "v"); - graph.AddEdge("v", "f"); + // Add edges + graph.AddEdge("a", "s"); + graph.AddEdge("a", "z"); + graph.AddEdge("s", "x"); + graph.AddEdge("x", "d"); + graph.AddEdge("x", "c"); + graph.AddEdge("d", "f"); + graph.AddEdge("d", "c"); + graph.AddEdge("c", "f"); + graph.AddEdge("c", "v"); + graph.AddEdge("v", "f"); - // Print the nodes in graph - Console.WriteLine(" [*] DFS PrintAll: "); - DepthFirstSearcher.PrintAll(graph, "d"); - Console.WriteLine("\r\n"); + // Print the nodes in graph + Console.WriteLine(" [*] DFS PrintAll: "); + DepthFirstSearcher.PrintAll(graph, "d"); + Console.WriteLine("\r\n"); - string searchResult = null; - string startFromNode = "d"; - Action writeToConsole = (node) => Console.Write (String.Format ("({0}) ", node)); - Predicate searchPredicate = (node) => node == "f" || node == "c"; + string searchResult = null; + string startFromNode = "d"; + Action writeToConsole = (node) => Console.Write (String.Format ("({0}) ", node)); + Predicate searchPredicate = (node) => node == "f" || node == "c"; - Console.WriteLine ("[*] DFS Visit All Nodes:"); - Console.WriteLine ("Graph traversal started at node: '" + startFromNode + "'"); + Console.WriteLine ("[*] DFS Visit All Nodes:"); + Console.WriteLine ("Graph traversal started at node: '" + startFromNode + "'"); - DepthFirstSearcher.VisitAll (ref graph, startFromNode, writeToConsole); + DepthFirstSearcher.VisitAll (ref graph, startFromNode, writeToConsole); - Console.WriteLine ("\r\n"); + Console.WriteLine ("\r\n"); - try - { - searchResult = DepthFirstSearcher.FindFirstMatch(graph, startFromNode, searchPredicate); - - Debug.Assert(searchResult == "c" || searchResult == "f"); + try + { + searchResult = DepthFirstSearcher.FindFirstMatch(graph, startFromNode, searchPredicate); - Console.WriteLine("[*] DFS Find First Match:"); - Console.WriteLine( - String.Format( - "Search result: '{0}'. The search started from node: '{1}'." - , searchResult - , startFromNode)); - } - catch(Exception) - { - Console.WriteLine ("Search predicate was not matched by any node in the graph."); - } + Debug.Assert(searchResult == "c" || searchResult == "f"); - Console.WriteLine ("\r\n"); + Console.WriteLine("[*] DFS Find First Match:"); + Console.WriteLine( + String.Format( + "Search result: '{0}'. The search started from node: '{1}'." + , searchResult + , startFromNode)); + } + catch(Exception) + { + Console.WriteLine ("Search predicate was not matched by any node in the graph."); } - } -} + Console.WriteLine ("\r\n"); + } +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs b/UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs index 57a1183a..93874d67 100644 --- a/UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs +++ b/UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs @@ -4,249 +4,248 @@ using System.Linq; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public class GraphsDijkstraShortestPathsTest { - public class GraphsDijkstraShortestPathsTest + [Fact] + public void Constructor_Throw_WhenGraphInNull() + { + Assert.Throws(() => new DijkstraShortestPaths, string>(null, "vertex")); + } + + [Fact] + public void Constructor_Throw_WhenSourceVertexIsNull() + { + var graph = new DirectedWeightedSparseGraph(); + Assert.Throws(() => new DijkstraShortestPaths, string>(graph, null)); + } + + [Fact] + public void Constructor_Throw_WhenSourceIsNotPartOfGraph() + { + var graph = new DirectedWeightedSparseGraph(); + graph.AddVertex("a"); + graph.AddVertex("b"); + graph.AddVertex("c"); + graph.AddVertex("d"); + Assert.Throws(() => new DijkstraShortestPaths, string>(graph, "x")); + } + + [Fact] + public void Constructor_Throw_WhenAnyEdgeWeightIsLessThanZero() + { + var graph = new DirectedWeightedSparseGraph(); + graph.AddVertex("a"); + graph.AddVertex("b"); + + graph.AddEdge("a", "b", -1); + + Assert.Throws(() => new DijkstraShortestPaths, string>(graph, "a")); + } + + [Fact] + public void ShortestPathTo_Throw_WhenDestinationIsNotInGraph() + { + var graph = new DirectedWeightedSparseGraph(); + graph.AddVertex("a"); + graph.AddVertex("b"); + graph.AddVertex("c"); + graph.AddVertex("d"); + + var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); + Assert.Throws(() => dijkstra.ShortestPathTo("z")); + } + + [Fact] + public void ShortestPathTo_ReturnNull_WhenDestinationIsNotAchievable() + { + var graph = new DirectedWeightedSparseGraph(); + graph.AddVertex("a"); + graph.AddVertex("b"); + graph.AddVertex("c"); + graph.AddVertex("d"); + + graph.AddEdge("a", "b", 1); + graph.AddEdge("b", "c", 1); + graph.AddEdge("c", "a", 1); + + var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); + Assert.Null(dijkstra.ShortestPathTo("d")); + } + + [Fact] + public void ShortestPathTo_ReturnSingleVertex_WhenDestinationIsSameAsSource() { - [Fact] - public void Constructor_Throw_WhenGraphInNull() - { - Assert.Throws(() => new DijkstraShortestPaths, string>(null, "vertex")); - } - - [Fact] - public void Constructor_Throw_WhenSourceVertexIsNull() - { - var graph = new DirectedWeightedSparseGraph(); - Assert.Throws(() => new DijkstraShortestPaths, string>(graph, null)); - } - - [Fact] - public void Constructor_Throw_WhenSourceIsNotPartOfGraph() - { - var graph = new DirectedWeightedSparseGraph(); - graph.AddVertex("a"); - graph.AddVertex("b"); - graph.AddVertex("c"); - graph.AddVertex("d"); - Assert.Throws(() => new DijkstraShortestPaths, string>(graph, "x")); - } - - [Fact] - public void Constructor_Throw_WhenAnyEdgeWeightIsLessThanZero() - { - var graph = new DirectedWeightedSparseGraph(); - graph.AddVertex("a"); - graph.AddVertex("b"); - - graph.AddEdge("a", "b", -1); - - Assert.Throws(() => new DijkstraShortestPaths, string>(graph, "a")); - } - - [Fact] - public void ShortestPathTo_Throw_WhenDestinationIsNotInGraph() - { - var graph = new DirectedWeightedSparseGraph(); - graph.AddVertex("a"); - graph.AddVertex("b"); - graph.AddVertex("c"); - graph.AddVertex("d"); - - var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); - Assert.Throws(() => dijkstra.ShortestPathTo("z")); - } - - [Fact] - public void ShortestPathTo_ReturnNull_WhenDestinationIsNotAchievable() - { - var graph = new DirectedWeightedSparseGraph(); - graph.AddVertex("a"); - graph.AddVertex("b"); - graph.AddVertex("c"); - graph.AddVertex("d"); - - graph.AddEdge("a", "b", 1); - graph.AddEdge("b", "c", 1); - graph.AddEdge("c", "a", 1); - - var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); - Assert.Null(dijkstra.ShortestPathTo("d")); - } - - [Fact] - public void ShortestPathTo_ReturnSingleVertex_WhenDestinationIsSameAsSource() - { - var graph = new DirectedWeightedSparseGraph(); - graph.AddVertex("a"); - graph.AddVertex("b"); - graph.AddVertex("c"); - graph.AddVertex("d"); - - graph.AddEdge("a", "b", 1); - graph.AddEdge("b", "c", 1); - graph.AddEdge("c", "a", 1); - - var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); - var result = dijkstra.ShortestPathTo("a"); - Assert.NotNull(result); - Assert.Single(result); - Assert.Equal("a", result.Single()); - } - - [Fact] - public void ShortestPathTo_FindShortestPath_WhenThereIsOnlyOnePath() - { - var graph = new DirectedWeightedSparseGraph(); - graph.AddVertex("a"); - graph.AddVertex("b"); - graph.AddVertex("c"); - graph.AddVertex("d"); - - graph.AddEdge("a", "b", 1); - graph.AddEdge("b", "c", 1); - graph.AddEdge("a", "c", 1); - graph.AddEdge("c", "d", 1); - - var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); - var result = dijkstra.ShortestPathTo("d"); - Assert.NotNull(result); - Assert.Equal(3, result.Count()); - Assert.Contains("a", result); - Assert.Contains("c", result); - Assert.Contains("d", result); - Assert.Equal(2, dijkstra.DistanceTo("d")); - } - - [Fact] - public void ShortestPathTo_FindShortestPath_WhenThereIsPossibleMultiplePaths() - { - var graph = new DirectedWeightedSparseGraph(); - graph.AddVertex("a"); - graph.AddVertex("b"); - graph.AddVertex("c"); - graph.AddVertex("d"); - - graph.AddEdge("a", "b", 1); - graph.AddEdge("b", "c", 1); - graph.AddEdge("c", "a", 1); - graph.AddEdge("c", "d", 1); - graph.AddEdge("b", "d", 1); - - var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); - var result = dijkstra.ShortestPathTo("d"); - Assert.NotNull(result); - Assert.Equal(3, result.Count()); - Assert.Contains("a", result); - Assert.Contains("b", result); - Assert.Contains("d", result); - Assert.Equal(2, dijkstra.DistanceTo("d")); - } - - [Fact] - public void ShortestPathTo_FindShortestPath_WhenEdgeHaveDifferentWeight() - { - var vertices = new[] { "r", "s", "t", "x", "y", "z" }; - var graph = new DirectedWeightedSparseGraph(); - graph.AddVertices(vertices); - - graph.AddEdge("r", "s", 7); - graph.AddEdge("r", "t", 6); - graph.AddEdge("s", "t", 5); - graph.AddEdge("s", "x", 9); - graph.AddEdge("t", "x", 10); - graph.AddEdge("t", "y", 7); - graph.AddEdge("t", "z", 5); - graph.AddEdge("x", "y", 2); - graph.AddEdge("x", "z", 4); - graph.AddEdge("y", "z", 1); - - var dijkstra = new DijkstraShortestPaths, string>(graph, "s"); - var shortestToZ = dijkstra.ShortestPathTo("z"); - Assert.NotNull(shortestToZ); - Assert.Equal(3, shortestToZ.Count()); - Assert.Contains("s", shortestToZ); - Assert.Contains("t", shortestToZ); - Assert.Contains("z", shortestToZ); - Assert.Equal(10, dijkstra.DistanceTo("z")); - - var shortestToY = dijkstra.ShortestPathTo("y"); - Assert.NotNull(shortestToY); - Assert.Equal(3, shortestToY.Count()); - Assert.Contains("s", shortestToY); - Assert.Contains("x", shortestToY); - Assert.Contains("y", shortestToY); - Assert.Equal(11, dijkstra.DistanceTo("y")); - } - - [Fact] - public void HasPathTo_Throw_WhenVertexIsNotInGraph() - { - var graph = new DirectedWeightedSparseGraph(); - graph.AddVertex("a"); - graph.AddVertex("b"); - graph.AddVertex("c"); - - graph.AddEdge("a", "b", 1); - - var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); - Assert.Throws(() => dijkstra.HasPathTo("z")); - } - - [Fact] - public void HasPathTo_ReturnTrue_WhenVertexIsAchievable() - { - var graph = new DirectedWeightedSparseGraph(); - graph.AddVertex("a"); - graph.AddVertex("b"); - graph.AddVertex("c"); - - graph.AddEdge("a", "b", 1); - - var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); - Assert.True(dijkstra.HasPathTo("b")); - } - - [Fact] - public void HasPathTo_ReturnFalse_WhenVertexIsNotAchievable() - { - var graph = new DirectedWeightedSparseGraph(); - graph.AddVertex("a"); - graph.AddVertex("b"); - graph.AddVertex("c"); - - graph.AddEdge("a", "b", 1); - - var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); - Assert.False(dijkstra.HasPathTo("c")); - } - - [Fact] - public void DistanceTo_Throw_WhenVertexIsNotInGraph() - { - var graph = new DirectedWeightedSparseGraph(); - graph.AddVertex("a"); - graph.AddVertex("b"); - graph.AddVertex("c"); - - graph.AddEdge("a", "b", 1); - - var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); - Assert.Throws(() => dijkstra.DistanceTo("z")); - } - - [Fact] - public void DistanceTo_ReturnInfinity_WhenVertexIsNotAchievable() - { - var graph = new DirectedWeightedSparseGraph(); - graph.AddVertex("a"); - graph.AddVertex("b"); - graph.AddVertex("c"); - - graph.AddEdge("a", "b", 1); - - var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); - Assert.Equal(long.MaxValue, dijkstra.DistanceTo("c")); - } + var graph = new DirectedWeightedSparseGraph(); + graph.AddVertex("a"); + graph.AddVertex("b"); + graph.AddVertex("c"); + graph.AddVertex("d"); + + graph.AddEdge("a", "b", 1); + graph.AddEdge("b", "c", 1); + graph.AddEdge("c", "a", 1); + + var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); + var result = dijkstra.ShortestPathTo("a"); + Assert.NotNull(result); + Assert.Single(result); + Assert.Equal("a", result.Single()); + } + + [Fact] + public void ShortestPathTo_FindShortestPath_WhenThereIsOnlyOnePath() + { + var graph = new DirectedWeightedSparseGraph(); + graph.AddVertex("a"); + graph.AddVertex("b"); + graph.AddVertex("c"); + graph.AddVertex("d"); + + graph.AddEdge("a", "b", 1); + graph.AddEdge("b", "c", 1); + graph.AddEdge("a", "c", 1); + graph.AddEdge("c", "d", 1); + + var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); + var result = dijkstra.ShortestPathTo("d"); + Assert.NotNull(result); + Assert.Equal(3, result.Count()); + Assert.Contains("a", result); + Assert.Contains("c", result); + Assert.Contains("d", result); + Assert.Equal(2, dijkstra.DistanceTo("d")); + } + + [Fact] + public void ShortestPathTo_FindShortestPath_WhenThereIsPossibleMultiplePaths() + { + var graph = new DirectedWeightedSparseGraph(); + graph.AddVertex("a"); + graph.AddVertex("b"); + graph.AddVertex("c"); + graph.AddVertex("d"); + + graph.AddEdge("a", "b", 1); + graph.AddEdge("b", "c", 1); + graph.AddEdge("c", "a", 1); + graph.AddEdge("c", "d", 1); + graph.AddEdge("b", "d", 1); + + var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); + var result = dijkstra.ShortestPathTo("d"); + Assert.NotNull(result); + Assert.Equal(3, result.Count()); + Assert.Contains("a", result); + Assert.Contains("b", result); + Assert.Contains("d", result); + Assert.Equal(2, dijkstra.DistanceTo("d")); + } + + [Fact] + public void ShortestPathTo_FindShortestPath_WhenEdgeHaveDifferentWeight() + { + var vertices = new[] { "r", "s", "t", "x", "y", "z" }; + var graph = new DirectedWeightedSparseGraph(); + graph.AddVertices(vertices); + + graph.AddEdge("r", "s", 7); + graph.AddEdge("r", "t", 6); + graph.AddEdge("s", "t", 5); + graph.AddEdge("s", "x", 9); + graph.AddEdge("t", "x", 10); + graph.AddEdge("t", "y", 7); + graph.AddEdge("t", "z", 5); + graph.AddEdge("x", "y", 2); + graph.AddEdge("x", "z", 4); + graph.AddEdge("y", "z", 1); + + var dijkstra = new DijkstraShortestPaths, string>(graph, "s"); + var shortestToZ = dijkstra.ShortestPathTo("z"); + Assert.NotNull(shortestToZ); + Assert.Equal(3, shortestToZ.Count()); + Assert.Contains("s", shortestToZ); + Assert.Contains("t", shortestToZ); + Assert.Contains("z", shortestToZ); + Assert.Equal(10, dijkstra.DistanceTo("z")); + + var shortestToY = dijkstra.ShortestPathTo("y"); + Assert.NotNull(shortestToY); + Assert.Equal(3, shortestToY.Count()); + Assert.Contains("s", shortestToY); + Assert.Contains("x", shortestToY); + Assert.Contains("y", shortestToY); + Assert.Equal(11, dijkstra.DistanceTo("y")); + } + + [Fact] + public void HasPathTo_Throw_WhenVertexIsNotInGraph() + { + var graph = new DirectedWeightedSparseGraph(); + graph.AddVertex("a"); + graph.AddVertex("b"); + graph.AddVertex("c"); + + graph.AddEdge("a", "b", 1); + + var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); + Assert.Throws(() => dijkstra.HasPathTo("z")); + } + + [Fact] + public void HasPathTo_ReturnTrue_WhenVertexIsAchievable() + { + var graph = new DirectedWeightedSparseGraph(); + graph.AddVertex("a"); + graph.AddVertex("b"); + graph.AddVertex("c"); + + graph.AddEdge("a", "b", 1); + + var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); + Assert.True(dijkstra.HasPathTo("b")); + } + + [Fact] + public void HasPathTo_ReturnFalse_WhenVertexIsNotAchievable() + { + var graph = new DirectedWeightedSparseGraph(); + graph.AddVertex("a"); + graph.AddVertex("b"); + graph.AddVertex("c"); + + graph.AddEdge("a", "b", 1); + + var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); + Assert.False(dijkstra.HasPathTo("c")); + } + + [Fact] + public void DistanceTo_Throw_WhenVertexIsNotInGraph() + { + var graph = new DirectedWeightedSparseGraph(); + graph.AddVertex("a"); + graph.AddVertex("b"); + graph.AddVertex("c"); + + graph.AddEdge("a", "b", 1); + + var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); + Assert.Throws(() => dijkstra.DistanceTo("z")); + } + + [Fact] + public void DistanceTo_ReturnInfinity_WhenVertexIsNotAchievable() + { + var graph = new DirectedWeightedSparseGraph(); + graph.AddVertex("a"); + graph.AddVertex("b"); + graph.AddVertex("c"); + + graph.AddEdge("a", "b", 1); + + var dijkstra = new DijkstraShortestPaths, string>(graph, "a"); + Assert.Equal(long.MaxValue, dijkstra.DistanceTo("c")); } -} +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/GraphsTopologicalSorterTest.cs b/UnitTest/AlgorithmsTests/GraphsTopologicalSorterTest.cs index 2d9959ea..21775dc1 100644 --- a/UnitTest/AlgorithmsTests/GraphsTopologicalSorterTest.cs +++ b/UnitTest/AlgorithmsTests/GraphsTopologicalSorterTest.cs @@ -7,69 +7,66 @@ using DataStructures.Lists; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class GraphsTopologicalSorterTest { - public static class GraphsTopologicalSorterTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - var V01 = new string[] { "A", "B", "C", "D", "E", "X" }; - var DAG01 = new DirectedSparseGraph(); + var V01 = new string[] { "A", "B", "C", "D", "E", "X" }; + var DAG01 = new DirectedSparseGraph(); - // Insert new values of V - DAG01.AddVertices(V01); + // Insert new values of V + DAG01.AddVertices(V01); - // Insert new value for edges - DAG01.AddEdge("A", "B"); - DAG01.AddEdge("A", "X"); - DAG01.AddEdge("B", "C"); - DAG01.AddEdge("C", "D"); - DAG01.AddEdge("D", "E"); - DAG01.AddEdge("E", "X"); + // Insert new value for edges + DAG01.AddEdge("A", "B"); + DAG01.AddEdge("A", "X"); + DAG01.AddEdge("B", "C"); + DAG01.AddEdge("C", "D"); + DAG01.AddEdge("D", "E"); + DAG01.AddEdge("E", "X"); - // PRINT THE GRAPH - // [*] DAG (Directed Asyclic Graph): + // PRINT THE GRAPH + // [*] DAG (Directed Asyclic Graph): - // CALCULATE THE TOPOLOGICAL SORT - var topologicalSort01 = TopologicalSorter.Sort(DAG01); + // CALCULATE THE TOPOLOGICAL SORT + var topologicalSort01 = TopologicalSorter.Sort(DAG01); - var output01 = string.Empty; - foreach (var node in topologicalSort01) - { - output01 = String.Format("{0}({1}) ", output01, node); - } + var output01 = string.Empty; + foreach (var node in topologicalSort01) + { + output01 = String.Format("{0}({1}) ", output01, node); + } - var V02 = new int[] { 7, 5, 3, 11, 8, 2, 9, 10 }; - var DAG02 = new DirectedSparseGraph(); + var V02 = new int[] { 7, 5, 3, 11, 8, 2, 9, 10 }; + var DAG02 = new DirectedSparseGraph(); - // Insert new values of V - DAG02.AddVertices(V02); + // Insert new values of V + DAG02.AddVertices(V02); - // Insert new value for edges - DAG02.AddEdge(7, 11); - DAG02.AddEdge(7, 8); - DAG02.AddEdge(5, 11); - DAG02.AddEdge(3, 8); - DAG02.AddEdge(3, 10); - DAG02.AddEdge(11, 2); - DAG02.AddEdge(11, 9); - DAG02.AddEdge(11, 10); - DAG02.AddEdge(8, 9); + // Insert new value for edges + DAG02.AddEdge(7, 11); + DAG02.AddEdge(7, 8); + DAG02.AddEdge(5, 11); + DAG02.AddEdge(3, 8); + DAG02.AddEdge(3, 10); + DAG02.AddEdge(11, 2); + DAG02.AddEdge(11, 9); + DAG02.AddEdge(11, 10); + DAG02.AddEdge(8, 9); - // PRINT THE GRAPH - // [*] DAG (Directed Asyclic Graph): - // CALCULATE THE TOPOLOGICAL SORT - var topologicalSort02 = TopologicalSorter.Sort(DAG02); + // PRINT THE GRAPH + // [*] DAG (Directed Asyclic Graph): + // CALCULATE THE TOPOLOGICAL SORT + var topologicalSort02 = TopologicalSorter.Sort(DAG02); - var output02 = string.Empty; - foreach (var node in topologicalSort02) - { - output02 = String.Format("{0}({1}) ", output02, node); - } + var output02 = string.Empty; + foreach (var node in topologicalSort02) + { + output02 = String.Format("{0}({1}) ", output02, node); } - } -} - +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/GreatestCommonDivisorTests.cs b/UnitTest/AlgorithmsTests/GreatestCommonDivisorTests.cs index 0c245b9e..fc69d5dd 100644 --- a/UnitTest/AlgorithmsTests/GreatestCommonDivisorTests.cs +++ b/UnitTest/AlgorithmsTests/GreatestCommonDivisorTests.cs @@ -1,88 +1,87 @@ using Algorithms.Numeric; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public class GreatestCommonDivisorTests { - public class GreatestCommonDivisorTests + [Fact] + public void FindGCD_BothAreZero() { - [Fact] - public void FindGCD_BothAreZero() - { - var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(0, 0); - Assert.Equal(0, gcdEuclidean); + var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(0, 0); + Assert.Equal(0, gcdEuclidean); - var gcdStein = GreatestCommonDivisor.FindGCDStein(0, 0); - Assert.Equal(0, gcdStein); - } + var gcdStein = GreatestCommonDivisor.FindGCDStein(0, 0); + Assert.Equal(0, gcdStein); + } - [Theory] - [InlineData(0, 4, 4)] - [InlineData(0, 9, 9)] - [InlineData(0, -14, 14)] - [InlineData(0, -99, 99)] - public void FindGCD_FirstIsZero(int a, int b, int expected) - { - var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b); - Assert.Equal(expected, gcdEuclidean); + [Theory] + [InlineData(0, 4, 4)] + [InlineData(0, 9, 9)] + [InlineData(0, -14, 14)] + [InlineData(0, -99, 99)] + public void FindGCD_FirstIsZero(int a, int b, int expected) + { + var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b); + Assert.Equal(expected, gcdEuclidean); - var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b); - Assert.Equal(expected, gcdStein); - } + var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b); + Assert.Equal(expected, gcdStein); + } - [Theory] - [InlineData(4, 0, 4)] - [InlineData(9, 0, 9)] - [InlineData(-14, 0, 14)] - [InlineData(-99, 0, 99)] - public void FindGCD_SecondIsZero(int a, int b, int expected) - { - var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b); - Assert.Equal(expected, gcdEuclidean); + [Theory] + [InlineData(4, 0, 4)] + [InlineData(9, 0, 9)] + [InlineData(-14, 0, 14)] + [InlineData(-99, 0, 99)] + public void FindGCD_SecondIsZero(int a, int b, int expected) + { + var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b); + Assert.Equal(expected, gcdEuclidean); - var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b); - Assert.Equal(expected, gcdStein); - } + var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b); + Assert.Equal(expected, gcdStein); + } - [Theory] - [InlineData(2, 4, 2)] - [InlineData(27, 9, 9)] - [InlineData(27, 14, 1)] - [InlineData(9, 6, 3)] - public void FindGCD_BothNumberArePositive(int a, int b, int expected) - { - var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b); - Assert.Equal(expected, gcdEuclidean); + [Theory] + [InlineData(2, 4, 2)] + [InlineData(27, 9, 9)] + [InlineData(27, 14, 1)] + [InlineData(9, 6, 3)] + public void FindGCD_BothNumberArePositive(int a, int b, int expected) + { + var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b); + Assert.Equal(expected, gcdEuclidean); - var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b); - Assert.Equal(expected, gcdStein); - } + var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b); + Assert.Equal(expected, gcdStein); + } - [Theory] - [InlineData(-2, -4, 2)] - [InlineData(-27, -9, 9)] - [InlineData(-27, -14, 1)] - [InlineData(-9, -6, 3)] - public void FindGCD_BothNumberAreNegative(int a, int b, int expected) - { - var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b); - Assert.Equal(expected, gcdEuclidean); + [Theory] + [InlineData(-2, -4, 2)] + [InlineData(-27, -9, 9)] + [InlineData(-27, -14, 1)] + [InlineData(-9, -6, 3)] + public void FindGCD_BothNumberAreNegative(int a, int b, int expected) + { + var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b); + Assert.Equal(expected, gcdEuclidean); - var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b); - Assert.Equal(expected, gcdStein); - } + var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b); + Assert.Equal(expected, gcdStein); + } - [Theory] - [InlineData(2, -4, 2)] - [InlineData(-27, 9, 9)] - [InlineData(27, -14, 1)] - [InlineData(-9, 6, 3)] - public void FindGCD_CombinationPositiveAndNegative(int a, int b, int expected) - { - var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b); - Assert.Equal(expected, gcdEuclidean); + [Theory] + [InlineData(2, -4, 2)] + [InlineData(-27, 9, 9)] + [InlineData(27, -14, 1)] + [InlineData(-9, 6, 3)] + public void FindGCD_CombinationPositiveAndNegative(int a, int b, int expected) + { + var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b); + Assert.Equal(expected, gcdEuclidean); - var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b); - Assert.Equal(expected, gcdStein); - } + var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b); + Assert.Equal(expected, gcdStein); } -} +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/HeapSorterTest.cs b/UnitTest/AlgorithmsTests/HeapSorterTest.cs index b9a5f446..88f50b29 100644 --- a/UnitTest/AlgorithmsTests/HeapSorterTest.cs +++ b/UnitTest/AlgorithmsTests/HeapSorterTest.cs @@ -2,27 +2,26 @@ using Algorithms.Sorting; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class HeapSorterTest { - public static class HeapSorterTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - int[] numbersList1 = new int[] { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; - List numbersList2 = new List { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; + int[] numbersList1 = new int[] { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; + List numbersList2 = new List { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; - numbersList1.HeapSort(); + numbersList1.HeapSort(); - // Sort Ascending (same as the method above); - numbersList2.HeapSortAscending(); + // Sort Ascending (same as the method above); + numbersList2.HeapSortAscending(); - Assert.True(numbersList2[numbersList2.Count - 1] == numbersList2[numbersList2.Count - 1]); + Assert.True(numbersList2[numbersList2.Count - 1] == numbersList2[numbersList2.Count - 1]); - // Sort Descending - numbersList2.HeapSortDescending(); + // Sort Descending + numbersList2.HeapSortDescending(); - Assert.True(numbersList2[0] > numbersList2[numbersList2.Count - 1]); - } + Assert.True(numbersList2[0] > numbersList2[numbersList2.Count - 1]); } -} +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/InsertionSortTest.cs b/UnitTest/AlgorithmsTests/InsertionSortTest.cs index 48d854a3..b177e908 100644 --- a/UnitTest/AlgorithmsTests/InsertionSortTest.cs +++ b/UnitTest/AlgorithmsTests/InsertionSortTest.cs @@ -3,60 +3,58 @@ using Algorithms.Sorting; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class InsertionSortTest { - public static class InsertionSortTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() + var list1 = new ArrayList { - var list1 = new ArrayList - { - 23, - 42, - 4, - 16, - 8, - 15, - 9, - 55, - 0, - 34, - 12, - 2 - }; - var list2 = new List - { - 23, - 42, - 4, - 16, - 8, - 15, - 9, - 55, - 0, - 34, - 12, - 2 - }; + 23, + 42, + 4, + 16, + 8, + 15, + 9, + 55, + 0, + 34, + 12, + 2 + }; + var list2 = new List + { + 23, + 42, + 4, + 16, + 8, + 15, + 9, + 55, + 0, + 34, + 12, + 2 + }; - // sort both lists - list1.InsertionSort(); - list2.InsertionSort(); + // sort both lists + list1.InsertionSort(); + list2.InsertionSort(); - bool isListEqual = true; - for (int i = 0; i < list1.Count; i++) + bool isListEqual = true; + for (int i = 0; i < list1.Count; i++) + { + if (list1[i] != list2[i]) { - if (list1[i] != list2[i]) - { - isListEqual = false; - break; - } + isListEqual = false; + break; } - - Assert.True(isListEqual); } - } -} + Assert.True(isListEqual); + } +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/LSDRadixSorterTest.cs b/UnitTest/AlgorithmsTests/LSDRadixSorterTest.cs index b240f6cb..b712741e 100644 --- a/UnitTest/AlgorithmsTests/LSDRadixSorterTest.cs +++ b/UnitTest/AlgorithmsTests/LSDRadixSorterTest.cs @@ -2,46 +2,44 @@ using System.Collections.Generic; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class LSDRadixSorterTest { - public static class LSDRadixSorterTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - // - // Sort strings - var name1 = "Mr. Ahmad Alhour"; - var name2 = "Msr. Anna John Hopcraft"; - var number1 = "0987654321"; - var number2 = "000999888777111222333777666555"; + // + // Sort strings + var name1 = "Mr. Ahmad Alhour"; + var name2 = "Msr. Anna John Hopcraft"; + var number1 = "0987654321"; + var number2 = "000999888777111222333777666555"; - name1 = name1.LSDRadixSort().Trim(); - Assert.True(name1 == ".AAMadhhlmorru"); + name1 = name1.LSDRadixSort().Trim(); + Assert.True(name1 == ".AAMadhhlmorru"); - name2 = name2.LSDRadixSort().Trim(); - Assert.True(name2 == ".AHJMaacfhnnnooprrst"); + name2 = name2.LSDRadixSort().Trim(); + Assert.True(name2 == ".AHJMaacfhnnnooprrst"); - number1 = number1.LSDRadixSort(); - Assert.True(number1 == "0123456789"); + number1 = number1.LSDRadixSort(); + Assert.True(number1 == "0123456789"); - number2 = number2.LSDRadixSort(); - Assert.True(number2 == "000111222333555666777777888999"); + number2 = number2.LSDRadixSort(); + Assert.True(number2 == "000111222333555666777777888999"); - // - // Sort a list of strings of the same length - var toBeSorted = new List() { "ahmad", "ahmed", "johny", "ammy1", "ammy2", "zeyad", "aliaa", "aaaaa", "mmmmm", "zzzzz" }; - var alreadySorted = new List() { "aaaaa", "ahmad", "ahmed", "aliaa", "ammy1", "ammy2", "johny", "mmmmm", "zeyad", "zzzzz" }; + // + // Sort a list of strings of the same length + var toBeSorted = new List() { "ahmad", "ahmed", "johny", "ammy1", "ammy2", "zeyad", "aliaa", "aaaaa", "mmmmm", "zzzzz" }; + var alreadySorted = new List() { "aaaaa", "ahmad", "ahmed", "aliaa", "ammy1", "ammy2", "johny", "mmmmm", "zeyad", "zzzzz" }; - toBeSorted.LSDRadixSort(stringFixedWidth: 5); - - for (int i = 0; i < toBeSorted.Count; ++i) - { - Assert.True(toBeSorted[i] == alreadySorted[i]); - } + toBeSorted.LSDRadixSort(stringFixedWidth: 5); + for (int i = 0; i < toBeSorted.Count; ++i) + { + Assert.True(toBeSorted[i] == alreadySorted[i]); } } -} +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/MergeSorterTest.cs b/UnitTest/AlgorithmsTests/MergeSorterTest.cs index 27329518..a6788803 100644 --- a/UnitTest/AlgorithmsTests/MergeSorterTest.cs +++ b/UnitTest/AlgorithmsTests/MergeSorterTest.cs @@ -3,18 +3,16 @@ using System.Linq; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class MergeSorterTest { - public static class MergeSorterTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - List numbersList = new List { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; - var sortedList = numbersList.MergeSort(); - int[] expectedSortedList = { 0, 2, 3, 4, 8, 9, 12, 15, 16, 23, 25, 34, 42, 46, 55 }; - Assert.True(sortedList.SequenceEqual(expectedSortedList)); - } + List numbersList = new List { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; + var sortedList = numbersList.MergeSort(); + int[] expectedSortedList = { 0, 2, 3, 4, 8, 9, 12, 15, 16, 23, 25, 34, 42, 46, 55 }; + Assert.True(sortedList.SequenceEqual(expectedSortedList)); } -} - +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/QuickSortTest.cs b/UnitTest/AlgorithmsTests/QuickSortTest.cs index 6aa6194c..c6fbe260 100644 --- a/UnitTest/AlgorithmsTests/QuickSortTest.cs +++ b/UnitTest/AlgorithmsTests/QuickSortTest.cs @@ -3,18 +3,16 @@ using System.Linq; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class QuickSortTest { - public static class QuickSortTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - var list = new List() { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; - list.QuickSort(); - long[] sortedList = { 0, 2, 3, 4, 8, 9, 12, 15, 16, 23, 25, 34, 42, 46, 55 }; - Assert.True(list.SequenceEqual(sortedList)); - } + var list = new List() { 23, 42, 4, 16, 8, 15, 3, 9, 55, 0, 34, 12, 2, 46, 25 }; + list.QuickSort(); + long[] sortedList = { 0, 2, 3, 4, 8, 9, 12, 15, 16, 23, 25, 34, 42, 46, 55 }; + Assert.True(list.SequenceEqual(sortedList)); } -} - +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/SieveOfAtkinTest.cs b/UnitTest/AlgorithmsTests/SieveOfAtkinTest.cs index 1df4a7db..1dfefaa3 100644 --- a/UnitTest/AlgorithmsTests/SieveOfAtkinTest.cs +++ b/UnitTest/AlgorithmsTests/SieveOfAtkinTest.cs @@ -2,19 +2,18 @@ using Algorithms.Numeric; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public class SieveOfAtkinTest { - public class SieveOfAtkinTest + [Theory] + [InlineData("Primes up to -100", -100)] + [InlineData("Primes up to 2", 2, 2)] + [InlineData("Primes up to 3", 3, 2, 3)] + [InlineData("Primes up to 100", 100, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97)] + public static void GeneratePrimesUpTo(string test, int max, params int[] expectedResult) { - [Theory] - [InlineData("Primes up to -100", -100)] - [InlineData("Primes up to 2", 2, 2)] - [InlineData("Primes up to 3", 3, 2, 3)] - [InlineData("Primes up to 100", 100, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97)] - public static void GeneratePrimesUpTo(string test, int max, params int[] expectedResult) - { - var result = SieveOfAtkin.GeneratePrimesUpTo(max); - Assert.True(result.SequenceEqual(expectedResult), test); - } + var result = SieveOfAtkin.GeneratePrimesUpTo(max); + Assert.True(result.SequenceEqual(expectedResult), test); } } \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/SieveOfEratosthenesTests.cs b/UnitTest/AlgorithmsTests/SieveOfEratosthenesTests.cs index ae2a19ab..e504f7db 100644 --- a/UnitTest/AlgorithmsTests/SieveOfEratosthenesTests.cs +++ b/UnitTest/AlgorithmsTests/SieveOfEratosthenesTests.cs @@ -2,34 +2,33 @@ using System.Linq; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public class SieveOfEratosthenesTests { - public class SieveOfEratosthenesTests - { - private const int MaxNumber = 100; + private const int MaxNumber = 100; - [Fact] - public void SieveOfEratosthenesGeneratesCorrectResults() - { - var results = SieveOfEratosthenes.GeneratePrimesUpTo(MaxNumber); - Assert.NotNull(results); - Assert.True(results.Any()); - Assert.Equal(results.Count(), 25); - Assert.DoesNotContain(1, results); - Assert.Contains(2, results); - Assert.Contains(7, results); - Assert.Contains(23, results); - Assert.Contains(41, results); - Assert.Contains(97, results); + [Fact] + public void SieveOfEratosthenesGeneratesCorrectResults() + { + var results = SieveOfEratosthenes.GeneratePrimesUpTo(MaxNumber); + Assert.NotNull(results); + Assert.True(results.Any()); + Assert.Equal(results.Count(), 25); + Assert.DoesNotContain(1, results); + Assert.Contains(2, results); + Assert.Contains(7, results); + Assert.Contains(23, results); + Assert.Contains(41, results); + Assert.Contains(97, results); - } + } - [Fact] - public void SieveOfEratosthenesReturnsEmptyListWhenGiven0() - { - var results = SieveOfEratosthenes.GeneratePrimesUpTo(0); - Assert.NotNull(results); - Assert.False(results.Any()); - } + [Fact] + public void SieveOfEratosthenesReturnsEmptyListWhenGiven0() + { + var results = SieveOfEratosthenes.GeneratePrimesUpTo(0); + Assert.NotNull(results); + Assert.False(results.Any()); } } \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/StringEditDistanceTest.cs b/UnitTest/AlgorithmsTests/StringEditDistanceTest.cs index 4c1acdab..a42e93f5 100644 --- a/UnitTest/AlgorithmsTests/StringEditDistanceTest.cs +++ b/UnitTest/AlgorithmsTests/StringEditDistanceTest.cs @@ -1,48 +1,46 @@ using Algorithms.Strings; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class StringEditDistanceTest { - public static class StringEditDistanceTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - short minDistance = 0; - - // Initialize the costs map - var costs = new EditDistanceCostsMap(insertionCost: 1, substitutionCost: 1, deletionCost: 1); + short minDistance = 0; - string one = ""; - string two = ""; - minDistance = EditDistance.GetMinDistance(one, two, costs); + // Initialize the costs map + var costs = new EditDistanceCostsMap(insertionCost: 1, substitutionCost: 1, deletionCost: 1); - // Assert min cost is zero - Assert.True(minDistance == 0); + string one = ""; + string two = ""; + minDistance = EditDistance.GetMinDistance(one, two, costs); - one = "I am Ahmad Alhour"; - two = "Ahmad Alhour"; - minDistance = EditDistance.GetMinDistance(one, two, costs); + // Assert min cost is zero + Assert.True(minDistance == 0); - // Assert min cost is 5 - Assert.True(minDistance == 5); + one = "I am Ahmad Alhour"; + two = "Ahmad Alhour"; + minDistance = EditDistance.GetMinDistance(one, two, costs); - one = "I am Ahmad Alhour"; - two = ""; - minDistance = EditDistance.GetMinDistance(one, two, costs); + // Assert min cost is 5 + Assert.True(minDistance == 5); - // Assert min cost is the length of string one (17 characters) - Assert.True(minDistance == one.Length); + one = "I am Ahmad Alhour"; + two = ""; + minDistance = EditDistance.GetMinDistance(one, two, costs); - one = "Thou shalt not kill"; - two = "You should not murder"; - minDistance = EditDistance.GetMinDistance(one, two, costs); + // Assert min cost is the length of string one (17 characters) + Assert.True(minDistance == one.Length); - // Assert min cost is 11 - Assert.True(minDistance == 11); + one = "Thou shalt not kill"; + two = "You should not murder"; + minDistance = EditDistance.GetMinDistance(one, two, costs); - } + // Assert min cost is 11 + Assert.True(minDistance == 11); } -} +} \ No newline at end of file diff --git a/UnitTest/AlgorithmsTests/StringPermutationTests.cs b/UnitTest/AlgorithmsTests/StringPermutationTests.cs index 0e8b8b82..4e87d21d 100644 --- a/UnitTest/AlgorithmsTests/StringPermutationTests.cs +++ b/UnitTest/AlgorithmsTests/StringPermutationTests.cs @@ -2,41 +2,40 @@ using Algorithms.Strings; using Xunit; -namespace UnitTest.AlgorithmsTests +namespace UnitTest.AlgorithmsTests; + +public static class StringPermutationTests { - public static class StringPermutationTests + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - var alphabets = "abcdefg"; - - var permutations = Permutations.ComputeDistinct(alphabets); - Assert.True(permutations.Count == 720); - - var one = "abcdefg"; - var two = "dabcgfe"; - Assert.True(Permutations.IsAnargram(one, two) == true); - - one = "123456"; - two = "789123"; - Assert.True(Permutations.IsAnargram(one, two) == false); - - one = "abc"; - two = "bbb"; - Assert.True(Permutations.IsAnargram(one, two) == false); - - one = "acdf"; - two = "bcde"; - Assert.True(Permutations.IsAnargram(one, two) == false); - - one = "I am legion"; // L is small - two = "Legion I am"; // L is capital - Assert.True(Permutations.IsAnargram(one, two) == false); - - one = "I am legion"; // L is small - two = "legion I am"; // L is small - Assert.True(Permutations.IsAnargram(one, two) == true); - } + var alphabets = "abcdefg"; + + var permutations = Permutations.ComputeDistinct(alphabets); + Assert.True(permutations.Count == 720); + + var one = "abcdefg"; + var two = "dabcgfe"; + Assert.True(Permutations.IsAnargram(one, two) == true); + + one = "123456"; + two = "789123"; + Assert.True(Permutations.IsAnargram(one, two) == false); + + one = "abc"; + two = "bbb"; + Assert.True(Permutations.IsAnargram(one, two) == false); + + one = "acdf"; + two = "bcde"; + Assert.True(Permutations.IsAnargram(one, two) == false); + + one = "I am legion"; // L is small + two = "Legion I am"; // L is capital + Assert.True(Permutations.IsAnargram(one, two) == false); + + one = "I am legion"; // L is small + two = "legion I am"; // L is small + Assert.True(Permutations.IsAnargram(one, two) == true); } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/AVLTreeTest.cs b/UnitTest/DataStructuresTests/AVLTreeTest.cs index 15b1933e..8610c339 100644 --- a/UnitTest/DataStructuresTests/AVLTreeTest.cs +++ b/UnitTest/DataStructuresTests/AVLTreeTest.cs @@ -2,271 +2,269 @@ using DataStructures.Trees; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class AVLTreeTest { - public static class AVLTreeTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - AVLTree avlTree = new AVLTree(); - - // - // CASE #1 - // Insert: 4, 5, 7 - // SIMPLE *left* rotation for node 4. - // - /*************************************** - ** UNBALANCED ===> BALANCED - ** 4 5 - ** \ / \ - ** 5 ===> 4 7 - ** \ - ** 7 - ** - *************************************** - */ - avlTree.Insert(4); // insert - avlTree.Insert(5); // insert - avlTree.Insert(7); // insert - - // ASSERT CAST 1; - AssertCase_1(avlTree); - - - // - // CASE #2 - // Insert to the previous tree: 2 and then 1. - // SIMPLE *right* rotation for node 4. - // - /********************************************* - ** UNBALANCED ===> BALANCED - ** 5 5 - ** / \ / \ - ** 4 7 ===> 2 7 - ** / / \ - ** 2 1 4 - ** / - ** 1 - ** - ********************************************* - */ - avlTree.Insert(2); // insert - avlTree.Insert(1); // insert - - // ASSERT CASE 2 - AssertCase_2(avlTree); - - - // - // CASE #3 - // Insert to the previous tree: 3. - // DOUBLE *right* rotation for node 5. - // - // The double rotation is achieved by: - // 1> Simple *left* rotation for node 2, and then - // 2> Simple *right* rotation for node 5 - // - /************************************* - ** UNBALANCED ===> TRANSITION (1st R) ===> BALANCED (2nd Rt) - ** 5 5 4 - ** / \ / \ / \ - ** 2 7 ===> 4 7 ===> 2 5 - ** / \ / / \ \ - ** 1 4 2 1 3 7 - ** / / \ - ** 3 1 3 - ** - ************************************* - */ - avlTree.Insert(3); // insert - - // ASSERT CASE 3 - AssertCase_3(avlTree); - - - // - // CASE #4 - // Insert to the previous tree: 6. - // DOUBLE *right* rotation for node 5. - // - // The double rotation is achieved by: - // 1> Simple *right* rotation for node 7, and then - // 2> Simple *left* rotation for node 5 - // - /************************************************************************** - ** UNBALANCED ===> TRANSITION (1st R) ===> BALANCED (2nd Rt) - ** 4 4 ..4.. - ** / \ / \ / \ - ** 2 5 ===> 2 5 ===> 2 6 - ** / \ \ / \ \ / \ / \ - ** 1 3 7 1 3 6 1 3 5 7 - ** / \ - ** 6 7 - ** - ************************************************************************** - */ - avlTree.Insert(6); // insert - - // ASSERT CASE 4 - AssertCase_4(avlTree); - - - // - // CASE #5 - // REMOVE the tree's root: 4. - // - /************************************************************************** - ** UNBALANCED ===> TRANSITION (1st R) ===> BALANCED (2nd Rt) - ** null .5.. - ** / \ / \ - ** 2 6 ===> ===> 2 6 - ** / \ / \ / \ \ - ** 1 3 5 7 1 3 7 - ** - ************************************************************************** - */ - avlTree.Remove(avlTree.Root.Value); // REMOVE 4 - - // ASSERT CASE 5 - AssertCase_5(avlTree); - - - // - // CLEAR THE TREE AND START OVER - // Compare two binary trees with each other (height-wise) using bulk-inserts - - avlTree = new AVLTree(); - var bsTree = new BinarySearchTree(); - - List treeDataList = new List() { 15, 25, 5, 12, 1, 16, 20, 9, 9, 7, 7, -1, 11, 19, 30, 8, 10, 13, 28, 39 }; - avlTree.Insert(treeDataList); - bsTree.Insert(treeDataList); - - int avlTreeHeight = avlTree.Height; - int bsTreeHeight = bsTree.Height; - - Assert.True(avlTreeHeight < bsTreeHeight, "Wrong heights. AVL Tree must be shorted than BS Tree."); - - treeDataList = new List() { 15, 25, 5, 12, 1, 9, 7, -1, 11, 30, 8, 10, 13, 28, 39 }; - avlTree.Clear(); - avlTree.Insert(treeDataList); - - // - // OUTPUT OF AVL TREE DRAWER - /** - ** ....9... - ** / \ - ** 5 .12. - ** / \ / \ - ** 1 7 11 25 - ** / \ / / \ - ** -1 8 10 15 30 - ** / / \ - ** 13 28 39 - */ - - }//end-do-test + AVLTree avlTree = new AVLTree(); + + // + // CASE #1 + // Insert: 4, 5, 7 + // SIMPLE *left* rotation for node 4. + // + /*************************************** + ** UNBALANCED ===> BALANCED + ** 4 5 + ** \ / \ + ** 5 ===> 4 7 + ** \ + ** 7 + ** + *************************************** + */ + avlTree.Insert(4); // insert + avlTree.Insert(5); // insert + avlTree.Insert(7); // insert + + // ASSERT CAST 1; + AssertCase_1(avlTree); + + + // + // CASE #2 + // Insert to the previous tree: 2 and then 1. + // SIMPLE *right* rotation for node 4. + // + /********************************************* + ** UNBALANCED ===> BALANCED + ** 5 5 + ** / \ / \ + ** 4 7 ===> 2 7 + ** / / \ + ** 2 1 4 + ** / + ** 1 + ** + ********************************************* + */ + avlTree.Insert(2); // insert + avlTree.Insert(1); // insert + + // ASSERT CASE 2 + AssertCase_2(avlTree); + + + // + // CASE #3 + // Insert to the previous tree: 3. + // DOUBLE *right* rotation for node 5. + // + // The double rotation is achieved by: + // 1> Simple *left* rotation for node 2, and then + // 2> Simple *right* rotation for node 5 + // + /************************************* + ** UNBALANCED ===> TRANSITION (1st R) ===> BALANCED (2nd Rt) + ** 5 5 4 + ** / \ / \ / \ + ** 2 7 ===> 4 7 ===> 2 5 + ** / \ / / \ \ + ** 1 4 2 1 3 7 + ** / / \ + ** 3 1 3 + ** + ************************************* + */ + avlTree.Insert(3); // insert + + // ASSERT CASE 3 + AssertCase_3(avlTree); + + + // + // CASE #4 + // Insert to the previous tree: 6. + // DOUBLE *right* rotation for node 5. + // + // The double rotation is achieved by: + // 1> Simple *right* rotation for node 7, and then + // 2> Simple *left* rotation for node 5 + // + /************************************************************************** + ** UNBALANCED ===> TRANSITION (1st R) ===> BALANCED (2nd Rt) + ** 4 4 ..4.. + ** / \ / \ / \ + ** 2 5 ===> 2 5 ===> 2 6 + ** / \ \ / \ \ / \ / \ + ** 1 3 7 1 3 6 1 3 5 7 + ** / \ + ** 6 7 + ** + ************************************************************************** + */ + avlTree.Insert(6); // insert + + // ASSERT CASE 4 + AssertCase_4(avlTree); + + + // + // CASE #5 + // REMOVE the tree's root: 4. + // + /************************************************************************** + ** UNBALANCED ===> TRANSITION (1st R) ===> BALANCED (2nd Rt) + ** null .5.. + ** / \ / \ + ** 2 6 ===> ===> 2 6 + ** / \ / \ / \ \ + ** 1 3 5 7 1 3 7 + ** + ************************************************************************** + */ + avlTree.Remove(avlTree.Root.Value); // REMOVE 4 + + // ASSERT CASE 5 + AssertCase_5(avlTree); // - // DEBUG.ASSERT <- CASE 1 - private static void AssertCase_1(AVLTree avlTree) - { - var avlRoot = avlTree.Root; - Assert.True(avlRoot.Value == 5, "Wrong root."); - Assert.True(avlRoot.LeftChild.Value == 4, "Wrong left child."); - Assert.True(avlRoot.RightChild.Value == 7, "Wrong right child."); - - Assert.True( - avlRoot.LeftChild.Height == 0 - && avlRoot.RightChild.Height == 0 - , - "Wrong heights at the leaf nodes!."); - } - - // DEBUG.ASSERT <- CASE 2 - private static void AssertCase_2(AVLTree avlTree) - { - var avlRoot = avlTree.Root; - Assert.True(avlRoot.Value == 5, "Wrong root."); - Assert.True(avlRoot.Height == 2, "Wrong root height!"); - Assert.True(avlRoot.LeftChild.Value == 2, "Wrong left child from root."); - Assert.True(avlRoot.RightChild.Value == 7, "Wrong right child from root."); - Assert.True(avlRoot.LeftChild.LeftChild.Value == 1, "Wrong value at {root->left->left}."); - Assert.True(avlRoot.LeftChild.RightChild.Value == 4, "Wrong value at {root->left->right}."); - - Assert.True( - avlRoot.LeftChild.LeftChild.Height == 0 - && avlRoot.LeftChild.RightChild.Height == 0 - && avlRoot.RightChild.Height == 0 - , - "Wrong heights at the leaf nodes!."); - } - - // DEBUG.ASSERT <- CASE 3 - private static void AssertCase_3(AVLTree avlTree) - { - var avlRoot = avlTree.Root; - Assert.True(avlRoot.Height == 2, "Wrong root height!"); - Assert.True(avlRoot.Value == 4, "Wrong root."); - Assert.True(avlRoot.LeftChild.Value == 2, "Wrong left child from root."); - Assert.True(avlRoot.RightChild.Value == 5, "Wrong right child from root."); - Assert.True(avlRoot.LeftChild.LeftChild.Value == 1, "Wrong value at {root->left->left}."); - Assert.True(avlRoot.LeftChild.RightChild.Value == 3, "Wrong value at {root->left->right}."); - Assert.True(avlRoot.RightChild.RightChild.Value == 7, "Wrong value at {root->right->right}."); - - Assert.True( - avlRoot.LeftChild.LeftChild.Height == 0 - && avlRoot.LeftChild.RightChild.Height == 0 - && avlRoot.RightChild.RightChild.Height == 0 - , - "Wrong heights at the leaf nodes!."); - } - - // DEBUG.ASSERT <- CASE 4 - private static void AssertCase_4(AVLTree avlTree) - { - var avlRoot = avlTree.Root; - Assert.True(avlRoot.Height == 2, "Wrong root height!"); - Assert.True(avlRoot.Value == 4, "Wrong root."); - Assert.True(avlRoot.LeftChild.Value == 2, "Wrong left child from root."); - Assert.True(avlRoot.RightChild.Value == 6, "Wrong right child from root."); - Assert.True(avlRoot.LeftChild.LeftChild.Value == 1, "Wrong value at {root->left->left}."); - Assert.True(avlRoot.LeftChild.RightChild.Value == 3, "Wrong value at {root->left->right}."); - Assert.True(avlRoot.RightChild.LeftChild.Value == 5, "Wrong value at {root->right->left}."); - Assert.True(avlRoot.RightChild.RightChild.Value == 7, "Wrong value at {root->right->right}."); - - Assert.True( - avlRoot.LeftChild.LeftChild.Height == 0 - && avlRoot.LeftChild.RightChild.Height == 0 - && avlRoot.RightChild.LeftChild.Height == 0 - && avlRoot.RightChild.RightChild.Height == 0 - , - "Wrong heights at the leaf nodes!."); - } - - // DEBUG.ASSERT <- CASE 5 - private static void AssertCase_5(AVLTree avlTree) - { - var avlRoot = avlTree.Root; - Assert.True(avlRoot.Height == 2, "Wrong root height!"); - Assert.True(avlRoot.Value == 5, "Wrong root."); - Assert.True(avlRoot.LeftChild.Value == 2, "Wrong left child from root."); - Assert.True(avlRoot.RightChild.Value == 6, "Wrong right child from root."); - Assert.True(avlRoot.LeftChild.LeftChild.Value == 1, "Wrong value at {root->left->left}."); - Assert.True(avlRoot.LeftChild.RightChild.Value == 3, "Wrong value at {root->left->right}."); - Assert.True(avlRoot.RightChild.LeftChild == null, "Wrong value at {root->right->left}."); - Assert.True(avlRoot.RightChild.RightChild.Value == 7, "Wrong value at {root->right->right}."); - - Assert.True( - avlRoot.LeftChild.LeftChild.Height == 0 - && avlRoot.LeftChild.RightChild.Height == 0 - && avlRoot.RightChild.RightChild.Height == 0 - , - "Wrong heights at the leaf nodes!."); - - } + // CLEAR THE TREE AND START OVER + // Compare two binary trees with each other (height-wise) using bulk-inserts + + avlTree = new AVLTree(); + var bsTree = new BinarySearchTree(); + + List treeDataList = new List() { 15, 25, 5, 12, 1, 16, 20, 9, 9, 7, 7, -1, 11, 19, 30, 8, 10, 13, 28, 39 }; + avlTree.Insert(treeDataList); + bsTree.Insert(treeDataList); + + int avlTreeHeight = avlTree.Height; + int bsTreeHeight = bsTree.Height; + + Assert.True(avlTreeHeight < bsTreeHeight, "Wrong heights. AVL Tree must be shorted than BS Tree."); + + treeDataList = new List() { 15, 25, 5, 12, 1, 9, 7, -1, 11, 30, 8, 10, 13, 28, 39 }; + avlTree.Clear(); + avlTree.Insert(treeDataList); + + // + // OUTPUT OF AVL TREE DRAWER + /** + ** ....9... + ** / \ + ** 5 .12. + ** / \ / \ + ** 1 7 11 25 + ** / \ / / \ + ** -1 8 10 15 30 + ** / / \ + ** 13 28 39 + */ + + }//end-do-test + + + // + // DEBUG.ASSERT <- CASE 1 + private static void AssertCase_1(AVLTree avlTree) + { + var avlRoot = avlTree.Root; + Assert.True(avlRoot.Value == 5, "Wrong root."); + Assert.True(avlRoot.LeftChild.Value == 4, "Wrong left child."); + Assert.True(avlRoot.RightChild.Value == 7, "Wrong right child."); + + Assert.True( + avlRoot.LeftChild.Height == 0 + && avlRoot.RightChild.Height == 0 + , + "Wrong heights at the leaf nodes!."); } -} + // DEBUG.ASSERT <- CASE 2 + private static void AssertCase_2(AVLTree avlTree) + { + var avlRoot = avlTree.Root; + Assert.True(avlRoot.Value == 5, "Wrong root."); + Assert.True(avlRoot.Height == 2, "Wrong root height!"); + Assert.True(avlRoot.LeftChild.Value == 2, "Wrong left child from root."); + Assert.True(avlRoot.RightChild.Value == 7, "Wrong right child from root."); + Assert.True(avlRoot.LeftChild.LeftChild.Value == 1, "Wrong value at {root->left->left}."); + Assert.True(avlRoot.LeftChild.RightChild.Value == 4, "Wrong value at {root->left->right}."); + + Assert.True( + avlRoot.LeftChild.LeftChild.Height == 0 + && avlRoot.LeftChild.RightChild.Height == 0 + && avlRoot.RightChild.Height == 0 + , + "Wrong heights at the leaf nodes!."); + } + + // DEBUG.ASSERT <- CASE 3 + private static void AssertCase_3(AVLTree avlTree) + { + var avlRoot = avlTree.Root; + Assert.True(avlRoot.Height == 2, "Wrong root height!"); + Assert.True(avlRoot.Value == 4, "Wrong root."); + Assert.True(avlRoot.LeftChild.Value == 2, "Wrong left child from root."); + Assert.True(avlRoot.RightChild.Value == 5, "Wrong right child from root."); + Assert.True(avlRoot.LeftChild.LeftChild.Value == 1, "Wrong value at {root->left->left}."); + Assert.True(avlRoot.LeftChild.RightChild.Value == 3, "Wrong value at {root->left->right}."); + Assert.True(avlRoot.RightChild.RightChild.Value == 7, "Wrong value at {root->right->right}."); + + Assert.True( + avlRoot.LeftChild.LeftChild.Height == 0 + && avlRoot.LeftChild.RightChild.Height == 0 + && avlRoot.RightChild.RightChild.Height == 0 + , + "Wrong heights at the leaf nodes!."); + } + + // DEBUG.ASSERT <- CASE 4 + private static void AssertCase_4(AVLTree avlTree) + { + var avlRoot = avlTree.Root; + Assert.True(avlRoot.Height == 2, "Wrong root height!"); + Assert.True(avlRoot.Value == 4, "Wrong root."); + Assert.True(avlRoot.LeftChild.Value == 2, "Wrong left child from root."); + Assert.True(avlRoot.RightChild.Value == 6, "Wrong right child from root."); + Assert.True(avlRoot.LeftChild.LeftChild.Value == 1, "Wrong value at {root->left->left}."); + Assert.True(avlRoot.LeftChild.RightChild.Value == 3, "Wrong value at {root->left->right}."); + Assert.True(avlRoot.RightChild.LeftChild.Value == 5, "Wrong value at {root->right->left}."); + Assert.True(avlRoot.RightChild.RightChild.Value == 7, "Wrong value at {root->right->right}."); + + Assert.True( + avlRoot.LeftChild.LeftChild.Height == 0 + && avlRoot.LeftChild.RightChild.Height == 0 + && avlRoot.RightChild.LeftChild.Height == 0 + && avlRoot.RightChild.RightChild.Height == 0 + , + "Wrong heights at the leaf nodes!."); + } + + // DEBUG.ASSERT <- CASE 5 + private static void AssertCase_5(AVLTree avlTree) + { + var avlRoot = avlTree.Root; + Assert.True(avlRoot.Height == 2, "Wrong root height!"); + Assert.True(avlRoot.Value == 5, "Wrong root."); + Assert.True(avlRoot.LeftChild.Value == 2, "Wrong left child from root."); + Assert.True(avlRoot.RightChild.Value == 6, "Wrong right child from root."); + Assert.True(avlRoot.LeftChild.LeftChild.Value == 1, "Wrong value at {root->left->left}."); + Assert.True(avlRoot.LeftChild.RightChild.Value == 3, "Wrong value at {root->left->right}."); + Assert.True(avlRoot.RightChild.LeftChild == null, "Wrong value at {root->right->left}."); + Assert.True(avlRoot.RightChild.RightChild.Value == 7, "Wrong value at {root->right->right}."); + + Assert.True( + avlRoot.LeftChild.LeftChild.Height == 0 + && avlRoot.LeftChild.RightChild.Height == 0 + && avlRoot.RightChild.RightChild.Height == 0 + , + "Wrong heights at the leaf nodes!."); + + } +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/ArrayListTest.cs b/UnitTest/DataStructuresTests/ArrayListTest.cs index 02bec1bd..7e882a99 100644 --- a/UnitTest/DataStructuresTests/ArrayListTest.cs +++ b/UnitTest/DataStructuresTests/ArrayListTest.cs @@ -1,82 +1,81 @@ using DataStructures.Lists; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class ArrayListTest { - public static class ArrayListTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - int index = 0; - var arrayList = new ArrayList(); + int index = 0; + var arrayList = new ArrayList(); - for (long i = 1; i < 1000000; ++i) - { - arrayList.Add(i); - } + for (long i = 1; i < 1000000; ++i) + { + arrayList.Add(i); + } - for (int i = 1000; i < 1100; i++) - { - arrayList.RemoveAt(i); - } + for (int i = 1000; i < 1100; i++) + { + arrayList.RemoveAt(i); + } - for (int i = 100000; i < 100100; i++) - { - arrayList.Remove(i); - } + for (int i = 100000; i < 100100; i++) + { + arrayList.Remove(i); + } - var allNumbersGreatorThanNineHundK = arrayList.FindAll(item => item > 900000); - Assert.True(allNumbersGreatorThanNineHundK.Count > 0, "Count check failed!"); + var allNumbersGreatorThanNineHundK = arrayList.FindAll(item => item > 900000); + Assert.True(allNumbersGreatorThanNineHundK.Count > 0, "Count check failed!"); - long nineHundK = arrayList.Find(item => item == 900000); + long nineHundK = arrayList.Find(item => item == 900000); - var indexIfNineHundK = arrayList.FindIndex(item => item == nineHundK); - Assert.True(indexIfNineHundK != -1, "Wrong index!"); + var indexIfNineHundK = arrayList.FindIndex(item => item == nineHundK); + Assert.True(indexIfNineHundK != -1, "Wrong index!"); - index = 900000; - arrayList.InsertAt(99999, index); - arrayList.InsertAt(99999, index); - arrayList.InsertAt(99999, index); - arrayList.InsertAt(99999, index); - arrayList.InsertAt(99999, index); + index = 900000; + arrayList.InsertAt(99999, index); + arrayList.InsertAt(99999, index); + arrayList.InsertAt(99999, index); + arrayList.InsertAt(99999, index); + arrayList.InsertAt(99999, index); - var allNines = arrayList.FindAll(item => item == 99999); - Assert.True(allNines.Count == 6, "Wrong result!"); + var allNines = arrayList.FindAll(item => item == 99999); + Assert.True(allNines.Count == 6, "Wrong result!"); - bool doesMillionExist = arrayList.Exists(item => item == 1000000); - Assert.False(doesMillionExist, "Wrong result!"); + bool doesMillionExist = arrayList.Exists(item => item == 1000000); + Assert.False(doesMillionExist, "Wrong result!"); - bool doesEightsExists = arrayList.Contains(88888); - Assert.True(doesEightsExists, "Wrong result!"); + bool doesEightsExists = arrayList.Contains(88888); + Assert.True(doesEightsExists, "Wrong result!"); - //arrayList.Reverse (); + //arrayList.Reverse (); - var arrayList2 = new ArrayList(); - arrayList2.Add(0); - arrayList2.Add(10); - arrayList2.Add(20); - arrayList2.Add(30); - arrayList2.Add(40); - arrayList2.Add(50); - arrayList2.Add(60); - arrayList2.Add(70); - arrayList2.Add(80); - arrayList2.Add(90); - arrayList2.Add(100); + var arrayList2 = new ArrayList(); + arrayList2.Add(0); + arrayList2.Add(10); + arrayList2.Add(20); + arrayList2.Add(30); + arrayList2.Add(40); + arrayList2.Add(50); + arrayList2.Add(60); + arrayList2.Add(70); + arrayList2.Add(80); + arrayList2.Add(90); + arrayList2.Add(100); - // Console.WriteLine(arrayList2.ToHumanReadable(addHeader: true)); + // Console.WriteLine(arrayList2.ToHumanReadable(addHeader: true)); - //var arrayList3 = arrayList.GetRange(0, 100); - //Console.WriteLine(arrayList3.ToHumanReadable(addHeader: true)); + //var arrayList3 = arrayList.GetRange(0, 100); + //Console.WriteLine(arrayList3.ToHumanReadable(addHeader: true)); - /****************************************************************/ + /****************************************************************/ - arrayList = new ArrayList(); - arrayList.AddRepeatedly(11, 32); - Assert.True(arrayList.Count == 32, "Wrong array size."); - } + arrayList = new ArrayList(); + arrayList.AddRepeatedly(11, 32); + Assert.True(arrayList.Count == 32, "Wrong array size."); } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/BTreeTest.cs b/UnitTest/DataStructuresTests/BTreeTest.cs index a4809f22..81c798ea 100644 --- a/UnitTest/DataStructuresTests/BTreeTest.cs +++ b/UnitTest/DataStructuresTests/BTreeTest.cs @@ -2,210 +2,209 @@ using DataStructures.Trees; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class BTreeTest { - public static class BTreeTest + [Fact] + public static void DoInsertTest() + { + BTree bTree = new BTree(4); + + // + // CASE #1 + // Insert: 10, 30, 20, 50, 40, 60, 70 + // ROOT contains all values; no split. + // + /*************************************** + ** + ** [10 , 20 , 30 , 40, 50, 60, 70] + ** + *************************************** + */ + bTree.Insert(10); + bTree.Insert(30); + bTree.Insert(20); + bTree.Insert(50); + bTree.Insert(40); + bTree.Insert(60); + bTree.Insert(70); + + Assert.Equal(7, bTree.Root.Keys.Count); + + + // + // CASE #2 + // Insert to the previous tree: 35. + // Split into multiple. + // + /*************************************** + ** + ** [40] + ** / \ + ** / \ + ** [10 , 20 , 30 , 35] [50 , 60 , 70] + ** + *************************************** + */ + bTree.Insert(35); + Assert.Equal(40, bTree.Root.Keys[0]); + Assert.Equal(4, bTree.Root.Children[0].Keys.Count); + Assert.Equal(3, bTree.Root.Children[1].Keys.Count); + + + // + // CASE #3 + // Insert to the previous tree: 5, 15, 25, 39. + // Split leftmost child. + // + /*************************************** + ** + ** [20 , 40] + ** / | \ + ** / | \ + ** [5, 10, 15] | [50 , 60 , 70] + ** | + ** [25, 30, 35, 39] + ** + *************************************** + */ + + bTree.Insert(5); + bTree.Insert(15); + bTree.Insert(25); + bTree.Insert(39); + Assert.Equal(20, bTree.Root.Keys[0]); + Assert.Equal(40, bTree.Root.Keys[1]); + Assert.Equal(3, bTree.Root.Children[0].Keys.Count); + Assert.Equal(4, bTree.Root.Children[1].Keys.Count); + Assert.Equal(3, bTree.Root.Children[2].Keys.Count); + } + + [Fact] + public static void DoSearchTest() + { + // Build a base tree + BTree bTree = new BTree(4); + bTree.Insert(10); + bTree.Insert(30); + bTree.Insert(20); + bTree.Insert(50); + bTree.Insert(40); + bTree.Insert(60); + bTree.Insert(70); + bTree.Insert(35); + bTree.Insert(5); + bTree.Insert(15); + bTree.Insert(25); + bTree.Insert(39); + + // The tree now looks like this: + /*************************************** + ** + ** [20 , 40] + ** / | \ + ** / | \ + ** [5, 10, 15] | [50 , 60 , 70] + ** | + ** [25, 30, 35, 39] + ** + *************************************** + */ + + Assert.Equal(2, bTree.Search(20).Keys.Count); + Assert.Equal(2, bTree.Search(40).Keys.Count); + Assert.Null(bTree.Search(41)); + Assert.Equal(3, bTree.Search(5).Keys.Count); + Assert.Equal(4, bTree.Search(25).Keys.Count); + } + + [Fact] + public static void DoDeleteTest() { - [Fact] - public static void DoInsertTest() - { - BTree bTree = new BTree(4); - - // - // CASE #1 - // Insert: 10, 30, 20, 50, 40, 60, 70 - // ROOT contains all values; no split. - // - /*************************************** - ** - ** [10 , 20 , 30 , 40, 50, 60, 70] - ** - *************************************** - */ - bTree.Insert(10); - bTree.Insert(30); - bTree.Insert(20); - bTree.Insert(50); - bTree.Insert(40); - bTree.Insert(60); - bTree.Insert(70); - - Assert.Equal(7, bTree.Root.Keys.Count); - - - // - // CASE #2 - // Insert to the previous tree: 35. - // Split into multiple. - // - /*************************************** - ** - ** [40] - ** / \ - ** / \ - ** [10 , 20 , 30 , 35] [50 , 60 , 70] - ** - *************************************** - */ - bTree.Insert(35); - Assert.Equal(40, bTree.Root.Keys[0]); - Assert.Equal(4, bTree.Root.Children[0].Keys.Count); - Assert.Equal(3, bTree.Root.Children[1].Keys.Count); - - - // - // CASE #3 - // Insert to the previous tree: 5, 15, 25, 39. - // Split leftmost child. - // - /*************************************** - ** - ** [20 , 40] - ** / | \ - ** / | \ - ** [5, 10, 15] | [50 , 60 , 70] - ** | - ** [25, 30, 35, 39] - ** - *************************************** - */ - - bTree.Insert(5); - bTree.Insert(15); - bTree.Insert(25); - bTree.Insert(39); - Assert.Equal(20, bTree.Root.Keys[0]); - Assert.Equal(40, bTree.Root.Keys[1]); - Assert.Equal(3, bTree.Root.Children[0].Keys.Count); - Assert.Equal(4, bTree.Root.Children[1].Keys.Count); - Assert.Equal(3, bTree.Root.Children[2].Keys.Count); - } - - [Fact] - public static void DoSearchTest() - { - // Build a base tree - BTree bTree = new BTree(4); - bTree.Insert(10); - bTree.Insert(30); - bTree.Insert(20); - bTree.Insert(50); - bTree.Insert(40); - bTree.Insert(60); - bTree.Insert(70); - bTree.Insert(35); - bTree.Insert(5); - bTree.Insert(15); - bTree.Insert(25); - bTree.Insert(39); - - // The tree now looks like this: - /*************************************** - ** - ** [20 , 40] - ** / | \ - ** / | \ - ** [5, 10, 15] | [50 , 60 , 70] - ** | - ** [25, 30, 35, 39] - ** - *************************************** - */ - - Assert.Equal(2, bTree.Search(20).Keys.Count); - Assert.Equal(2, bTree.Search(40).Keys.Count); - Assert.Null(bTree.Search(41)); - Assert.Equal(3, bTree.Search(5).Keys.Count); - Assert.Equal(4, bTree.Search(25).Keys.Count); - } - - [Fact] - public static void DoDeleteTest() - { - // Build a base tree - BTree bTree = new BTree(4); - bTree.Insert(10); - bTree.Insert(30); - bTree.Insert(20); - bTree.Insert(50); - bTree.Insert(40); - bTree.Insert(60); - bTree.Insert(70); - bTree.Insert(35); - bTree.Insert(5); - bTree.Insert(15); - bTree.Insert(25); - bTree.Insert(39); - - // The tree now looks like this: - /*************************************** - ** - ** [20 , 40] - ** / | \ - ** / | \ - ** [5, 10, 15] | [50 , 60 , 70] - ** | - ** [25, 30, 35, 39] - ** - *************************************** - */ - // First. assert the shape. - Assert.Equal(2, bTree.Search(20).Keys.Count); - Assert.Equal(2, bTree.Search(40).Keys.Count); - Assert.Null(bTree.Search(41)); - Assert.Equal(3, bTree.Search(5).Keys.Count); - Assert.Equal(4, bTree.Search(25).Keys.Count); - - // Now, remove a key from the left-most child. - bTree.Remove(5); - - // The tree now looks like this: - /*************************************** - ** - ** [40] - ** / \ - ** / \ - ** [10, 15, 20, 25, 30, 35, 39] [50 , 60 , 70] - ** - *************************************** - */ - - // The tree should now be rooted around 40, with the left child full. - Assert.Equal(null, bTree.Search(5)); - Assert.Equal(2, bTree.Root.Children.Count); - Assert.Equal(7, bTree.Root.Children[0].Keys.Count); // left-most - Assert.Equal(3, bTree.Root.Children[1].Keys.Count); // right-most - - // Remove 50 - it needs to be rebalanced now. - bTree.Remove(50); - - // The tree now looks like this: - /*************************************** - ** - ** [39] - ** / \ - ** / \ - ** [10, 15, 20, 25, 30, 35] [40, 60, 70] - ** - *************************************** - */ - Assert.Equal(39, bTree.Root.Keys[0]); - Assert.Equal(6, bTree.Root.Children[0].Keys.Count); - Assert.Equal(3, bTree.Root.Children[1].Keys.Count); - - // Remove everything - bTree.Remove(10); - bTree.Remove(15); - bTree.Remove(20); - bTree.Remove(25); - bTree.Remove(30); - bTree.Remove(35); - bTree.Remove(39); - bTree.Remove(40); - bTree.Remove(60); - bTree.Remove(70); - - Assert.Null(bTree.Root); - } + // Build a base tree + BTree bTree = new BTree(4); + bTree.Insert(10); + bTree.Insert(30); + bTree.Insert(20); + bTree.Insert(50); + bTree.Insert(40); + bTree.Insert(60); + bTree.Insert(70); + bTree.Insert(35); + bTree.Insert(5); + bTree.Insert(15); + bTree.Insert(25); + bTree.Insert(39); + + // The tree now looks like this: + /*************************************** + ** + ** [20 , 40] + ** / | \ + ** / | \ + ** [5, 10, 15] | [50 , 60 , 70] + ** | + ** [25, 30, 35, 39] + ** + *************************************** + */ + // First. assert the shape. + Assert.Equal(2, bTree.Search(20).Keys.Count); + Assert.Equal(2, bTree.Search(40).Keys.Count); + Assert.Null(bTree.Search(41)); + Assert.Equal(3, bTree.Search(5).Keys.Count); + Assert.Equal(4, bTree.Search(25).Keys.Count); + + // Now, remove a key from the left-most child. + bTree.Remove(5); + + // The tree now looks like this: + /*************************************** + ** + ** [40] + ** / \ + ** / \ + ** [10, 15, 20, 25, 30, 35, 39] [50 , 60 , 70] + ** + *************************************** + */ + + // The tree should now be rooted around 40, with the left child full. + Assert.Equal(null, bTree.Search(5)); + Assert.Equal(2, bTree.Root.Children.Count); + Assert.Equal(7, bTree.Root.Children[0].Keys.Count); // left-most + Assert.Equal(3, bTree.Root.Children[1].Keys.Count); // right-most + + // Remove 50 - it needs to be rebalanced now. + bTree.Remove(50); + + // The tree now looks like this: + /*************************************** + ** + ** [39] + ** / \ + ** / \ + ** [10, 15, 20, 25, 30, 35] [40, 60, 70] + ** + *************************************** + */ + Assert.Equal(39, bTree.Root.Keys[0]); + Assert.Equal(6, bTree.Root.Children[0].Keys.Count); + Assert.Equal(3, bTree.Root.Children[1].Keys.Count); + + // Remove everything + bTree.Remove(10); + bTree.Remove(15); + bTree.Remove(20); + bTree.Remove(25); + bTree.Remove(30); + bTree.Remove(35); + bTree.Remove(39); + bTree.Remove(40); + bTree.Remove(60); + bTree.Remove(70); + + Assert.Null(bTree.Root); } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/BinaryHeapsTest.cs b/UnitTest/DataStructuresTests/BinaryHeapsTest.cs index 73122961..b6dac5f3 100644 --- a/UnitTest/DataStructuresTests/BinaryHeapsTest.cs +++ b/UnitTest/DataStructuresTests/BinaryHeapsTest.cs @@ -3,178 +3,176 @@ using System.Collections.Generic; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class MinHeapTest { - public static class MinHeapTest + [Fact] + public static void CheckOrderInHeap_RandomOrder_ReturnsTrue() { - [Fact] - public static void CheckOrderInHeap_RandomOrder_ReturnsTrue() - { - BinaryMinHeap minHeap = new BinaryMinHeap(Comparer.Default); - - minHeap.Add(23); - minHeap.Add(42); - minHeap.Add(4); - minHeap.Add(16); - minHeap.Add(8); - minHeap.Add(1); - minHeap.Add(3); - minHeap.Add(100); - minHeap.Add(5); - minHeap.Add(7); - - var isRightOrder = IsRightOrderInHeap(minHeap); - Assert.True(isRightOrder); - } + BinaryMinHeap minHeap = new BinaryMinHeap(Comparer.Default); + + minHeap.Add(23); + minHeap.Add(42); + minHeap.Add(4); + minHeap.Add(16); + minHeap.Add(8); + minHeap.Add(1); + minHeap.Add(3); + minHeap.Add(100); + minHeap.Add(5); + minHeap.Add(7); + + var isRightOrder = IsRightOrderInHeap(minHeap); + Assert.True(isRightOrder); + } - [Fact] - public static void CheckOrderInHeap_AscendingOrder_ReturnsTrue() - { - BinaryMinHeap minHeap = new BinaryMinHeap(Comparer.Default); - - minHeap.Add(1); - minHeap.Add(2); - minHeap.Add(3); - minHeap.Add(4); - minHeap.Add(5); - minHeap.Add(6); - minHeap.Add(7); - minHeap.Add(8); - minHeap.Add(9); - minHeap.Add(10); - - var isRightOrder = IsRightOrderInHeap(minHeap); - Assert.True(isRightOrder); - } + [Fact] + public static void CheckOrderInHeap_AscendingOrder_ReturnsTrue() + { + BinaryMinHeap minHeap = new BinaryMinHeap(Comparer.Default); + + minHeap.Add(1); + minHeap.Add(2); + minHeap.Add(3); + minHeap.Add(4); + minHeap.Add(5); + minHeap.Add(6); + minHeap.Add(7); + minHeap.Add(8); + minHeap.Add(9); + minHeap.Add(10); + + var isRightOrder = IsRightOrderInHeap(minHeap); + Assert.True(isRightOrder); + } - [Fact] - public static void CheckOrderInHeap_DecreasingOrder_ReturnsTrue() - { - BinaryMinHeap minHeap = new BinaryMinHeap(Comparer.Default); - - minHeap.Add(10); - minHeap.Add(9); - minHeap.Add(8); - minHeap.Add(7); - minHeap.Add(6); - minHeap.Add(5); - minHeap.Add(4); - minHeap.Add(3); - minHeap.Add(2); - minHeap.Add(1); - - var isRightOrder = IsRightOrderInHeap(minHeap); - Assert.True(isRightOrder); - } + [Fact] + public static void CheckOrderInHeap_DecreasingOrder_ReturnsTrue() + { + BinaryMinHeap minHeap = new BinaryMinHeap(Comparer.Default); + + minHeap.Add(10); + minHeap.Add(9); + minHeap.Add(8); + minHeap.Add(7); + minHeap.Add(6); + minHeap.Add(5); + minHeap.Add(4); + minHeap.Add(3); + minHeap.Add(2); + minHeap.Add(1); + + var isRightOrder = IsRightOrderInHeap(minHeap); + Assert.True(isRightOrder); + } - public static bool IsRightOrderInHeap(BinaryMinHeap binaryMinHeap) where T : IComparable - { - var array = binaryMinHeap.ToArray(); + public static bool IsRightOrderInHeap(BinaryMinHeap binaryMinHeap) where T : IComparable + { + var array = binaryMinHeap.ToArray(); - for(int i=0; i * 2 + 1 < array.Length; ++i) + for(int i=0; i * 2 + 1 < array.Length; ++i) + { + int leftChildIndex = i * 2 + 1; + int rightChildIndex = leftChildIndex + 1; + + if (array[i].CompareTo(array[leftChildIndex]) > 0) { - int leftChildIndex = i * 2 + 1; - int rightChildIndex = leftChildIndex + 1; - - if (array[i].CompareTo(array[leftChildIndex]) > 0) - { - return false; - } - - if (rightChildIndex < array.Length && array[i].CompareTo(array[rightChildIndex]) > 0) - { - return true; - } + return false; } - return true; + if (rightChildIndex < array.Length && array[i].CompareTo(array[rightChildIndex]) > 0) + { + return true; + } } + + return true; } +} - public static class MaxHeapTest +public static class MaxHeapTest +{ + [Fact] + public static void CheckOrderInHeap_RandomOrder_ReturnsTrue() { - [Fact] - public static void CheckOrderInHeap_RandomOrder_ReturnsTrue() - { - BinaryMaxHeap maxHeap = new BinaryMaxHeap(Comparer.Default); - - maxHeap.Add(23); - maxHeap.Add(42); - maxHeap.Add(4); - maxHeap.Add(16); - maxHeap.Add(8); - maxHeap.Add(1); - maxHeap.Add(3); - maxHeap.Add(100); - maxHeap.Add(5); - maxHeap.Add(7); - - var isRightOrder = IsRightOrderInHeap(maxHeap); - Assert.True(isRightOrder); - } + BinaryMaxHeap maxHeap = new BinaryMaxHeap(Comparer.Default); + + maxHeap.Add(23); + maxHeap.Add(42); + maxHeap.Add(4); + maxHeap.Add(16); + maxHeap.Add(8); + maxHeap.Add(1); + maxHeap.Add(3); + maxHeap.Add(100); + maxHeap.Add(5); + maxHeap.Add(7); + + var isRightOrder = IsRightOrderInHeap(maxHeap); + Assert.True(isRightOrder); + } - [Fact] - public static void CheckOrderInHeap_AscendingOrder_ReturnsTrue() - { - BinaryMaxHeap maxHeap = new BinaryMaxHeap(Comparer.Default); - - maxHeap.Add(1); - maxHeap.Add(2); - maxHeap.Add(3); - maxHeap.Add(4); - maxHeap.Add(5); - maxHeap.Add(6); - maxHeap.Add(7); - maxHeap.Add(8); - maxHeap.Add(9); - maxHeap.Add(10); - - var isRightOrder = IsRightOrderInHeap(maxHeap); - Assert.True(isRightOrder); - } + [Fact] + public static void CheckOrderInHeap_AscendingOrder_ReturnsTrue() + { + BinaryMaxHeap maxHeap = new BinaryMaxHeap(Comparer.Default); + + maxHeap.Add(1); + maxHeap.Add(2); + maxHeap.Add(3); + maxHeap.Add(4); + maxHeap.Add(5); + maxHeap.Add(6); + maxHeap.Add(7); + maxHeap.Add(8); + maxHeap.Add(9); + maxHeap.Add(10); + + var isRightOrder = IsRightOrderInHeap(maxHeap); + Assert.True(isRightOrder); + } - [Fact] - public static void CheckOrderInHeap_DecreasingOrder_ReturnsTrue() - { - BinaryMaxHeap maxHeap = new BinaryMaxHeap(Comparer.Default); - - maxHeap.Add(10); - maxHeap.Add(9); - maxHeap.Add(8); - maxHeap.Add(7); - maxHeap.Add(6); - maxHeap.Add(5); - maxHeap.Add(4); - maxHeap.Add(3); - maxHeap.Add(2); - maxHeap.Add(1); - - var isRightOrder = IsRightOrderInHeap(maxHeap); - Assert.True(isRightOrder); - } + [Fact] + public static void CheckOrderInHeap_DecreasingOrder_ReturnsTrue() + { + BinaryMaxHeap maxHeap = new BinaryMaxHeap(Comparer.Default); + + maxHeap.Add(10); + maxHeap.Add(9); + maxHeap.Add(8); + maxHeap.Add(7); + maxHeap.Add(6); + maxHeap.Add(5); + maxHeap.Add(4); + maxHeap.Add(3); + maxHeap.Add(2); + maxHeap.Add(1); + + var isRightOrder = IsRightOrderInHeap(maxHeap); + Assert.True(isRightOrder); + } - public static bool IsRightOrderInHeap(BinaryMaxHeap binaryMaxHeap) where T : IComparable + public static bool IsRightOrderInHeap(BinaryMaxHeap binaryMaxHeap) where T : IComparable + { + var array = binaryMaxHeap.ToArray(); + + for (int i = 0; i * 2 + 1 < array.Length; ++i) { - var array = binaryMaxHeap.ToArray(); + int leftChildIndex = i * 2 + 1; + int rightChildIndex = leftChildIndex + 1; - for (int i = 0; i * 2 + 1 < array.Length; ++i) + if (array[i].CompareTo(array[leftChildIndex]) < 0) { - int leftChildIndex = i * 2 + 1; - int rightChildIndex = leftChildIndex + 1; - - if (array[i].CompareTo(array[leftChildIndex]) < 0) - { - return false; - } - - if (rightChildIndex < array.Length && array[i].CompareTo(array[rightChildIndex]) > 0) - { - return true; - } + return false; } - return true; + if (rightChildIndex < array.Length && array[i].CompareTo(array[rightChildIndex]) > 0) + { + return true; + } } - } -} + return true; + } +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/BinarySearchTreeMapTests.cs b/UnitTest/DataStructuresTests/BinarySearchTreeMapTests.cs index 4468edf5..a5122a55 100644 --- a/UnitTest/DataStructuresTests/BinarySearchTreeMapTests.cs +++ b/UnitTest/DataStructuresTests/BinarySearchTreeMapTests.cs @@ -3,138 +3,136 @@ using System.Collections.Generic; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class BinarySearchTreeMapTests { - public static class BinarySearchTreeMapTests + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - // Binary Search Tree Map collection - var bstMap = new BinarySearchTreeMap(allowDuplicates: false); + // Binary Search Tree Map collection + var bstMap = new BinarySearchTreeMap(allowDuplicates: false); - // Testing data - KeyValuePair[] values = new KeyValuePair[10]; + // Testing data + KeyValuePair[] values = new KeyValuePair[10]; - // Prepare the values array - for (int i = 1; i <= 10; ++i) - { - var keyValPair = new KeyValuePair(i, String.Format("Integer: {0}", i)); - values[i - 1] = keyValPair; - } + // Prepare the values array + for (int i = 1; i <= 10; ++i) + { + var keyValPair = new KeyValuePair(i, String.Format("Integer: {0}", i)); + values[i - 1] = keyValPair; + } - // Test singular insert - for (int i = 0; i < 10; ++i) - bstMap.Insert(values[i].Key, values[i].Value); + // Test singular insert + for (int i = 0; i < 10; ++i) + bstMap.Insert(values[i].Key, values[i].Value); - Assert.True(bstMap.Count == values.Length, "Expected the same number of items."); + Assert.True(bstMap.Count == values.Length, "Expected the same number of items."); - bstMap.Clear(); + bstMap.Clear(); - // Test collection insert - bstMap.Insert(values); + // Test collection insert + bstMap.Insert(values); - bool passed = true; - // Test enumeration of key-value pairs is still in oreder - var enumerator = bstMap.GetInOrderEnumerator(); - for (int i = 0; i < 10; ++i) + bool passed = true; + // Test enumeration of key-value pairs is still in oreder + var enumerator = bstMap.GetInOrderEnumerator(); + for (int i = 0; i < 10; ++i) + { + if (enumerator.MoveNext()) { - if (enumerator.MoveNext()) + var curr = enumerator.Current; + if (curr.Key != values[i].Key || curr.Value != values[i].Value) { - var curr = enumerator.Current; - if (curr.Key != values[i].Key || curr.Value != values[i].Value) - { - passed = false; - break; - } + passed = false; + break; } } - Assert.True(passed); - - - // Test against re-shuffled insertions (not like above order) - bstMap = new BinarySearchTreeMap(allowDuplicates: false); - - bstMap.Insert(4, "int4"); - bstMap.Insert(5, "int5"); - bstMap.Insert(7, "int7"); + } + Assert.True(passed); + + + // Test against re-shuffled insertions (not like above order) + bstMap = new BinarySearchTreeMap(allowDuplicates: false); + + bstMap.Insert(4, "int4"); + bstMap.Insert(5, "int5"); + bstMap.Insert(7, "int7"); + bstMap.Insert(2, "int2"); + bstMap.Insert(1, "int1"); + bstMap.Insert(3, "int3"); + bstMap.Insert(6, "int6"); + bstMap.Insert(0, "int0"); + bstMap.Insert(8, "int8"); + bstMap.Insert(10, "int10"); + bstMap.Insert(9, "int9"); + + Assert.True(bstMap.Count == values.Length + 1, "Expected the same number of items."); + + // ASSERT INSERTING DUPLICATES WOULD BREAK + var insert_duplicate_passed = true; + try + { + // 2 already exists in tree bstMap.Insert(2, "int2"); - bstMap.Insert(1, "int1"); - bstMap.Insert(3, "int3"); - bstMap.Insert(6, "int6"); - bstMap.Insert(0, "int0"); - bstMap.Insert(8, "int8"); - bstMap.Insert(10, "int10"); - bstMap.Insert(9, "int9"); - - Assert.True(bstMap.Count == values.Length + 1, "Expected the same number of items."); - - // ASSERT INSERTING DUPLICATES WOULD BREAK - var insert_duplicate_passed = true; - try - { - // 2 already exists in tree - bstMap.Insert(2, "int2"); - insert_duplicate_passed = true; - } - catch - { - insert_duplicate_passed = false; - } + insert_duplicate_passed = true; + } + catch + { + insert_duplicate_passed = false; + } - Assert.False(insert_duplicate_passed, "Fail! The tree doesn't allow duplicates"); + Assert.False(insert_duplicate_passed, "Fail! The tree doesn't allow duplicates"); - // Test find - Assert.True(bstMap.Find(5).Key == 5, "Wrong find result!"); - Assert.True(bstMap.FindMin().Key == 0, "Wrong min!"); - Assert.True(bstMap.FindMax().Key == 10, "Wrong max!"); + // Test find + Assert.True(bstMap.Find(5).Key == 5, "Wrong find result!"); + Assert.True(bstMap.FindMin().Key == 0, "Wrong min!"); + Assert.True(bstMap.FindMax().Key == 10, "Wrong max!"); - // Assert find raises exception on non-existing elements - bool threwKeyNotFoundError = false; + // Assert find raises exception on non-existing elements + bool threwKeyNotFoundError = false; - try - { - bstMap.Find(999999999); - threwKeyNotFoundError = false; - } - catch (KeyNotFoundException) - { - threwKeyNotFoundError = true; - } - - Assert.True(threwKeyNotFoundError, "Expected to catch KeyNotFoundException."); + try + { + bstMap.Find(999999999); + threwKeyNotFoundError = false; + } + catch (KeyNotFoundException) + { + threwKeyNotFoundError = true; + } - // Assert count - Assert.True(bstMap.Count == 11); + Assert.True(threwKeyNotFoundError, "Expected to catch KeyNotFoundException."); - // Assert existence and nonexistence of some items - Assert.True(bstMap.Contains(1)); - Assert.True(bstMap.Contains(3)); - Assert.False(bstMap.Contains(999)); + // Assert count + Assert.True(bstMap.Count == 11); - // Do some deletions - bstMap.Remove(7); - bstMap.Remove(1); - bstMap.Remove(3); + // Assert existence and nonexistence of some items + Assert.True(bstMap.Contains(1)); + Assert.True(bstMap.Contains(3)); + Assert.False(bstMap.Contains(999)); - // Assert count - Assert.True(bstMap.Count == 8); + // Do some deletions + bstMap.Remove(7); + bstMap.Remove(1); + bstMap.Remove(3); - // Assert nonexistence of previously existing items - Assert.False(bstMap.Contains(1)); - Assert.False(bstMap.Contains(3)); + // Assert count + Assert.True(bstMap.Count == 8); - // Remove root key - var oldRootKey = bstMap.Root.Key; - bstMap.Remove(bstMap.Root.Key); + // Assert nonexistence of previously existing items + Assert.False(bstMap.Contains(1)); + Assert.False(bstMap.Contains(3)); - // Assert count - Assert.True(bstMap.Count == 7); + // Remove root key + var oldRootKey = bstMap.Root.Key; + bstMap.Remove(bstMap.Root.Key); - // Assert nonexistence of old root's key - Assert.False(bstMap.Contains(oldRootKey)); + // Assert count + Assert.True(bstMap.Count == 7); - }//end-do-test - } -} + // Assert nonexistence of old root's key + Assert.False(bstMap.Contains(oldRootKey)); + }//end-do-test +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/BinarySearchTreeTest.cs b/UnitTest/DataStructuresTests/BinarySearchTreeTest.cs index 74effaef..6da49d17 100644 --- a/UnitTest/DataStructuresTests/BinarySearchTreeTest.cs +++ b/UnitTest/DataStructuresTests/BinarySearchTreeTest.cs @@ -3,144 +3,141 @@ using DataStructures.Trees; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class BinarySearchTreeTest { - public static class BinarySearchTreeTest + /// + /// FIRST TEST TREE WITH DUPLICATES ELEMENTS + /// + /// + [Fact] + public static void AssertTreeWithDuplicatesElements() { - /// - /// FIRST TEST TREE WITH DUPLICATES ELEMENTS - /// - /// - [Fact] - public static void AssertTreeWithDuplicatesElements() - { - // New tree which doesn't allow duplicates - var binarySearchTree = new AugmentedBinarySearchTree(allowDuplicates: true); + // New tree which doesn't allow duplicates + var binarySearchTree = new AugmentedBinarySearchTree(allowDuplicates: true); - int[] values = new int[21] { 15, 25, 5, 12, 1, 16, 20, 9, 9, 7, 7, 7, -1, 11, 19, 30, 8, 10, 13, 28, 39 }; + int[] values = new int[21] { 15, 25, 5, 12, 1, 16, 20, 9, 9, 7, 7, 7, -1, 11, 19, 30, 8, 10, 13, 28, 39 }; - // Insert values with duplicates - binarySearchTree.Insert(values); + // Insert values with duplicates + binarySearchTree.Insert(values); - // ASSERT COUNT = 21 (allows duplicates) - Assert.Equal(21, binarySearchTree.Count); + // ASSERT COUNT = 21 (allows duplicates) + Assert.Equal(21, binarySearchTree.Count); - // Test contains/find - Assert.True(binarySearchTree.Contains(10), "Wrong element."); + // Test contains/find + Assert.True(binarySearchTree.Contains(10), "Wrong element."); - // Test find all - var list = binarySearchTree.FindAll(element => element > 15).ToList(); - Assert.True(list.Count == 7, "Wrong FindAll result!"); + // Test find all + var list = binarySearchTree.FindAll(element => element > 15).ToList(); + Assert.True(list.Count == 7, "Wrong FindAll result!"); - // test sort - List sortedList = binarySearchTree.ToList(); - for (int i = 1; i < sortedList.Count; ++i) - Assert.True(sortedList[i - 1] <= sortedList[i], "BST sort is wrong!"); + // test sort + List sortedList = binarySearchTree.ToList(); + for (int i = 1; i < sortedList.Count; ++i) + Assert.True(sortedList[i - 1] <= sortedList[i], "BST sort is wrong!"); - // ASSERT MIN ITEM - Assert.True(binarySearchTree.FindMin() == -1, "Min is wrong."); + // ASSERT MIN ITEM + Assert.True(binarySearchTree.FindMin() == -1, "Min is wrong."); - // ASSERT MAX ITEM - Assert.True(binarySearchTree.FindMax() == 39, "Max is wrong."); + // ASSERT MAX ITEM + Assert.True(binarySearchTree.FindMax() == 39, "Max is wrong."); - // Remove min & max - binarySearchTree.RemoveMin(); - binarySearchTree.RemoveMax(); + // Remove min & max + binarySearchTree.RemoveMin(); + binarySearchTree.RemoveMax(); - // ASSERT MIN AFTER REMOVE-MIN - Assert.True(binarySearchTree.FindMin() == 1, "Min is wrong."); + // ASSERT MIN AFTER REMOVE-MIN + Assert.True(binarySearchTree.FindMin() == 1, "Min is wrong."); - // ASSERT MAX AFTER REMOVE MAX - Assert.True(binarySearchTree.FindMax() == 30, "Max is wrong."); + // ASSERT MAX AFTER REMOVE MAX + Assert.True(binarySearchTree.FindMax() == 30, "Max is wrong."); - // Remove min twice - binarySearchTree.RemoveMin(); - binarySearchTree.RemoveMin(); + // Remove min twice + binarySearchTree.RemoveMin(); + binarySearchTree.RemoveMin(); - // ASSERT MIN - Assert.True(binarySearchTree.FindMin() == 7, "Min is wrong."); + // ASSERT MIN + Assert.True(binarySearchTree.FindMin() == 7, "Min is wrong."); - // 7 STILL EXISTS BECAUSE IT WAS DUPLICATED - binarySearchTree.RemoveMin(); - Assert.True(binarySearchTree.FindMin() == 7, "Min is wrong."); + // 7 STILL EXISTS BECAUSE IT WAS DUPLICATED + binarySearchTree.RemoveMin(); + Assert.True(binarySearchTree.FindMin() == 7, "Min is wrong."); - // Remove max thrice - binarySearchTree.RemoveMax(); - binarySearchTree.RemoveMax(); - binarySearchTree.RemoveMax(); + // Remove max thrice + binarySearchTree.RemoveMax(); + binarySearchTree.RemoveMax(); + binarySearchTree.RemoveMax(); - // ASSERT MAX AFTER REMOVE-MAX 3 TIMES - Assert.True(binarySearchTree.FindMax() == 20, "Max is wrong."); + // ASSERT MAX AFTER REMOVE-MAX 3 TIMES + Assert.True(binarySearchTree.FindMax() == 20, "Max is wrong."); - // Test removing an element with subtrees - try - { - // doesn't exist! - binarySearchTree.Remove(1000); - } - catch - { - // does exist! - binarySearchTree.Remove(16); - } + // Test removing an element with subtrees + try + { + // doesn't exist! + binarySearchTree.Remove(1000); + } + catch + { + // does exist! + binarySearchTree.Remove(16); + } + + var enumerator = binarySearchTree.GetInOrderEnumerator(); + enumerator.MoveNext(); + Assert.Equal(7, enumerator.Current); + + enumerator.MoveNext(); + enumerator.MoveNext(); + Assert.True(enumerator.Current == 8, "Wrong in-order enumeration."); + } + + /// + /// NEXT TEST TREE THAT DOES NOT ALLOW DUPLICATES + /// + /// + [Fact] + public static void AssertTreeWithUniqueElements() + { + // New tree which doesn't allow duplicates + var binarySearchTree = new AugmentedBinarySearchTree(allowDuplicates: false); - var enumerator = binarySearchTree.GetInOrderEnumerator(); - enumerator.MoveNext(); - Assert.Equal(7, enumerator.Current); + int[] values = new int[24] { 14, 15, 25, 5, 12, 1, 16, 20, 9, 9, 9, 7, 7, 7, -1, 11, 19, 30, 8, 10, 13, 28, 39, 39 }; - enumerator.MoveNext(); - enumerator.MoveNext(); - Assert.True(enumerator.Current == 8, "Wrong in-order enumeration."); + var inserting_duplicates_passed = true; + try + { + // Insert values with duplicates + binarySearchTree.Insert(values); } + catch + { + inserting_duplicates_passed = false; + } + + Assert.False(inserting_duplicates_passed, "Fail! Tree doesn't allow duplicates"); - /// - /// NEXT TEST TREE THAT DOES NOT ALLOW DUPLICATES - /// - /// - [Fact] - public static void AssertTreeWithUniqueElements() + // + // Reduce values array to an array of distinct values + binarySearchTree.Clear(); + values = values.Distinct().ToArray(); + + var inserting_unique_passed = true; + try + { + // Insert unique values + binarySearchTree.Insert(values); + } + catch { - // New tree which doesn't allow duplicates - var binarySearchTree = new AugmentedBinarySearchTree(allowDuplicates: false); - - int[] values = new int[24] { 14, 15, 25, 5, 12, 1, 16, 20, 9, 9, 9, 7, 7, 7, -1, 11, 19, 30, 8, 10, 13, 28, 39, 39 }; - - var inserting_duplicates_passed = true; - try - { - // Insert values with duplicates - binarySearchTree.Insert(values); - } - catch - { - inserting_duplicates_passed = false; - } - - Assert.False(inserting_duplicates_passed, "Fail! Tree doesn't allow duplicates"); - - // - // Reduce values array to an array of distinct values - binarySearchTree.Clear(); - values = values.Distinct().ToArray(); - - var inserting_unique_passed = true; - try - { - // Insert unique values - binarySearchTree.Insert(values); - } - catch - { - inserting_unique_passed = false; - } - - Assert.True(inserting_unique_passed, "Fail! Inserting unique elements should pass!"); - - // ASSERT COUNT - Assert.Equal(binarySearchTree.Count, values.Length); + inserting_unique_passed = false; } - } + Assert.True(inserting_unique_passed, "Fail! Inserting unique elements should pass!"); -} + // ASSERT COUNT + Assert.Equal(binarySearchTree.Count, values.Length); + } +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/BinomialHeapsTest.cs b/UnitTest/DataStructuresTests/BinomialHeapsTest.cs index dea569dd..b74b02c7 100644 --- a/UnitTest/DataStructuresTests/BinomialHeapsTest.cs +++ b/UnitTest/DataStructuresTests/BinomialHeapsTest.cs @@ -1,37 +1,36 @@ using DataStructures.Heaps; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class BinomialHeapsTest { - public static class BinomialHeapsTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - int i = 37; - int numberOfItems = 100000; - BinomialMinHeap firstHeap = new BinomialMinHeap(); - BinomialMinHeap secondHeap = new BinomialMinHeap(); - BinomialMinHeap thirdHeap = new BinomialMinHeap(); + int i = 37; + int numberOfItems = 100000; + BinomialMinHeap firstHeap = new BinomialMinHeap(); + BinomialMinHeap secondHeap = new BinomialMinHeap(); + BinomialMinHeap thirdHeap = new BinomialMinHeap(); - for (i = 37; i != 0; i = (i + 37) % numberOfItems) - { - if (i % 2 == 0) - secondHeap.Add(i); - else - firstHeap.Add(i); - } - - firstHeap.Merge(secondHeap); - thirdHeap = firstHeap; + for (i = 37; i != 0; i = (i + 37) % numberOfItems) + { + if (i % 2 == 0) + secondHeap.Add(i); + else + firstHeap.Add(i); + } - for (i = 1; i <= thirdHeap.Count; i++) - { - var min = thirdHeap.ExtractMin(); - Assert.True(min == i, "WRONG MIN"); - } + firstHeap.Merge(secondHeap); + thirdHeap = firstHeap; - Assert.True(secondHeap.IsEmpty, "SECOND HEAP SHOULD BE EMPTY"); + for (i = 1; i <= thirdHeap.Count; i++) + { + var min = thirdHeap.ExtractMin(); + Assert.True(min == i, "WRONG MIN"); } + + Assert.True(secondHeap.IsEmpty, "SECOND HEAP SHOULD BE EMPTY"); } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/CircularBufferTest.cs b/UnitTest/DataStructuresTests/CircularBufferTest.cs index a385e813..fb30db4a 100644 --- a/UnitTest/DataStructuresTests/CircularBufferTest.cs +++ b/UnitTest/DataStructuresTests/CircularBufferTest.cs @@ -2,258 +2,257 @@ using System; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public class CircularBufferTest { - public class CircularBufferTest - { - [Fact] - public static void SetsFixedLength() - { - var circularBuffer = new CircularBuffer(3); - var length = circularBuffer.Length; - Assert.Equal(3, length); - } + [Fact] + public static void SetsFixedLength() + { + var circularBuffer = new CircularBuffer(3); + var length = circularBuffer.Length; + Assert.Equal(3, length); + } - [Fact] - public static void ChecksIsEmptyProperty() - { - var circularBuffer = new CircularBuffer(4); - Assert.True(circularBuffer.IsEmpty); - } + [Fact] + public static void ChecksIsEmptyProperty() + { + var circularBuffer = new CircularBuffer(4); + Assert.True(circularBuffer.IsEmpty); + } - [Fact] - public static void ChecksIsFilledProperty() - { - var circularBuffer = new CircularBuffer(3, false); - circularBuffer.Add(1); - circularBuffer.Add(2); - circularBuffer.Add(3); + [Fact] + public static void ChecksIsFilledProperty() + { + var circularBuffer = new CircularBuffer(3, false); + circularBuffer.Add(1); + circularBuffer.Add(2); + circularBuffer.Add(3); - Assert.True(circularBuffer.IsFilledUp); - } + Assert.True(circularBuffer.IsFilledUp); + } - [Fact] - public static void InitializesWithDefaultLengthOf10() - { - var circularBuffer = new CircularBuffer(); - var length = circularBuffer.Length; + [Fact] + public static void InitializesWithDefaultLengthOf10() + { + var circularBuffer = new CircularBuffer(); + var length = circularBuffer.Length; - Assert.Equal(10, length); - } - [Fact] - public static void ThrowsArguementOutOfRangeExceptionForLengthLessThanOne() + Assert.Equal(10, length); + } + [Fact] + public static void ThrowsArguementOutOfRangeExceptionForLengthLessThanOne() + { + Assert.Throws(() => { - Assert.Throws(() => - { - var circularBuffer = new CircularBuffer(0); - }); - Assert.Throws(() => - { - var circularBuffer = new CircularBuffer(-2); - }); - } - - [Fact] - public static void ThrowsCircularBufferFullExceptionWhenInsertingInFullBuffer() + var circularBuffer = new CircularBuffer(0); + }); + Assert.Throws(() => { - Assert.Throws(() => - { - var circularBuffer = new CircularBuffer(3, false); - circularBuffer.Add(1); - circularBuffer.Add(2); - circularBuffer.Add(3); - circularBuffer.Add(4); - }); - } + var circularBuffer = new CircularBuffer(-2); + }); + } - [Fact] - public static void WritesAndReadsValue() + [Fact] + public static void ThrowsCircularBufferFullExceptionWhenInsertingInFullBuffer() + { + Assert.Throws(() => { - var circularBuffer = new CircularBuffer(4); - circularBuffer.Add(13); - circularBuffer.Add(43); - circularBuffer.Add(23); + var circularBuffer = new CircularBuffer(3, false); + circularBuffer.Add(1); circularBuffer.Add(2); + circularBuffer.Add(3); + circularBuffer.Add(4); + }); + } - var result1 = circularBuffer.Pop(); - var result2 = circularBuffer.Pop(); - var result3 = circularBuffer.Pop(); - var result4 = circularBuffer.Pop(); - var result5 = circularBuffer.Pop(); - var result6 = circularBuffer.Pop(); - var result7 = circularBuffer.Pop(); - var result8 = circularBuffer.Pop(); + [Fact] + public static void WritesAndReadsValue() + { + var circularBuffer = new CircularBuffer(4); + circularBuffer.Add(13); + circularBuffer.Add(43); + circularBuffer.Add(23); + circularBuffer.Add(2); + + var result1 = circularBuffer.Pop(); + var result2 = circularBuffer.Pop(); + var result3 = circularBuffer.Pop(); + var result4 = circularBuffer.Pop(); + var result5 = circularBuffer.Pop(); + var result6 = circularBuffer.Pop(); + var result7 = circularBuffer.Pop(); + var result8 = circularBuffer.Pop(); - Assert.Equal(13, result1); - Assert.Equal(43, result2); - Assert.Equal(23, result3); - Assert.Equal(2, result4); - Assert.Equal(0, result5); - Assert.Equal(0, result6); - Assert.Equal(0, result7); - Assert.Equal(0, result8); - } + Assert.Equal(13, result1); + Assert.Equal(43, result2); + Assert.Equal(23, result3); + Assert.Equal(2, result4); + Assert.Equal(0, result5); + Assert.Equal(0, result6); + Assert.Equal(0, result7); + Assert.Equal(0, result8); + } - [Fact] - public static void TestingCantOverrideFunctionality() + [Fact] + public static void TestingCantOverrideFunctionality() + { + var circularBuffer = new CircularBuffer(3, false); + circularBuffer.Add(3); + circularBuffer.Add(34); + circularBuffer.Add(24); + // if it doesn't override, then it will throw CircularBufferFullException + Assert.Throws(() => { - var circularBuffer = new CircularBuffer(3, false); - circularBuffer.Add(3); - circularBuffer.Add(34); - circularBuffer.Add(24); - // if it doesn't override, then it will throw CircularBufferFullException - Assert.Throws(() => - { - circularBuffer.Add(2); - }); + circularBuffer.Add(2); + }); - // Ensuring that it reads the appropriate values in the buffer. - var result1 = circularBuffer.Pop(); - var result2 = circularBuffer.Pop(); - var result3 = circularBuffer.Pop(); + // Ensuring that it reads the appropriate values in the buffer. + var result1 = circularBuffer.Pop(); + var result2 = circularBuffer.Pop(); + var result3 = circularBuffer.Pop(); - Assert.Equal(3, result1); - Assert.Equal(34, result2); - Assert.Equal(24, result3); - } + Assert.Equal(3, result1); + Assert.Equal(34, result2); + Assert.Equal(24, result3); + } - [Fact] - public static void TestingWritingAndReadingSimultenouslyWithoutOverriding() - { - var circularBuffer = new CircularBuffer(3, false); - circularBuffer.Add(3); - circularBuffer.Add(34); - circularBuffer.Add(24); - var result1 = circularBuffer.Pop(); - var result2 = circularBuffer.Pop(); + [Fact] + public static void TestingWritingAndReadingSimultenouslyWithoutOverriding() + { + var circularBuffer = new CircularBuffer(3, false); + circularBuffer.Add(3); + circularBuffer.Add(34); + circularBuffer.Add(24); + var result1 = circularBuffer.Pop(); + var result2 = circularBuffer.Pop(); - circularBuffer.Add(4); - circularBuffer.Add(14); - var result3 = circularBuffer.Pop(); - var result4 = circularBuffer.Pop(); - var result5 = circularBuffer.Pop(); + circularBuffer.Add(4); + circularBuffer.Add(14); + var result3 = circularBuffer.Pop(); + var result4 = circularBuffer.Pop(); + var result5 = circularBuffer.Pop(); - Assert.Equal(24, result3); - Assert.Equal(4, result4); - Assert.Equal(14, result5); - } + Assert.Equal(24, result3); + Assert.Equal(4, result4); + Assert.Equal(14, result5); + } - [Fact] - public static void TestingICollectionImplementation() - { - var circularBuffer = new CircularBuffer(3, false); - circularBuffer.Add(3); - circularBuffer.Add(34); - circularBuffer.Add(24); - //Testing contains - Assert.True(circularBuffer.Contains(3)); + [Fact] + public static void TestingICollectionImplementation() + { + var circularBuffer = new CircularBuffer(3, false); + circularBuffer.Add(3); + circularBuffer.Add(34); + circularBuffer.Add(24); + //Testing contains + Assert.True(circularBuffer.Contains(3)); - //Testing CopyTo - var array = new byte[3]; - circularBuffer.CopyTo(array, 0); - Assert.Equal(3, array[0]); - Assert.Equal(34, array[1]); - Assert.Equal(24, array[2]); + //Testing CopyTo + var array = new byte[3]; + circularBuffer.CopyTo(array, 0); + Assert.Equal(3, array[0]); + Assert.Equal(34, array[1]); + Assert.Equal(24, array[2]); - //Testing Count - Assert.Equal(3, circularBuffer.Count); - //Testing clear - circularBuffer.Clear(); - Assert.Equal(0, circularBuffer.Pop()); - Assert.Equal(0, circularBuffer.Pop()); - Assert.Equal(0, circularBuffer.Pop()); - Assert.Empty(circularBuffer); - } - [Fact] - public static void TestingRemoveMethod() { - var circularBuffer = new CircularBuffer(5, false); - circularBuffer.Add(3); - circularBuffer.Add(34); - circularBuffer.Add(24); - circularBuffer.Add(31); - circularBuffer.Add(14); + //Testing Count + Assert.Equal(3, circularBuffer.Count); + //Testing clear + circularBuffer.Clear(); + Assert.Equal(0, circularBuffer.Pop()); + Assert.Equal(0, circularBuffer.Pop()); + Assert.Equal(0, circularBuffer.Pop()); + Assert.Empty(circularBuffer); + } + [Fact] + public static void TestingRemoveMethod() { + var circularBuffer = new CircularBuffer(5, false); + circularBuffer.Add(3); + circularBuffer.Add(34); + circularBuffer.Add(24); + circularBuffer.Add(31); + circularBuffer.Add(14); - //Removing default(T) from the buffer. buffer should not be affected since default is not contained - circularBuffer.Remove(default); - Assert.Equal(3, circularBuffer.Pop()); - Assert.Equal(34, circularBuffer.Pop()); - Assert.Equal(24, circularBuffer.Pop()); - Assert.Equal(31, circularBuffer.Pop()); - Assert.Equal(14, circularBuffer.Pop()); + //Removing default(T) from the buffer. buffer should not be affected since default is not contained + circularBuffer.Remove(default); + Assert.Equal(3, circularBuffer.Pop()); + Assert.Equal(34, circularBuffer.Pop()); + Assert.Equal(24, circularBuffer.Pop()); + Assert.Equal(31, circularBuffer.Pop()); + Assert.Equal(14, circularBuffer.Pop()); - //Filling the buffer again with some duplicate entries - circularBuffer.Add(3); - circularBuffer.Add(3); - circularBuffer.Add(3); - circularBuffer.Add(31); - circularBuffer.Add(14); + //Filling the buffer again with some duplicate entries + circularBuffer.Add(3); + circularBuffer.Add(3); + circularBuffer.Add(3); + circularBuffer.Add(31); + circularBuffer.Add(14); - circularBuffer.Remove(3); - Assert.Equal(5 - 3, circularBuffer.Count); + circularBuffer.Remove(3); + Assert.Equal(5 - 3, circularBuffer.Count); - circularBuffer = new CircularBuffer(3, false); - circularBuffer.Add(1); - circularBuffer.Add(2); - circularBuffer.Add(3); - Assert.Equal(3, circularBuffer.Count); - //Removing elements one by one from the end - circularBuffer.Remove(3); - circularBuffer.Remove(2); - circularBuffer.Remove(1); - Assert.Empty(circularBuffer); - //Adding elements back - circularBuffer.Add(1); - circularBuffer.Add(2); - circularBuffer.Add(3); - Assert.Equal(3, circularBuffer.Count); + circularBuffer = new CircularBuffer(3, false); + circularBuffer.Add(1); + circularBuffer.Add(2); + circularBuffer.Add(3); + Assert.Equal(3, circularBuffer.Count); + //Removing elements one by one from the end + circularBuffer.Remove(3); + circularBuffer.Remove(2); + circularBuffer.Remove(1); + Assert.Empty(circularBuffer); + //Adding elements back + circularBuffer.Add(1); + circularBuffer.Add(2); + circularBuffer.Add(3); + Assert.Equal(3, circularBuffer.Count); - //buffer would yield these results if it was poped initially - Assert.Equal(1, circularBuffer.Pop()); - Assert.Equal(2, circularBuffer.Pop()); - Assert.Equal(3, circularBuffer.Pop()); + //buffer would yield these results if it was poped initially + Assert.Equal(1, circularBuffer.Pop()); + Assert.Equal(2, circularBuffer.Pop()); + Assert.Equal(3, circularBuffer.Pop()); - //Test for removing duplicate values of default(T) - circularBuffer = new CircularBuffer(12, false); - circularBuffer.Add(1); - circularBuffer.Add(0); - circularBuffer.Add(2); - circularBuffer.Add(0); - circularBuffer.Add(3); - circularBuffer.Add(0); - circularBuffer.Add(4); - circularBuffer.Add(0); - circularBuffer.Add(5); + //Test for removing duplicate values of default(T) + circularBuffer = new CircularBuffer(12, false); + circularBuffer.Add(1); + circularBuffer.Add(0); + circularBuffer.Add(2); + circularBuffer.Add(0); + circularBuffer.Add(3); + circularBuffer.Add(0); + circularBuffer.Add(4); + circularBuffer.Add(0); + circularBuffer.Add(5); - circularBuffer.Remove(0); - Assert.Equal(5, circularBuffer.Count); + circularBuffer.Remove(0); + Assert.Equal(5, circularBuffer.Count); - Assert.Equal(1, circularBuffer.Pop()); - Assert.Equal(2, circularBuffer.Pop()); - Assert.Equal(3, circularBuffer.Pop()); - Assert.Equal(4, circularBuffer.Pop()); - Assert.Equal(5, circularBuffer.Pop()); + Assert.Equal(1, circularBuffer.Pop()); + Assert.Equal(2, circularBuffer.Pop()); + Assert.Equal(3, circularBuffer.Pop()); + Assert.Equal(4, circularBuffer.Pop()); + Assert.Equal(5, circularBuffer.Pop()); - //Test for removing duplicate values of default(T) for strings - var stringBuffer = new CircularBuffer(10, false); - stringBuffer.Add("one"); - stringBuffer.Add(null); - stringBuffer.Add("two"); - stringBuffer.Add(null); - stringBuffer.Add("three"); - stringBuffer.Add(null); - stringBuffer.Add("four"); - stringBuffer.Add(null); - stringBuffer.Add("five"); + //Test for removing duplicate values of default(T) for strings + var stringBuffer = new CircularBuffer(10, false); + stringBuffer.Add("one"); + stringBuffer.Add(null); + stringBuffer.Add("two"); + stringBuffer.Add(null); + stringBuffer.Add("three"); + stringBuffer.Add(null); + stringBuffer.Add("four"); + stringBuffer.Add(null); + stringBuffer.Add("five"); - stringBuffer.Remove(null); - Assert.Equal(5, stringBuffer.Count); + stringBuffer.Remove(null); + Assert.Equal(5, stringBuffer.Count); - Assert.Equal("one", stringBuffer.Pop()); - Assert.Equal("two", stringBuffer.Pop()); - Assert.Equal("three", stringBuffer.Pop()); - Assert.Equal("four", stringBuffer.Pop()); - Assert.Equal("five", stringBuffer.Pop()); - } + Assert.Equal("one", stringBuffer.Pop()); + Assert.Equal("two", stringBuffer.Pop()); + Assert.Equal("three", stringBuffer.Pop()); + Assert.Equal("four", stringBuffer.Pop()); + Assert.Equal("five", stringBuffer.Pop()); } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/CliqueGraphTest.cs b/UnitTest/DataStructuresTests/CliqueGraphTest.cs index 5028140b..8b86797f 100644 --- a/UnitTest/DataStructuresTests/CliqueGraphTest.cs +++ b/UnitTest/DataStructuresTests/CliqueGraphTest.cs @@ -1,123 +1,121 @@ using System; using DataStructures.Graphs; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class CliqueGraphTest { - public static class CliqueGraphTest + public const int vertexPerCluster = 10; + public const int numClusters = 10; + static CliqueGraph testGraph = new CliqueGraph(); + static IGraph compareGraph; + + static void MakeGraph(IGraph gra) { - public const int vertexPerCluster = 10; - public const int numClusters = 10; - static CliqueGraph testGraph = new CliqueGraph(); - static IGraph compareGraph; - static void MakeGraph(IGraph gra) + for (int i = 0; i < numClusters; i++) { - - for (int i = 0; i < numClusters; i++) + for (int j = 0; j < vertexPerCluster; j++) { - for (int j = 0; j < vertexPerCluster; j++) - { - gra.AddVertex(new ComparableTuple(i, j)); - } + gra.AddVertex(new ComparableTuple(i, j)); } + } - for (int i = 0; i < numClusters; i++) - { - MakeCluster(gra, i); - System.Diagnostics.Debug.WriteLine(string.Format("Cluster {0} finished.", i)); - } + for (int i = 0; i < numClusters; i++) + { + MakeCluster(gra, i); + System.Diagnostics.Debug.WriteLine(string.Format("Cluster {0} finished.", i)); + } - for (int i = 0; i < numClusters; i++) + for (int i = 0; i < numClusters; i++) + { + for (int j = 0; j < numClusters; j++) { - for (int j = 0; j < numClusters; j++) - { - gra.AddEdge(new ComparableTuple(i, 0), new ComparableTuple(j, 0)); - } + gra.AddEdge(new ComparableTuple(i, 0), new ComparableTuple(j, 0)); } - - System.Diagnostics.Debug.WriteLine(string.Format("Graph connected")); } - static void MakeCluster(IGraph gra, int i) + System.Diagnostics.Debug.WriteLine(string.Format("Graph connected")); + } + + static void MakeCluster(IGraph gra, int i) + { + for (int j = 0; j < vertexPerCluster; j++) { - for (int j = 0; j < vertexPerCluster; j++) + for (int k = j; k < vertexPerCluster; k++) { - for (int k = j; k < vertexPerCluster; k++) - { - gra.AddEdge(new ComparableTuple(i, j), new ComparableTuple(i, k)); - } + gra.AddEdge(new ComparableTuple(i, j), new ComparableTuple(i, k)); } } + } - public static void DoTest() - { - compareGraph = new UndirectedDenseGraph(numClusters * vertexPerCluster); - MakeGraph(compareGraph); + public static void DoTest() + { + compareGraph = new UndirectedDenseGraph(numClusters * vertexPerCluster); + MakeGraph(compareGraph); - testGraph = new CliqueGraph(compareGraph); - // ICollection component = testGraph.GetConnectedComponent(new ComparableTuple(0, 0)); - // DataStructures.Lists.DLinkedList neighbor = testGraph.Neighbours(new ComparableTuple(0, 0)); + testGraph = new CliqueGraph(compareGraph); + // ICollection component = testGraph.GetConnectedComponent(new ComparableTuple(0, 0)); + // DataStructures.Lists.DLinkedList neighbor = testGraph.Neighbours(new ComparableTuple(0, 0)); - testGraph.RemoveEdge(new ComparableTuple(0, 0), new ComparableTuple(1, 0)); + testGraph.RemoveEdge(new ComparableTuple(0, 0), new ComparableTuple(1, 0)); - IGraph.Clique> dualGraph = testGraph.buildDualGraph(); + IGraph.Clique> dualGraph = testGraph.buildDualGraph(); - foreach (var x in dualGraph.Vertices) + foreach (var x in dualGraph.Vertices) + { + foreach (var y in dualGraph.Neighbours(x)) { - foreach (var y in dualGraph.Neighbours(x)) - { - System.Diagnostics.Debug.WriteLine(string.Format("{0}-{1}", x, y)); - } + System.Diagnostics.Debug.WriteLine(string.Format("{0}-{1}", x, y)); } + } - // CliqueGraph.Edges test - foreach (var edge in testGraph.Edges) - { - //System.Diagnostics.Debug.WriteLine(string.Format("{0} -> {1}\t", edge.Source, edge.Destination)); - } + // CliqueGraph.Edges test + foreach (var edge in testGraph.Edges) + { + //System.Diagnostics.Debug.WriteLine(string.Format("{0} -> {1}\t", edge.Source, edge.Destination)); + } - foreach (var edge in testGraph.OutgoingEdges(new ComparableTuple(0, 0))) - { - System.Diagnostics.Debug.WriteLine(string.Format("{0} -> {1}\t", edge.Source, edge.Destination)); - } + foreach (var edge in testGraph.OutgoingEdges(new ComparableTuple(0, 0))) + { + System.Diagnostics.Debug.WriteLine(string.Format("{0} -> {1}\t", edge.Source, edge.Destination)); + } - } } +} - class ComparableTuple : Tuple, IComparable, IEquatable - { - #region IComparable implementation - +class ComparableTuple : Tuple, IComparable, IEquatable +{ + #region IComparable implementation - int IComparable.CompareTo(ComparableTuple other) - { - int myInt = ToInt; - int otherInt = other.ToInt; - return myInt < otherInt ? -1 : myInt > otherInt ? 1 : 0; - } - #endregion + int IComparable.CompareTo(ComparableTuple other) + { + int myInt = ToInt; + int otherInt = other.ToInt; + return myInt < otherInt ? -1 : myInt > otherInt ? 1 : 0; + } - #region IEquatable implementation + #endregion - bool IEquatable.Equals(ComparableTuple other) - { - return ToInt == other.ToInt; - } + #region IEquatable implementation - #endregion + bool IEquatable.Equals(ComparableTuple other) + { + return ToInt == other.ToInt; + } - static readonly int multiplier = CliqueGraphTest.numClusters; + #endregion - public ComparableTuple(int item1, int item2) - : base(item1, item2) - { + static readonly int multiplier = CliqueGraphTest.numClusters; - } + public ComparableTuple(int item1, int item2) + : base(item1, item2) + { - int ToInt => Item1 * multiplier + Item2; } -} + int ToInt => Item1 * multiplier + Item2; +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/CuckooHashTableTest.cs b/UnitTest/DataStructuresTests/CuckooHashTableTest.cs index b435094d..b8586fed 100644 --- a/UnitTest/DataStructuresTests/CuckooHashTableTest.cs +++ b/UnitTest/DataStructuresTests/CuckooHashTableTest.cs @@ -1,45 +1,44 @@ using DataStructures.Dictionaries; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class CuckooHashTableTest { - public static class CuckooHashTableTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - var cuckooTable = new CuckooHashTable(); + var cuckooTable = new CuckooHashTable(); - cuckooTable.Add("Ahmad", 10); - cuckooTable.Add("Oliver", 11); - cuckooTable.Add("Konstantinos", 12); - cuckooTable.Add("Olympos", 13); - cuckooTable.Add("Bic", 14); - cuckooTable.Add("Carter", 15); - cuckooTable.Add("Sameeros", 16); + cuckooTable.Add("Ahmad", 10); + cuckooTable.Add("Oliver", 11); + cuckooTable.Add("Konstantinos", 12); + cuckooTable.Add("Olympos", 13); + cuckooTable.Add("Bic", 14); + cuckooTable.Add("Carter", 15); + cuckooTable.Add("Sameeros", 16); - var Ahmad = cuckooTable["Ahmad"]; - Assert.True(Ahmad == 10); + var Ahmad = cuckooTable["Ahmad"]; + Assert.True(Ahmad == 10); - var Oliver = cuckooTable["Oliver"]; - Assert.True(Oliver == 11); + var Oliver = cuckooTable["Oliver"]; + Assert.True(Oliver == 11); - var Konstantinos = cuckooTable["Konstantinos"]; - Assert.True(Konstantinos == 12); + var Konstantinos = cuckooTable["Konstantinos"]; + Assert.True(Konstantinos == 12); - var Olympos = cuckooTable["Olympos"]; - Assert.True(Olympos == 13); + var Olympos = cuckooTable["Olympos"]; + Assert.True(Olympos == 13); - var Bic = cuckooTable["Bic"]; - Assert.True(Bic == 14); + var Bic = cuckooTable["Bic"]; + Assert.True(Bic == 14); - var Carter = cuckooTable["Carter"]; - Assert.True(Carter == 15); + var Carter = cuckooTable["Carter"]; + Assert.True(Carter == 15); - var Sameeros = cuckooTable["Sameeros"]; - Assert.True(Sameeros == 16); + var Sameeros = cuckooTable["Sameeros"]; + Assert.True(Sameeros == 16); - cuckooTable.Clear(); - } + cuckooTable.Clear(); } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/DLinkedListTest.cs b/UnitTest/DataStructuresTests/DLinkedListTest.cs index 0045e650..0b448797 100644 --- a/UnitTest/DataStructuresTests/DLinkedListTest.cs +++ b/UnitTest/DataStructuresTests/DLinkedListTest.cs @@ -2,129 +2,127 @@ using System; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class DLinkedListTest { - public static class DLinkedListTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() + DLinkedList listOfStrings = new DLinkedList(); + + listOfStrings.Append("zero"); + listOfStrings.Append("fst"); + listOfStrings.Append("sec"); + listOfStrings.Append("trd"); + listOfStrings.Append("for"); + listOfStrings.Append("fft"); + listOfStrings.Append("sxt"); + listOfStrings.Append("svn"); + listOfStrings.Append("egt"); + + // Remove 1st + listOfStrings.RemoveAt(0); + Assert.True(listOfStrings[0] == "fst", "Wrong first element."); + + // Remove 4th + listOfStrings.RemoveAt(4); + Console.WriteLine("Remove At 4:\r\n" + listOfStrings.ToReadable()); + Assert.True(listOfStrings[4] == "sxt", "Wrong 4th element."); + + // Remove 5th and 6th + // Note that after removing 5th, the old element at index 6 becomes at index 5. + listOfStrings.RemoveAt(5); + listOfStrings.RemoveAt(5); + Assert.True(listOfStrings[4] == "sxt", "Wrong element at index 5."); + Assert.True(listOfStrings.Count < 6, "Wrong element at index 6. There must be no element at index 5."); + + // Remove 3rd + listOfStrings.RemoveAt(listOfStrings.Count - 1); + Assert.True(listOfStrings[3] == "for", "Wrong element at index 3."); + + // Remove 1st + listOfStrings.RemoveAt(0); + Assert.True(listOfStrings[0] == "sec", "Wrong element at index 0."); + + listOfStrings.Prepend("semsem3"); + listOfStrings.Prepend("semsem2"); + listOfStrings.Prepend("semsem1"); + + listOfStrings.InsertAt("InsertedAtLast1", listOfStrings.Count); + listOfStrings.InsertAt("InsertedAtLast2", listOfStrings.Count); + listOfStrings.InsertAt("InsertedAtMiddle", listOfStrings.Count / 2); + listOfStrings.InsertAt("InsertedAt 4", 4); + listOfStrings.InsertAt("InsertedAt 9", 9); + listOfStrings.InsertAfter("InsertedAfter 11", 11); + + // Test the remove item method + listOfStrings.Remove("trd"); + + listOfStrings.Remove("InsertedAt 9"); + var arrayVersion = listOfStrings.ToArray(); + Assert.True(arrayVersion.Length == listOfStrings.Count); + + /****************************************************************************************/ + + var stringsIterators = listOfStrings.GetEnumerator(); + stringsIterators.MoveNext(); + Assert.True(stringsIterators.Current == listOfStrings[0], "Wrong enumeration."); + if (stringsIterators.MoveNext() == true) { - DLinkedList listOfStrings = new DLinkedList(); - - listOfStrings.Append("zero"); - listOfStrings.Append("fst"); - listOfStrings.Append("sec"); - listOfStrings.Append("trd"); - listOfStrings.Append("for"); - listOfStrings.Append("fft"); - listOfStrings.Append("sxt"); - listOfStrings.Append("svn"); - listOfStrings.Append("egt"); - - // Remove 1st - listOfStrings.RemoveAt(0); - Assert.True(listOfStrings[0] == "fst", "Wrong first element."); - - // Remove 4th - listOfStrings.RemoveAt(4); - Console.WriteLine("Remove At 4:\r\n" + listOfStrings.ToReadable()); - Assert.True(listOfStrings[4] == "sxt", "Wrong 4th element."); - - // Remove 5th and 6th - // Note that after removing 5th, the old element at index 6 becomes at index 5. - listOfStrings.RemoveAt(5); - listOfStrings.RemoveAt(5); - Assert.True(listOfStrings[4] == "sxt", "Wrong element at index 5."); - Assert.True(listOfStrings.Count < 6, "Wrong element at index 6. There must be no element at index 5."); - - // Remove 3rd - listOfStrings.RemoveAt(listOfStrings.Count - 1); - Assert.True(listOfStrings[3] == "for", "Wrong element at index 3."); - - // Remove 1st - listOfStrings.RemoveAt(0); - Assert.True(listOfStrings[0] == "sec", "Wrong element at index 0."); - - listOfStrings.Prepend("semsem3"); - listOfStrings.Prepend("semsem2"); - listOfStrings.Prepend("semsem1"); - - listOfStrings.InsertAt("InsertedAtLast1", listOfStrings.Count); - listOfStrings.InsertAt("InsertedAtLast2", listOfStrings.Count); - listOfStrings.InsertAt("InsertedAtMiddle", listOfStrings.Count / 2); - listOfStrings.InsertAt("InsertedAt 4", 4); - listOfStrings.InsertAt("InsertedAt 9", 9); - listOfStrings.InsertAfter("InsertedAfter 11", 11); - - // Test the remove item method - listOfStrings.Remove("trd"); - - listOfStrings.Remove("InsertedAt 9"); - var arrayVersion = listOfStrings.ToArray(); - Assert.True(arrayVersion.Length == listOfStrings.Count); - - /****************************************************************************************/ - - var stringsIterators = listOfStrings.GetEnumerator(); - stringsIterators.MoveNext(); - Assert.True(stringsIterators.Current == listOfStrings[0], "Wrong enumeration."); - if (stringsIterators.MoveNext() == true) - { - Assert.True(stringsIterators.Current == listOfStrings[1], "Wrong enumeration."); - } - - stringsIterators.Dispose(); - Assert.True(listOfStrings != null && listOfStrings.Count > 0, "Enumartor has side effects!"); - - /****************************************************************************************/ - var listOfNumbers = new DLinkedList(); - listOfNumbers.Append(23); - listOfNumbers.Append(42); - listOfNumbers.Append(4); - listOfNumbers.Append(16); - listOfNumbers.Append(8); - listOfNumbers.Append(15); - listOfNumbers.Append(9); - listOfNumbers.Append(55); - listOfNumbers.Append(0); - listOfNumbers.Append(34); - listOfNumbers.Append(12); - listOfNumbers.Append(2); - - listOfNumbers.SelectionSort(); - var intArray = listOfNumbers.ToArray(); - Assert.True(intArray[0] == 0 && intArray[intArray.Length - 1] == 55, "Wrong sorting!"); + Assert.True(stringsIterators.Current == listOfStrings[1], "Wrong enumeration."); } - /// - ///Check SelectionSort method - /// - /// - [Fact] - public static void TestSelectionSort() - { - var listOfNumbers = new DLinkedList(); - listOfNumbers.Append(23); - listOfNumbers.Append(42); - listOfNumbers.Append(4); - listOfNumbers.Append(16); - listOfNumbers.Append(8); - listOfNumbers.Append(15); - listOfNumbers.Append(9); - listOfNumbers.Append(55); - listOfNumbers.Append(0); - - listOfNumbers.SelectionSort(); - var intArray = listOfNumbers.ToArray(); - var i = 0; - while (i < intArray.Length - 1) - { - Assert.True(intArray[i] <= intArray[i + 1], "Wrong sorting at index: " + i); - ++i; - } + stringsIterators.Dispose(); + Assert.True(listOfStrings != null && listOfStrings.Count > 0, "Enumartor has side effects!"); + + /****************************************************************************************/ + var listOfNumbers = new DLinkedList(); + listOfNumbers.Append(23); + listOfNumbers.Append(42); + listOfNumbers.Append(4); + listOfNumbers.Append(16); + listOfNumbers.Append(8); + listOfNumbers.Append(15); + listOfNumbers.Append(9); + listOfNumbers.Append(55); + listOfNumbers.Append(0); + listOfNumbers.Append(34); + listOfNumbers.Append(12); + listOfNumbers.Append(2); + + listOfNumbers.SelectionSort(); + var intArray = listOfNumbers.ToArray(); + Assert.True(intArray[0] == 0 && intArray[intArray.Length - 1] == 55, "Wrong sorting!"); + } + /// + ///Check SelectionSort method + /// + /// + [Fact] + public static void TestSelectionSort() + { + var listOfNumbers = new DLinkedList(); + listOfNumbers.Append(23); + listOfNumbers.Append(42); + listOfNumbers.Append(4); + listOfNumbers.Append(16); + listOfNumbers.Append(8); + listOfNumbers.Append(15); + listOfNumbers.Append(9); + listOfNumbers.Append(55); + listOfNumbers.Append(0); + + listOfNumbers.SelectionSort(); + var intArray = listOfNumbers.ToArray(); + var i = 0; + while (i < intArray.Length - 1) + { + Assert.True(intArray[i] <= intArray[i + 1], "Wrong sorting at index: " + i); + ++i; } } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/GraphsDirectedDenseGraphTest.cs b/UnitTest/DataStructuresTests/GraphsDirectedDenseGraphTest.cs index 10f77c33..a4f38b46 100644 --- a/UnitTest/DataStructuresTests/GraphsDirectedDenseGraphTest.cs +++ b/UnitTest/DataStructuresTests/GraphsDirectedDenseGraphTest.cs @@ -2,119 +2,116 @@ using System.Linq; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class GraphsDirectedDenseGraphTest { - public static class GraphsDirectedDenseGraphTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - var graph = new DirectedDenseGraph(); - - var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }; - - graph.AddVertices(verticesSet1); - - graph.AddEdge("a", "s"); - graph.AddEdge("a", "z"); - graph.AddEdge("s", "x"); - graph.AddEdge("x", "d"); - graph.AddEdge("x", "c"); - graph.AddEdge("x", "a"); - graph.AddEdge("d", "f"); - graph.AddEdge("d", "c"); - graph.AddEdge("d", "s"); - graph.AddEdge("c", "f"); - graph.AddEdge("c", "v"); - graph.AddEdge("c", "d"); - graph.AddEdge("v", "f"); - graph.AddEdge("f", "c"); - - var allEdges = graph.Edges.ToList(); - - Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 14, "Wrong edges count."); - Assert.True(graph.EdgesCount == allEdges.Count, "Wrong edges count."); - - Assert.True(graph.OutgoingEdges("a").ToList().Count == 2, "Wrong outgoing edges from 'a'."); - Assert.True(graph.OutgoingEdges("s").ToList().Count == 1, "Wrong outgoing edges from 's'."); - Assert.True(graph.OutgoingEdges("d").ToList().Count == 3, "Wrong outgoing edges from 'd'."); - Assert.True(graph.OutgoingEdges("x").ToList().Count == 3, "Wrong outgoing edges from 'x'."); - Assert.True(graph.OutgoingEdges("c").ToList().Count == 3, "Wrong outgoing edges from 'c'."); - Assert.True(graph.OutgoingEdges("v").ToList().Count == 1, "Wrong outgoing edges from 'v'."); - Assert.True(graph.OutgoingEdges("f").ToList().Count == 1, "Wrong outgoing edges from 'f'."); - Assert.True(graph.OutgoingEdges("z").ToList().Count == 0, "Wrong outgoing edges from 'z'."); - - Assert.True(graph.IncomingEdges("a").ToList().Count == 1, "Wrong incoming edges from 'a'."); - Assert.True(graph.IncomingEdges("s").ToList().Count == 2, "Wrong incoming edges from 's'."); - Assert.True(graph.IncomingEdges("d").ToList().Count == 2, "Wrong incoming edges from 'd'."); - Assert.True(graph.IncomingEdges("x").ToList().Count == 1, "Wrong incoming edges from 'x'."); - Assert.True(graph.IncomingEdges("c").ToList().Count == 3, "Wrong incoming edges from 'c'."); - Assert.True(graph.IncomingEdges("v").ToList().Count == 1, "Wrong incoming edges from 'v'."); - Assert.True(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); - Assert.True(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); - - graph.RemoveEdge("d", "c"); - graph.RemoveEdge("c", "v"); - graph.RemoveEdge("a", "z"); - Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 11, "Wrong edges count."); - - graph.RemoveVertex("x"); - Assert.True(graph.VerticesCount == 7, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 7, "Wrong edges count."); - - graph.AddVertex("x"); - graph.AddEdge("s", "x"); - graph.AddEdge("x", "d"); - graph.AddEdge("x", "c"); - graph.AddEdge("x", "a"); - graph.AddEdge("d", "c"); - graph.AddEdge("c", "v"); - graph.AddEdge("a", "z"); - - // BFS from A - // Walk the graph using BFS from A: - Assert.True(graph.BreadthFirstWalk("a").SequenceEqual(new string[] { "a", "z", "s", "x", "d", "c", "f", "v" })); - - // DFS from A - // Walk the graph using DFS from A: - Assert.True(graph.DepthFirstWalk("a").SequenceEqual(new string[] { "a", "s", "x", "c", "v", "f", "d", "z" })); - - // BFS from F - // Walk the graph using BFS from F: - Assert.True(graph.BreadthFirstWalk("f").SequenceEqual(new string[] { "f", "c", "d", "v", "s", "x", "a", "z" })); - - - // DFS from F - // Walk the graph using DFS from F: - Assert.True(graph.DepthFirstWalk("f").SequenceEqual(new string[] { "f", "c", "v", "d", "s", "x", "a", "z" })); - - graph.Clear(); - // Cleared the graph from all vertices and edges - - var verticesSet2 = new string[] { "a", "b", "c", "d", "e", "f" }; - - graph.AddVertices(verticesSet2); - - graph.AddEdge("a", "b"); - graph.AddEdge("a", "d"); - graph.AddEdge("b", "e"); - graph.AddEdge("d", "b"); - graph.AddEdge("d", "e"); - graph.AddEdge("e", "c"); - graph.AddEdge("c", "f"); - graph.AddEdge("f", "f"); - - Assert.True(graph.VerticesCount == 6, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 8, "Wrong edges count."); - - // Walk the graph using DFS: - Assert.True(graph.DepthFirstWalk().SequenceEqual(new string[] { "a", "d", "e", "c", "f", "b" })); - - } + var graph = new DirectedDenseGraph(); + + var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }; + + graph.AddVertices(verticesSet1); + + graph.AddEdge("a", "s"); + graph.AddEdge("a", "z"); + graph.AddEdge("s", "x"); + graph.AddEdge("x", "d"); + graph.AddEdge("x", "c"); + graph.AddEdge("x", "a"); + graph.AddEdge("d", "f"); + graph.AddEdge("d", "c"); + graph.AddEdge("d", "s"); + graph.AddEdge("c", "f"); + graph.AddEdge("c", "v"); + graph.AddEdge("c", "d"); + graph.AddEdge("v", "f"); + graph.AddEdge("f", "c"); + + var allEdges = graph.Edges.ToList(); + + Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 14, "Wrong edges count."); + Assert.True(graph.EdgesCount == allEdges.Count, "Wrong edges count."); + + Assert.True(graph.OutgoingEdges("a").ToList().Count == 2, "Wrong outgoing edges from 'a'."); + Assert.True(graph.OutgoingEdges("s").ToList().Count == 1, "Wrong outgoing edges from 's'."); + Assert.True(graph.OutgoingEdges("d").ToList().Count == 3, "Wrong outgoing edges from 'd'."); + Assert.True(graph.OutgoingEdges("x").ToList().Count == 3, "Wrong outgoing edges from 'x'."); + Assert.True(graph.OutgoingEdges("c").ToList().Count == 3, "Wrong outgoing edges from 'c'."); + Assert.True(graph.OutgoingEdges("v").ToList().Count == 1, "Wrong outgoing edges from 'v'."); + Assert.True(graph.OutgoingEdges("f").ToList().Count == 1, "Wrong outgoing edges from 'f'."); + Assert.True(graph.OutgoingEdges("z").ToList().Count == 0, "Wrong outgoing edges from 'z'."); + + Assert.True(graph.IncomingEdges("a").ToList().Count == 1, "Wrong incoming edges from 'a'."); + Assert.True(graph.IncomingEdges("s").ToList().Count == 2, "Wrong incoming edges from 's'."); + Assert.True(graph.IncomingEdges("d").ToList().Count == 2, "Wrong incoming edges from 'd'."); + Assert.True(graph.IncomingEdges("x").ToList().Count == 1, "Wrong incoming edges from 'x'."); + Assert.True(graph.IncomingEdges("c").ToList().Count == 3, "Wrong incoming edges from 'c'."); + Assert.True(graph.IncomingEdges("v").ToList().Count == 1, "Wrong incoming edges from 'v'."); + Assert.True(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); + Assert.True(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); + + graph.RemoveEdge("d", "c"); + graph.RemoveEdge("c", "v"); + graph.RemoveEdge("a", "z"); + Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 11, "Wrong edges count."); + + graph.RemoveVertex("x"); + Assert.True(graph.VerticesCount == 7, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 7, "Wrong edges count."); + + graph.AddVertex("x"); + graph.AddEdge("s", "x"); + graph.AddEdge("x", "d"); + graph.AddEdge("x", "c"); + graph.AddEdge("x", "a"); + graph.AddEdge("d", "c"); + graph.AddEdge("c", "v"); + graph.AddEdge("a", "z"); + + // BFS from A + // Walk the graph using BFS from A: + Assert.True(graph.BreadthFirstWalk("a").SequenceEqual(new string[] { "a", "z", "s", "x", "d", "c", "f", "v" })); + + // DFS from A + // Walk the graph using DFS from A: + Assert.True(graph.DepthFirstWalk("a").SequenceEqual(new string[] { "a", "s", "x", "c", "v", "f", "d", "z" })); + + // BFS from F + // Walk the graph using BFS from F: + Assert.True(graph.BreadthFirstWalk("f").SequenceEqual(new string[] { "f", "c", "d", "v", "s", "x", "a", "z" })); + + + // DFS from F + // Walk the graph using DFS from F: + Assert.True(graph.DepthFirstWalk("f").SequenceEqual(new string[] { "f", "c", "v", "d", "s", "x", "a", "z" })); + + graph.Clear(); + // Cleared the graph from all vertices and edges + + var verticesSet2 = new string[] { "a", "b", "c", "d", "e", "f" }; + + graph.AddVertices(verticesSet2); + + graph.AddEdge("a", "b"); + graph.AddEdge("a", "d"); + graph.AddEdge("b", "e"); + graph.AddEdge("d", "b"); + graph.AddEdge("d", "e"); + graph.AddEdge("e", "c"); + graph.AddEdge("c", "f"); + graph.AddEdge("f", "f"); + + Assert.True(graph.VerticesCount == 6, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 8, "Wrong edges count."); + + // Walk the graph using DFS: + Assert.True(graph.DepthFirstWalk().SequenceEqual(new string[] { "a", "d", "e", "c", "f", "b" })); } -} - +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/GraphsDirectedSparseGraphTest.cs b/UnitTest/DataStructuresTests/GraphsDirectedSparseGraphTest.cs index 373127f8..714dd664 100644 --- a/UnitTest/DataStructuresTests/GraphsDirectedSparseGraphTest.cs +++ b/UnitTest/DataStructuresTests/GraphsDirectedSparseGraphTest.cs @@ -3,145 +3,143 @@ using System.Linq; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class GraphsDirectedSparseGraphTest { - public static class GraphsDirectedSparseGraphTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() + var graph = new DirectedSparseGraph(); + + var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }; + + graph.AddVertices(verticesSet1); + + graph.AddEdge("a", "s"); + graph.AddEdge("a", "z"); + graph.AddEdge("s", "x"); + graph.AddEdge("x", "d"); + graph.AddEdge("x", "c"); + graph.AddEdge("x", "a"); + graph.AddEdge("d", "f"); + graph.AddEdge("d", "c"); + graph.AddEdge("d", "s"); + graph.AddEdge("c", "f"); + graph.AddEdge("c", "v"); + graph.AddEdge("c", "d"); + graph.AddEdge("v", "f"); + graph.AddEdge("f", "c"); + + var allEdges = graph.Edges.ToList(); + + Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 14, "Wrong edges count."); + Assert.True(graph.EdgesCount == allEdges.Count, "Wrong edges count."); + + Assert.True(graph.OutgoingEdges("a").ToList().Count == 2, "Wrong outgoing edges from 'a'."); + Assert.True(graph.OutgoingEdges("s").ToList().Count == 1, "Wrong outgoing edges from 's'."); + Assert.True(graph.OutgoingEdges("d").ToList().Count == 3, "Wrong outgoing edges from 'd'."); + Assert.True(graph.OutgoingEdges("x").ToList().Count == 3, "Wrong outgoing edges from 'x'."); + Assert.True(graph.OutgoingEdges("c").ToList().Count == 3, "Wrong outgoing edges from 'c'."); + Assert.True(graph.OutgoingEdges("v").ToList().Count == 1, "Wrong outgoing edges from 'v'."); + Assert.True(graph.OutgoingEdges("f").ToList().Count == 1, "Wrong outgoing edges from 'f'."); + Assert.True(graph.OutgoingEdges("z").ToList().Count == 0, "Wrong outgoing edges from 'z'."); + + Assert.True(graph.IncomingEdges("a").ToList().Count == 1, "Wrong incoming edges from 'a'."); + Assert.True(graph.IncomingEdges("s").ToList().Count == 2, "Wrong incoming edges from 's'."); + Assert.True(graph.IncomingEdges("d").ToList().Count == 2, "Wrong incoming edges from 'd'."); + Assert.True(graph.IncomingEdges("x").ToList().Count == 1, "Wrong incoming edges from 'x'."); + Assert.True(graph.IncomingEdges("c").ToList().Count == 3, "Wrong incoming edges from 'c'."); + Assert.True(graph.IncomingEdges("v").ToList().Count == 1, "Wrong incoming edges from 'v'."); + Assert.True(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); + Assert.True(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); + + graph.RemoveEdge("d", "c"); + graph.RemoveEdge("c", "v"); + graph.RemoveEdge("a", "z"); + + Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 11, "Wrong edges count."); + + graph.RemoveVertex("x"); + Assert.True(graph.VerticesCount == 7, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 7, "Wrong edges count."); + + graph.AddVertex("x"); + graph.AddEdge("s", "x"); + graph.AddEdge("x", "d"); + graph.AddEdge("x", "c"); + graph.AddEdge("x", "a"); + graph.AddEdge("d", "c"); + graph.AddEdge("c", "v"); + graph.AddEdge("a", "z"); + + // BFS from A + // Walk the graph using BFS from A: + var bfsWalk = graph.BreadthFirstWalk("a"); + // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in bfsWalk) + { + Console.Write(String.Format("({0})", node)); + } + + // DFS from A + // Walk the graph using DFS from A: + var dfsWalk = graph.DepthFirstWalk("a"); + // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in dfsWalk) + { + Console.Write(String.Format("({0})", node)); + } + + // BFS from F + Console.WriteLine("Walk the graph using BFS from F:"); + bfsWalk = graph.BreadthFirstWalk("f"); + // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in bfsWalk) + { + Console.Write(String.Format("({0})", node)); + } + + // DFS from F + // Walk the graph using DFS from F: + dfsWalk = graph.DepthFirstWalk("f"); + // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in dfsWalk) { - var graph = new DirectedSparseGraph(); - - var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }; - - graph.AddVertices(verticesSet1); - - graph.AddEdge("a", "s"); - graph.AddEdge("a", "z"); - graph.AddEdge("s", "x"); - graph.AddEdge("x", "d"); - graph.AddEdge("x", "c"); - graph.AddEdge("x", "a"); - graph.AddEdge("d", "f"); - graph.AddEdge("d", "c"); - graph.AddEdge("d", "s"); - graph.AddEdge("c", "f"); - graph.AddEdge("c", "v"); - graph.AddEdge("c", "d"); - graph.AddEdge("v", "f"); - graph.AddEdge("f", "c"); - - var allEdges = graph.Edges.ToList(); - - Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 14, "Wrong edges count."); - Assert.True(graph.EdgesCount == allEdges.Count, "Wrong edges count."); - - Assert.True(graph.OutgoingEdges("a").ToList().Count == 2, "Wrong outgoing edges from 'a'."); - Assert.True(graph.OutgoingEdges("s").ToList().Count == 1, "Wrong outgoing edges from 's'."); - Assert.True(graph.OutgoingEdges("d").ToList().Count == 3, "Wrong outgoing edges from 'd'."); - Assert.True(graph.OutgoingEdges("x").ToList().Count == 3, "Wrong outgoing edges from 'x'."); - Assert.True(graph.OutgoingEdges("c").ToList().Count == 3, "Wrong outgoing edges from 'c'."); - Assert.True(graph.OutgoingEdges("v").ToList().Count == 1, "Wrong outgoing edges from 'v'."); - Assert.True(graph.OutgoingEdges("f").ToList().Count == 1, "Wrong outgoing edges from 'f'."); - Assert.True(graph.OutgoingEdges("z").ToList().Count == 0, "Wrong outgoing edges from 'z'."); - - Assert.True(graph.IncomingEdges("a").ToList().Count == 1, "Wrong incoming edges from 'a'."); - Assert.True(graph.IncomingEdges("s").ToList().Count == 2, "Wrong incoming edges from 's'."); - Assert.True(graph.IncomingEdges("d").ToList().Count == 2, "Wrong incoming edges from 'd'."); - Assert.True(graph.IncomingEdges("x").ToList().Count == 1, "Wrong incoming edges from 'x'."); - Assert.True(graph.IncomingEdges("c").ToList().Count == 3, "Wrong incoming edges from 'c'."); - Assert.True(graph.IncomingEdges("v").ToList().Count == 1, "Wrong incoming edges from 'v'."); - Assert.True(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); - Assert.True(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); - - graph.RemoveEdge("d", "c"); - graph.RemoveEdge("c", "v"); - graph.RemoveEdge("a", "z"); - - Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 11, "Wrong edges count."); - - graph.RemoveVertex("x"); - Assert.True(graph.VerticesCount == 7, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 7, "Wrong edges count."); - - graph.AddVertex("x"); - graph.AddEdge("s", "x"); - graph.AddEdge("x", "d"); - graph.AddEdge("x", "c"); - graph.AddEdge("x", "a"); - graph.AddEdge("d", "c"); - graph.AddEdge("c", "v"); - graph.AddEdge("a", "z"); - - // BFS from A - // Walk the graph using BFS from A: - var bfsWalk = graph.BreadthFirstWalk("a"); - // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in bfsWalk) - { - Console.Write(String.Format("({0})", node)); - } - - // DFS from A - // Walk the graph using DFS from A: - var dfsWalk = graph.DepthFirstWalk("a"); - // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in dfsWalk) - { - Console.Write(String.Format("({0})", node)); - } - - // BFS from F - Console.WriteLine("Walk the graph using BFS from F:"); - bfsWalk = graph.BreadthFirstWalk("f"); - // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in bfsWalk) - { - Console.Write(String.Format("({0})", node)); - } - - // DFS from F - // Walk the graph using DFS from F: - dfsWalk = graph.DepthFirstWalk("f"); - // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in dfsWalk) - { - Console.Write(String.Format("({0})", node)); - } - - /********************************************************************/ - - - graph.Clear(); - // Cleared the graph from all vertices and edges - - var verticesSet2 = new string[] { "a", "b", "c", "d", "e", "f" }; - - graph.AddVertices(verticesSet2); - - graph.AddEdge("a", "b"); - graph.AddEdge("a", "d"); - graph.AddEdge("b", "e"); - graph.AddEdge("d", "b"); - graph.AddEdge("d", "e"); - graph.AddEdge("e", "c"); - graph.AddEdge("c", "f"); - graph.AddEdge("f", "f"); - - Assert.True(graph.VerticesCount == 6, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 8, "Wrong edges count."); - - // Walk the graph using DFS: - dfsWalk = graph.DepthFirstWalk(); - // output: (a) (b) (e) (d) (c) (f) - foreach (var node in dfsWalk) - { - Console.Write(String.Format("({0})", node)); - } + Console.Write(String.Format("({0})", node)); } + /********************************************************************/ + + + graph.Clear(); + // Cleared the graph from all vertices and edges + + var verticesSet2 = new string[] { "a", "b", "c", "d", "e", "f" }; + + graph.AddVertices(verticesSet2); + + graph.AddEdge("a", "b"); + graph.AddEdge("a", "d"); + graph.AddEdge("b", "e"); + graph.AddEdge("d", "b"); + graph.AddEdge("d", "e"); + graph.AddEdge("e", "c"); + graph.AddEdge("c", "f"); + graph.AddEdge("f", "f"); + + Assert.True(graph.VerticesCount == 6, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 8, "Wrong edges count."); + + // Walk the graph using DFS: + dfsWalk = graph.DepthFirstWalk(); + // output: (a) (b) (e) (d) (c) (f) + foreach (var node in dfsWalk) + { + Console.Write(String.Format("({0})", node)); + } } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/GraphsDirectedWeightedDenseGraphTest.cs b/UnitTest/DataStructuresTests/GraphsDirectedWeightedDenseGraphTest.cs index e6905f13..bd7290a0 100644 --- a/UnitTest/DataStructuresTests/GraphsDirectedWeightedDenseGraphTest.cs +++ b/UnitTest/DataStructuresTests/GraphsDirectedWeightedDenseGraphTest.cs @@ -3,165 +3,162 @@ using System.Linq; using DataStructures.Graphs; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class GraphsDirectedWeightedDenseGraphTest { - public static class GraphsDirectedWeightedDenseGraphTest + public static void DoTest() { - public static void DoTest() - { - var graph = new DirectedWeightedDenseGraph(); - - var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }; - - graph.AddVertices(verticesSet1); - - graph.AddEdge("a", "s", 1); - graph.AddEdge("a", "z", 2); - graph.AddEdge("s", "x", 3); - graph.AddEdge("x", "d", 1); - graph.AddEdge("x", "c", 2); - graph.AddEdge("x", "a", 3); - graph.AddEdge("d", "f", 1); - graph.AddEdge("d", "c", 2); - graph.AddEdge("d", "s", 3); - graph.AddEdge("c", "f", 1); - graph.AddEdge("c", "v", 2); - graph.AddEdge("c", "d", 3); - graph.AddEdge("v", "f", 1); - graph.AddEdge("f", "c", 2); - - var allEdges = graph.Edges.ToList(); - - Debug.Assert(graph.VerticesCount == 8, "Wrong vertices count."); - Debug.Assert(graph.EdgesCount == 14, "Wrong edges count."); - Debug.Assert(graph.EdgesCount == allEdges.Count, "Wrong edges count."); - - Debug.Assert(graph.OutgoingEdges("a").ToList().Count == 2, "Wrong outgoing edges from 'a'."); - Debug.Assert(graph.OutgoingEdges("s").ToList().Count == 1, "Wrong outgoing edges from 's'."); - Debug.Assert(graph.OutgoingEdges("d").ToList().Count == 3, "Wrong outgoing edges from 'd'."); - Debug.Assert(graph.OutgoingEdges("x").ToList().Count == 3, "Wrong outgoing edges from 'x'."); - Debug.Assert(graph.OutgoingEdges("c").ToList().Count == 3, "Wrong outgoing edges from 'c'."); - Debug.Assert(graph.OutgoingEdges("v").ToList().Count == 1, "Wrong outgoing edges from 'v'."); - Debug.Assert(graph.OutgoingEdges("f").ToList().Count == 1, "Wrong outgoing edges from 'f'."); - Debug.Assert(graph.OutgoingEdges("z").ToList().Count == 0, "Wrong outgoing edges from 'z'."); - - Debug.Assert(graph.IncomingEdges("a").ToList().Count == 1, "Wrong incoming edges from 'a'."); - Debug.Assert(graph.IncomingEdges("s").ToList().Count == 2, "Wrong incoming edges from 's'."); - Debug.Assert(graph.IncomingEdges("d").ToList().Count == 2, "Wrong incoming edges from 'd'."); - Debug.Assert(graph.IncomingEdges("x").ToList().Count == 1, "Wrong incoming edges from 'x'."); - Debug.Assert(graph.IncomingEdges("c").ToList().Count == 3, "Wrong incoming edges from 'c'."); - Debug.Assert(graph.IncomingEdges("v").ToList().Count == 1, "Wrong incoming edges from 'v'."); - Debug.Assert(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); - Debug.Assert(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); - - Console.WriteLine("[*] Directed Weighted Dense Graph:"); - Console.WriteLine("Graph nodes and edges:"); - Console.WriteLine(graph.ToReadable() + "\r\n"); - - var f_to_c = graph.HasEdge("f", "c"); - var f_to_c_weight = graph.GetEdgeWeight("f", "c"); - Debug.Assert(f_to_c == true, "Edge f->c doesn't exist."); - Debug.Assert(f_to_c_weight == 2, "Edge f->c must have a weight of 2."); - Console.WriteLine("Is there an edge from f to c? " + f_to_c + ". If yes it's weight is: " + f_to_c_weight + "."); - - var d_to_s = graph.HasEdge("d", "s"); - var d_to_s_weight = graph.GetEdgeWeight("d", "s"); - Debug.Assert(d_to_s == true, "Edge d->s doesn't exist."); - Debug.Assert(d_to_s_weight == 3, "Edge d->s must have a weight of 3."); - Console.WriteLine("Is there an edge from d to d? " + d_to_s + ". If yes it's weight is: " + d_to_s_weight + "."); - - Console.WriteLine(); - - graph.RemoveEdge("d", "c"); - graph.RemoveEdge("c", "v"); - graph.RemoveEdge("a", "z"); - Debug.Assert(graph.VerticesCount == 8, "Wrong vertices count."); - Debug.Assert(graph.EdgesCount == 11, "Wrong edges count."); - - Console.WriteLine("After removing edges (d-c), (c-v), (a-z):"); - Console.WriteLine(graph.ToReadable() + "\r\n"); - - graph.RemoveVertex("x"); - Debug.Assert(graph.VerticesCount == 7, "Wrong vertices count."); - Debug.Assert(graph.EdgesCount == 7, "Wrong edges count."); - - Console.WriteLine("After removing node (x):"); - Console.WriteLine(graph.ToReadable() + "\r\n"); - - graph.AddVertex("x"); - graph.AddEdge("s", "x", 3); - graph.AddEdge("x", "d", 1); - graph.AddEdge("x", "c", 2); - graph.AddEdge("x", "a", 3); - graph.AddEdge("d", "c", 2); - graph.AddEdge("c", "v", 2); - graph.AddEdge("a", "z", 2); - Console.WriteLine("Re-added the deleted vertices and edges to the graph."); - Console.WriteLine(graph.ToReadable() + "\r\n"); - - // BFS from A - Console.WriteLine("Walk the graph using BFS from A:"); - var bfsWalk = graph.BreadthFirstWalk("a"); // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in bfsWalk) Console.Write(String.Format("({0})", node)); - Console.WriteLine("\r\n"); - - // DFS from A - Console.WriteLine("Walk the graph using DFS from A:"); - var dfsWalk = graph.DepthFirstWalk("a"); // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in dfsWalk) Console.Write(String.Format("({0})", node)); - Console.WriteLine("\r\n"); - - // BFS from F - Console.WriteLine("Walk the graph using BFS from F:"); - bfsWalk = graph.BreadthFirstWalk("f"); // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in bfsWalk) Console.Write(String.Format("({0})", node)); - Console.WriteLine("\r\n"); - - // DFS from F - Console.WriteLine("Walk the graph using DFS from F:"); - dfsWalk = graph.DepthFirstWalk("f"); // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in dfsWalk) Console.Write(String.Format("({0})", node)); - Console.WriteLine("\r\n"); - - Console.ReadLine(); - - - /********************************************************************/ - - - Console.WriteLine("***************************************************\r\n"); - - graph.Clear(); - Console.WriteLine("Cleared the graph from all vertices and edges.\r\n"); - - var verticesSet2 = new string[] { "a", "b", "c", "d", "e", "f" }; - - graph.AddVertices(verticesSet2); - - graph.AddEdge("a", "b", 1); - graph.AddEdge("a", "d", 2); - graph.AddEdge("b", "e", 3); - graph.AddEdge("d", "b", 1); - graph.AddEdge("d", "e", 2); - graph.AddEdge("e", "c", 3); - graph.AddEdge("c", "f", 1); - graph.AddEdge("f", "f", 1); - - Debug.Assert(graph.VerticesCount == 6, "Wrong vertices count."); - Debug.Assert(graph.EdgesCount == 8, "Wrong edges count."); - - Console.WriteLine("[*] NEW Directed Weighted Dense Graph:"); - Console.WriteLine("Graph nodes and edges:"); - Console.WriteLine(graph.ToReadable() + "\r\n"); - - Console.WriteLine("Walk the graph using DFS:"); - dfsWalk = graph.DepthFirstWalk(); // output: (a) (b) (e) (d) (c) (f) - foreach (var node in dfsWalk) Console.Write(String.Format("({0})", node)); + var graph = new DirectedWeightedDenseGraph(); + + var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }; + + graph.AddVertices(verticesSet1); + + graph.AddEdge("a", "s", 1); + graph.AddEdge("a", "z", 2); + graph.AddEdge("s", "x", 3); + graph.AddEdge("x", "d", 1); + graph.AddEdge("x", "c", 2); + graph.AddEdge("x", "a", 3); + graph.AddEdge("d", "f", 1); + graph.AddEdge("d", "c", 2); + graph.AddEdge("d", "s", 3); + graph.AddEdge("c", "f", 1); + graph.AddEdge("c", "v", 2); + graph.AddEdge("c", "d", 3); + graph.AddEdge("v", "f", 1); + graph.AddEdge("f", "c", 2); + + var allEdges = graph.Edges.ToList(); + + Debug.Assert(graph.VerticesCount == 8, "Wrong vertices count."); + Debug.Assert(graph.EdgesCount == 14, "Wrong edges count."); + Debug.Assert(graph.EdgesCount == allEdges.Count, "Wrong edges count."); + + Debug.Assert(graph.OutgoingEdges("a").ToList().Count == 2, "Wrong outgoing edges from 'a'."); + Debug.Assert(graph.OutgoingEdges("s").ToList().Count == 1, "Wrong outgoing edges from 's'."); + Debug.Assert(graph.OutgoingEdges("d").ToList().Count == 3, "Wrong outgoing edges from 'd'."); + Debug.Assert(graph.OutgoingEdges("x").ToList().Count == 3, "Wrong outgoing edges from 'x'."); + Debug.Assert(graph.OutgoingEdges("c").ToList().Count == 3, "Wrong outgoing edges from 'c'."); + Debug.Assert(graph.OutgoingEdges("v").ToList().Count == 1, "Wrong outgoing edges from 'v'."); + Debug.Assert(graph.OutgoingEdges("f").ToList().Count == 1, "Wrong outgoing edges from 'f'."); + Debug.Assert(graph.OutgoingEdges("z").ToList().Count == 0, "Wrong outgoing edges from 'z'."); + + Debug.Assert(graph.IncomingEdges("a").ToList().Count == 1, "Wrong incoming edges from 'a'."); + Debug.Assert(graph.IncomingEdges("s").ToList().Count == 2, "Wrong incoming edges from 's'."); + Debug.Assert(graph.IncomingEdges("d").ToList().Count == 2, "Wrong incoming edges from 'd'."); + Debug.Assert(graph.IncomingEdges("x").ToList().Count == 1, "Wrong incoming edges from 'x'."); + Debug.Assert(graph.IncomingEdges("c").ToList().Count == 3, "Wrong incoming edges from 'c'."); + Debug.Assert(graph.IncomingEdges("v").ToList().Count == 1, "Wrong incoming edges from 'v'."); + Debug.Assert(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); + Debug.Assert(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); + + Console.WriteLine("[*] Directed Weighted Dense Graph:"); + Console.WriteLine("Graph nodes and edges:"); + Console.WriteLine(graph.ToReadable() + "\r\n"); + + var f_to_c = graph.HasEdge("f", "c"); + var f_to_c_weight = graph.GetEdgeWeight("f", "c"); + Debug.Assert(f_to_c == true, "Edge f->c doesn't exist."); + Debug.Assert(f_to_c_weight == 2, "Edge f->c must have a weight of 2."); + Console.WriteLine("Is there an edge from f to c? " + f_to_c + ". If yes it's weight is: " + f_to_c_weight + "."); + + var d_to_s = graph.HasEdge("d", "s"); + var d_to_s_weight = graph.GetEdgeWeight("d", "s"); + Debug.Assert(d_to_s == true, "Edge d->s doesn't exist."); + Debug.Assert(d_to_s_weight == 3, "Edge d->s must have a weight of 3."); + Console.WriteLine("Is there an edge from d to d? " + d_to_s + ". If yes it's weight is: " + d_to_s_weight + "."); + + Console.WriteLine(); + + graph.RemoveEdge("d", "c"); + graph.RemoveEdge("c", "v"); + graph.RemoveEdge("a", "z"); + Debug.Assert(graph.VerticesCount == 8, "Wrong vertices count."); + Debug.Assert(graph.EdgesCount == 11, "Wrong edges count."); + + Console.WriteLine("After removing edges (d-c), (c-v), (a-z):"); + Console.WriteLine(graph.ToReadable() + "\r\n"); + + graph.RemoveVertex("x"); + Debug.Assert(graph.VerticesCount == 7, "Wrong vertices count."); + Debug.Assert(graph.EdgesCount == 7, "Wrong edges count."); + + Console.WriteLine("After removing node (x):"); + Console.WriteLine(graph.ToReadable() + "\r\n"); + + graph.AddVertex("x"); + graph.AddEdge("s", "x", 3); + graph.AddEdge("x", "d", 1); + graph.AddEdge("x", "c", 2); + graph.AddEdge("x", "a", 3); + graph.AddEdge("d", "c", 2); + graph.AddEdge("c", "v", 2); + graph.AddEdge("a", "z", 2); + Console.WriteLine("Re-added the deleted vertices and edges to the graph."); + Console.WriteLine(graph.ToReadable() + "\r\n"); + + // BFS from A + Console.WriteLine("Walk the graph using BFS from A:"); + var bfsWalk = graph.BreadthFirstWalk("a"); // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in bfsWalk) Console.Write(String.Format("({0})", node)); + Console.WriteLine("\r\n"); + + // DFS from A + Console.WriteLine("Walk the graph using DFS from A:"); + var dfsWalk = graph.DepthFirstWalk("a"); // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in dfsWalk) Console.Write(String.Format("({0})", node)); + Console.WriteLine("\r\n"); + + // BFS from F + Console.WriteLine("Walk the graph using BFS from F:"); + bfsWalk = graph.BreadthFirstWalk("f"); // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in bfsWalk) Console.Write(String.Format("({0})", node)); + Console.WriteLine("\r\n"); + + // DFS from F + Console.WriteLine("Walk the graph using DFS from F:"); + dfsWalk = graph.DepthFirstWalk("f"); // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in dfsWalk) Console.Write(String.Format("({0})", node)); + Console.WriteLine("\r\n"); + + Console.ReadLine(); + + + /********************************************************************/ + + + Console.WriteLine("***************************************************\r\n"); + + graph.Clear(); + Console.WriteLine("Cleared the graph from all vertices and edges.\r\n"); + + var verticesSet2 = new string[] { "a", "b", "c", "d", "e", "f" }; + + graph.AddVertices(verticesSet2); + + graph.AddEdge("a", "b", 1); + graph.AddEdge("a", "d", 2); + graph.AddEdge("b", "e", 3); + graph.AddEdge("d", "b", 1); + graph.AddEdge("d", "e", 2); + graph.AddEdge("e", "c", 3); + graph.AddEdge("c", "f", 1); + graph.AddEdge("f", "f", 1); + + Debug.Assert(graph.VerticesCount == 6, "Wrong vertices count."); + Debug.Assert(graph.EdgesCount == 8, "Wrong edges count."); + + Console.WriteLine("[*] NEW Directed Weighted Dense Graph:"); + Console.WriteLine("Graph nodes and edges:"); + Console.WriteLine(graph.ToReadable() + "\r\n"); - Console.ReadLine(); - } + Console.WriteLine("Walk the graph using DFS:"); + dfsWalk = graph.DepthFirstWalk(); // output: (a) (b) (e) (d) (c) (f) + foreach (var node in dfsWalk) Console.Write(String.Format("({0})", node)); + Console.ReadLine(); } -} - +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/GraphsDirectedWeightedSparseGraphTest.cs b/UnitTest/DataStructuresTests/GraphsDirectedWeightedSparseGraphTest.cs index 56b226fc..9ffb827b 100644 --- a/UnitTest/DataStructuresTests/GraphsDirectedWeightedSparseGraphTest.cs +++ b/UnitTest/DataStructuresTests/GraphsDirectedWeightedSparseGraphTest.cs @@ -5,159 +5,157 @@ using DataStructures.Graphs; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class GraphsDirectedWeightedSparseGraphTest { - public static class GraphsDirectedWeightedSparseGraphTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - var graph = new DirectedWeightedSparseGraph(); - - var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }; - - graph.AddVertices(verticesSet1); - - graph.AddEdge("a", "s", 1); - graph.AddEdge("a", "z", 2); - graph.AddEdge("s", "x", 3); - graph.AddEdge("x", "d", 1); - graph.AddEdge("x", "c", 2); - graph.AddEdge("x", "a", 3); - graph.AddEdge("d", "f", 1); - graph.AddEdge("d", "c", 2); - graph.AddEdge("d", "s", 3); - graph.AddEdge("c", "f", 1); - graph.AddEdge("c", "v", 2); - graph.AddEdge("c", "d", 3); - graph.AddEdge("v", "f", 1); - graph.AddEdge("f", "c", 2); - - var allEdges = graph.Edges.ToList(); - - Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 14, "Wrong edges count."); - Assert.True(graph.EdgesCount == allEdges.Count, "Wrong edges count."); - - Assert.True(graph.OutgoingEdges("a").ToList().Count == 2, "Wrong outgoing edges from 'a'."); - Assert.True(graph.OutgoingEdges("s").ToList().Count == 1, "Wrong outgoing edges from 's'."); - Assert.True(graph.OutgoingEdges("d").ToList().Count == 3, "Wrong outgoing edges from 'd'."); - Assert.True(graph.OutgoingEdges("x").ToList().Count == 3, "Wrong outgoing edges from 'x'."); - Assert.True(graph.OutgoingEdges("c").ToList().Count == 3, "Wrong outgoing edges from 'c'."); - Assert.True(graph.OutgoingEdges("v").ToList().Count == 1, "Wrong outgoing edges from 'v'."); - Assert.True(graph.OutgoingEdges("f").ToList().Count == 1, "Wrong outgoing edges from 'f'."); - Assert.True(graph.OutgoingEdges("z").ToList().Count == 0, "Wrong outgoing edges from 'z'."); - - Assert.True(graph.IncomingEdges("a").ToList().Count == 1, "Wrong incoming edges from 'a'."); - Assert.True(graph.IncomingEdges("s").ToList().Count == 2, "Wrong incoming edges from 's'."); - Assert.True(graph.IncomingEdges("d").ToList().Count == 2, "Wrong incoming edges from 'd'."); - Assert.True(graph.IncomingEdges("x").ToList().Count == 1, "Wrong incoming edges from 'x'."); - Assert.True(graph.IncomingEdges("c").ToList().Count == 3, "Wrong incoming edges from 'c'."); - Assert.True(graph.IncomingEdges("v").ToList().Count == 1, "Wrong incoming edges from 'v'."); - Assert.True(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); - Assert.True(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); - - // ASSERT RANDOMLY SELECTED EDGES - var f_to_c = graph.HasEdge("f", "c"); - var f_to_c_weight = graph.GetEdgeWeight("f", "c"); - Assert.True(f_to_c == true, "Edge f->c doesn't exist."); - Assert.True(f_to_c_weight == 2, "Edge f->c must have a weight of 2."); - - // ASSERT RANDOMLY SELECTED EDGES - var d_to_s = graph.HasEdge("d", "s"); - var d_to_s_weight = graph.GetEdgeWeight("d", "s"); - Assert.True(d_to_s == true, "Edge d->s doesn't exist."); - Assert.True(d_to_s_weight == 3, "Edge d->s must have a weight of 3."); - - // TRY ADDING DUPLICATE EDGES BUT WITH DIFFERENT WEIGHTS - var add_d_to_s_status = graph.AddEdge("d", "s", 6); - Assert.True(add_d_to_s_status == false, "Error! Added a duplicate edge."); - - var add_c_to_f_status = graph.AddEdge("c", "f", 12); - Assert.True(add_c_to_f_status == false, "Error! Added a duplicate edge."); - - var add_s_to_x_status = graph.AddEdge("s", "x", 123); - Assert.True(add_s_to_x_status == false, "Error! Added a duplicate edge."); - - var add_x_to_d_status = graph.AddEdge("x", "d", 34); - Assert.True(add_x_to_d_status == false, "Error! Added a duplicate edge."); - - // TEST DELETING EDGES - graph.RemoveEdge("d", "c"); - Assert.True(graph.HasEdge("d", "c") == false, "Error! The edge d->c was deleted."); - - graph.RemoveEdge("c", "v"); - Assert.True(graph.HasEdge("c", "v") == false, "Error! The edge c->v was deleted."); - - graph.RemoveEdge("a", "z"); - Assert.True(graph.HasEdge("a", "z") == false, "Error! The edge a->z was deleted."); - - // ASSERT VERTICES AND EDGES COUNT - Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 11, "Wrong edges count."); - - // TEST DELETING VERTICES - graph.RemoveVertex("x"); - Assert.True(graph.HasEdge("x", "a") == false, "Error! The edge x->a was deleted because vertex x was deleted."); - - // ASSERT VERTICES AND EDGES COUNT - Assert.True(graph.VerticesCount == 7, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 7, "Wrong edges count."); - - graph.AddVertex("x"); - graph.AddEdge("s", "x", 3); - graph.AddEdge("x", "d", 1); - graph.AddEdge("x", "c", 2); - graph.AddEdge("x", "a", 3); - graph.AddEdge("d", "c", 2); - graph.AddEdge("c", "v", 2); - graph.AddEdge("a", "z", 2); - - // BFS from A - // Walk the graph using BFS from A: - var bfsWalk = graph.BreadthFirstWalk("a"); // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in bfsWalk) Console.Write(String.Format("({0})", node)); - - // DFS from A - // Walk the graph using DFS from A: - var dfsWalk = graph.DepthFirstWalk("a"); // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in dfsWalk) Console.Write(String.Format("({0})", node)); - - // BFS from F - // Walk the graph using BFS from F: - bfsWalk = graph.BreadthFirstWalk("f"); // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in bfsWalk) Console.Write(String.Format("({0})", node)); - - // DFS from F - Console.WriteLine("Walk the graph using DFS from F:"); - dfsWalk = graph.DepthFirstWalk("f"); // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in dfsWalk) Console.Write(String.Format("({0})", node)); - - /********************************************************************/ - - graph.Clear(); - - var verticesSet2 = new string[] { "a", "b", "c", "d", "e", "f" }; - graph.AddVertices(verticesSet2); - - graph.AddEdge("a", "b", 1); - graph.AddEdge("a", "d", 2); - graph.AddEdge("b", "e", 3); - graph.AddEdge("d", "b", 1); - graph.AddEdge("d", "e", 2); - graph.AddEdge("e", "c", 3); - graph.AddEdge("c", "f", 1); - graph.AddEdge("f", "f", 1); - - Assert.True(graph.VerticesCount == 6, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 8, "Wrong edges count."); - - // Walk the graph using DFS: - dfsWalk = graph.DepthFirstWalk(); // output: (a) (b) (e) (d) (c) (f) - foreach (var node in dfsWalk) Console.Write(String.Format("({0})", node)); - - } + var graph = new DirectedWeightedSparseGraph(); + + var verticesSet1 = new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }; + + graph.AddVertices(verticesSet1); + + graph.AddEdge("a", "s", 1); + graph.AddEdge("a", "z", 2); + graph.AddEdge("s", "x", 3); + graph.AddEdge("x", "d", 1); + graph.AddEdge("x", "c", 2); + graph.AddEdge("x", "a", 3); + graph.AddEdge("d", "f", 1); + graph.AddEdge("d", "c", 2); + graph.AddEdge("d", "s", 3); + graph.AddEdge("c", "f", 1); + graph.AddEdge("c", "v", 2); + graph.AddEdge("c", "d", 3); + graph.AddEdge("v", "f", 1); + graph.AddEdge("f", "c", 2); + + var allEdges = graph.Edges.ToList(); + + Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 14, "Wrong edges count."); + Assert.True(graph.EdgesCount == allEdges.Count, "Wrong edges count."); + + Assert.True(graph.OutgoingEdges("a").ToList().Count == 2, "Wrong outgoing edges from 'a'."); + Assert.True(graph.OutgoingEdges("s").ToList().Count == 1, "Wrong outgoing edges from 's'."); + Assert.True(graph.OutgoingEdges("d").ToList().Count == 3, "Wrong outgoing edges from 'd'."); + Assert.True(graph.OutgoingEdges("x").ToList().Count == 3, "Wrong outgoing edges from 'x'."); + Assert.True(graph.OutgoingEdges("c").ToList().Count == 3, "Wrong outgoing edges from 'c'."); + Assert.True(graph.OutgoingEdges("v").ToList().Count == 1, "Wrong outgoing edges from 'v'."); + Assert.True(graph.OutgoingEdges("f").ToList().Count == 1, "Wrong outgoing edges from 'f'."); + Assert.True(graph.OutgoingEdges("z").ToList().Count == 0, "Wrong outgoing edges from 'z'."); + + Assert.True(graph.IncomingEdges("a").ToList().Count == 1, "Wrong incoming edges from 'a'."); + Assert.True(graph.IncomingEdges("s").ToList().Count == 2, "Wrong incoming edges from 's'."); + Assert.True(graph.IncomingEdges("d").ToList().Count == 2, "Wrong incoming edges from 'd'."); + Assert.True(graph.IncomingEdges("x").ToList().Count == 1, "Wrong incoming edges from 'x'."); + Assert.True(graph.IncomingEdges("c").ToList().Count == 3, "Wrong incoming edges from 'c'."); + Assert.True(graph.IncomingEdges("v").ToList().Count == 1, "Wrong incoming edges from 'v'."); + Assert.True(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); + Assert.True(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); + + // ASSERT RANDOMLY SELECTED EDGES + var f_to_c = graph.HasEdge("f", "c"); + var f_to_c_weight = graph.GetEdgeWeight("f", "c"); + Assert.True(f_to_c == true, "Edge f->c doesn't exist."); + Assert.True(f_to_c_weight == 2, "Edge f->c must have a weight of 2."); + + // ASSERT RANDOMLY SELECTED EDGES + var d_to_s = graph.HasEdge("d", "s"); + var d_to_s_weight = graph.GetEdgeWeight("d", "s"); + Assert.True(d_to_s == true, "Edge d->s doesn't exist."); + Assert.True(d_to_s_weight == 3, "Edge d->s must have a weight of 3."); + + // TRY ADDING DUPLICATE EDGES BUT WITH DIFFERENT WEIGHTS + var add_d_to_s_status = graph.AddEdge("d", "s", 6); + Assert.True(add_d_to_s_status == false, "Error! Added a duplicate edge."); + + var add_c_to_f_status = graph.AddEdge("c", "f", 12); + Assert.True(add_c_to_f_status == false, "Error! Added a duplicate edge."); + + var add_s_to_x_status = graph.AddEdge("s", "x", 123); + Assert.True(add_s_to_x_status == false, "Error! Added a duplicate edge."); + + var add_x_to_d_status = graph.AddEdge("x", "d", 34); + Assert.True(add_x_to_d_status == false, "Error! Added a duplicate edge."); + + // TEST DELETING EDGES + graph.RemoveEdge("d", "c"); + Assert.True(graph.HasEdge("d", "c") == false, "Error! The edge d->c was deleted."); + + graph.RemoveEdge("c", "v"); + Assert.True(graph.HasEdge("c", "v") == false, "Error! The edge c->v was deleted."); + + graph.RemoveEdge("a", "z"); + Assert.True(graph.HasEdge("a", "z") == false, "Error! The edge a->z was deleted."); + + // ASSERT VERTICES AND EDGES COUNT + Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 11, "Wrong edges count."); + + // TEST DELETING VERTICES + graph.RemoveVertex("x"); + Assert.True(graph.HasEdge("x", "a") == false, "Error! The edge x->a was deleted because vertex x was deleted."); + + // ASSERT VERTICES AND EDGES COUNT + Assert.True(graph.VerticesCount == 7, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 7, "Wrong edges count."); + + graph.AddVertex("x"); + graph.AddEdge("s", "x", 3); + graph.AddEdge("x", "d", 1); + graph.AddEdge("x", "c", 2); + graph.AddEdge("x", "a", 3); + graph.AddEdge("d", "c", 2); + graph.AddEdge("c", "v", 2); + graph.AddEdge("a", "z", 2); + + // BFS from A + // Walk the graph using BFS from A: + var bfsWalk = graph.BreadthFirstWalk("a"); // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in bfsWalk) Console.Write(String.Format("({0})", node)); + + // DFS from A + // Walk the graph using DFS from A: + var dfsWalk = graph.DepthFirstWalk("a"); // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in dfsWalk) Console.Write(String.Format("({0})", node)); + + // BFS from F + // Walk the graph using BFS from F: + bfsWalk = graph.BreadthFirstWalk("f"); // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in bfsWalk) Console.Write(String.Format("({0})", node)); + + // DFS from F + Console.WriteLine("Walk the graph using DFS from F:"); + dfsWalk = graph.DepthFirstWalk("f"); // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in dfsWalk) Console.Write(String.Format("({0})", node)); + + /********************************************************************/ + + graph.Clear(); + + var verticesSet2 = new string[] { "a", "b", "c", "d", "e", "f" }; + graph.AddVertices(verticesSet2); + + graph.AddEdge("a", "b", 1); + graph.AddEdge("a", "d", 2); + graph.AddEdge("b", "e", 3); + graph.AddEdge("d", "b", 1); + graph.AddEdge("d", "e", 2); + graph.AddEdge("e", "c", 3); + graph.AddEdge("c", "f", 1); + graph.AddEdge("f", "f", 1); + + Assert.True(graph.VerticesCount == 6, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 8, "Wrong edges count."); + + // Walk the graph using DFS: + dfsWalk = graph.DepthFirstWalk(); // output: (a) (b) (e) (d) (c) (f) + foreach (var node in dfsWalk) Console.Write(String.Format("({0})", node)); } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/GraphsUndirectedDenseGraphTest.cs b/UnitTest/DataStructuresTests/GraphsUndirectedDenseGraphTest.cs index 4bcc6bfe..d22e9cf3 100644 --- a/UnitTest/DataStructuresTests/GraphsUndirectedDenseGraphTest.cs +++ b/UnitTest/DataStructuresTests/GraphsUndirectedDenseGraphTest.cs @@ -2,115 +2,112 @@ using System.Linq; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class GraphsUndirectedDenseGraphTests { - public static class GraphsUndirectedDenseGraphTests - { - [Fact] - public static void DoTest() - { - var graph = new UndirectedDenseGraph(); - - graph.AddVertices(new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }); - - graph.AddEdge("a", "s"); - graph.AddEdge("a", "z"); - graph.AddEdge("s", "x"); - graph.AddEdge("x", "d"); - graph.AddEdge("x", "c"); - graph.AddEdge("d", "f"); - graph.AddEdge("d", "c"); - graph.AddEdge("c", "f"); - graph.AddEdge("c", "v"); - graph.AddEdge("v", "f"); - - var allEdges = graph.Edges.ToList(); - - Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 10, "Wrong edges count."); - Assert.True(graph.EdgesCount == allEdges.Count, "Wrong edges count."); - - Assert.True(graph.OutgoingEdges("a").ToList().Count == 2, "Wrong outgoing edges from 'a'."); - Assert.True(graph.OutgoingEdges("s").ToList().Count == 2, "Wrong outgoing edges from 's'."); - Assert.True(graph.OutgoingEdges("x").ToList().Count == 3, "Wrong outgoing edges from 'x'."); - Assert.True(graph.OutgoingEdges("d").ToList().Count == 3, "Wrong outgoing edges from 'd'."); - Assert.True(graph.OutgoingEdges("c").ToList().Count == 4, "Wrong outgoing edges from 'c'."); - Assert.True(graph.OutgoingEdges("v").ToList().Count == 2, "Wrong outgoing edges from 'v'."); - Assert.True(graph.OutgoingEdges("f").ToList().Count == 3, "Wrong outgoing edges from 'f'."); - Assert.True(graph.OutgoingEdges("z").ToList().Count == 1, "Wrong outgoing edges from 'z'."); - - Assert.True(graph.IncomingEdges("a").ToList().Count == 2, "Wrong incoming edges from 'a'."); - Assert.True(graph.IncomingEdges("s").ToList().Count == 2, "Wrong incoming edges from 's'."); - Assert.True(graph.IncomingEdges("x").ToList().Count == 3, "Wrong incoming edges from 'x'."); - Assert.True(graph.IncomingEdges("d").ToList().Count == 3, "Wrong incoming edges from 'd'."); - Assert.True(graph.IncomingEdges("c").ToList().Count == 4, "Wrong incoming edges from 'c'."); - Assert.True(graph.IncomingEdges("v").ToList().Count == 2, "Wrong incoming edges from 'v'."); - Assert.True(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); - Assert.True(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); - - // TEST REMOVE nodes v and f - graph.RemoveVertex("v"); - graph.RemoveVertex("f"); - Assert.True(graph.VerticesCount == 6, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 6, "Wrong edges count."); - Assert.True(graph.HasVertex("v") == false, "Vertex v must have been deleted."); - Assert.True(graph.HasVertex("f") == false, "Vertex f must have been deleted."); - - // TEST RE-ADD REMOVED NODES AND EDGES - graph.AddVertex("v"); - graph.AddVertex("f"); - graph.AddEdge("d", "f"); - graph.AddEdge("c", "f"); - graph.AddEdge("c", "v"); - graph.AddEdge("v", "f"); - - Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 10, "Wrong edges count."); - Assert.True(graph.HasVertex("v") == true, "Vertex v does not exist."); - Assert.True(graph.HasVertex("f") == true, "Vertex f does not exist."); - - // RE-TEST REMOVE AND ADD NODES AND EDGES - graph.RemoveEdge("d", "c"); - graph.RemoveEdge("c", "v"); - graph.RemoveEdge("a", "z"); - Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 7, "Wrong edges count."); - - graph.RemoveVertex("x"); - Assert.True(graph.VerticesCount == 7, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 4, "Wrong edges count."); - - graph.AddVertex("x"); - graph.AddEdge("s", "x"); - graph.AddEdge("x", "d"); - graph.AddEdge("x", "c"); - graph.AddEdge("d", "c"); - graph.AddEdge("c", "v"); - graph.AddEdge("a", "z"); - - // output: (s) (a) (x) (z) (d) (c) (f) (v) - Assert.True(graph.BreadthFirstWalk("s").SequenceEqual(new string[] { "s", "a", "x", "z", "d", "c", "f", "v" })); - - graph.Clear(); - - graph.AddVertices(new string[] { "a", "b", "c", "d", "e", "f" }); - graph.AddEdge("a", "b"); - graph.AddEdge("a", "d"); - graph.AddEdge("b", "e"); - graph.AddEdge("d", "b"); - graph.AddEdge("d", "e"); - graph.AddEdge("e", "c"); - graph.AddEdge("c", "f"); - graph.AddEdge("f", "f"); - - Assert.True(graph.VerticesCount == 6, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 8, "Wrong edges count."); - Assert.True(graph.DepthFirstWalk().SequenceEqual(new string[] { "a", "d", "e", "c", "f", "b" })); - - } + [Fact] + public static void DoTest() + { + var graph = new UndirectedDenseGraph(); + + graph.AddVertices(new string[] { "a", "z", "s", "x", "d", "c", "f", "v" }); + + graph.AddEdge("a", "s"); + graph.AddEdge("a", "z"); + graph.AddEdge("s", "x"); + graph.AddEdge("x", "d"); + graph.AddEdge("x", "c"); + graph.AddEdge("d", "f"); + graph.AddEdge("d", "c"); + graph.AddEdge("c", "f"); + graph.AddEdge("c", "v"); + graph.AddEdge("v", "f"); + + var allEdges = graph.Edges.ToList(); + + Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 10, "Wrong edges count."); + Assert.True(graph.EdgesCount == allEdges.Count, "Wrong edges count."); + + Assert.True(graph.OutgoingEdges("a").ToList().Count == 2, "Wrong outgoing edges from 'a'."); + Assert.True(graph.OutgoingEdges("s").ToList().Count == 2, "Wrong outgoing edges from 's'."); + Assert.True(graph.OutgoingEdges("x").ToList().Count == 3, "Wrong outgoing edges from 'x'."); + Assert.True(graph.OutgoingEdges("d").ToList().Count == 3, "Wrong outgoing edges from 'd'."); + Assert.True(graph.OutgoingEdges("c").ToList().Count == 4, "Wrong outgoing edges from 'c'."); + Assert.True(graph.OutgoingEdges("v").ToList().Count == 2, "Wrong outgoing edges from 'v'."); + Assert.True(graph.OutgoingEdges("f").ToList().Count == 3, "Wrong outgoing edges from 'f'."); + Assert.True(graph.OutgoingEdges("z").ToList().Count == 1, "Wrong outgoing edges from 'z'."); + + Assert.True(graph.IncomingEdges("a").ToList().Count == 2, "Wrong incoming edges from 'a'."); + Assert.True(graph.IncomingEdges("s").ToList().Count == 2, "Wrong incoming edges from 's'."); + Assert.True(graph.IncomingEdges("x").ToList().Count == 3, "Wrong incoming edges from 'x'."); + Assert.True(graph.IncomingEdges("d").ToList().Count == 3, "Wrong incoming edges from 'd'."); + Assert.True(graph.IncomingEdges("c").ToList().Count == 4, "Wrong incoming edges from 'c'."); + Assert.True(graph.IncomingEdges("v").ToList().Count == 2, "Wrong incoming edges from 'v'."); + Assert.True(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); + Assert.True(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); + + // TEST REMOVE nodes v and f + graph.RemoveVertex("v"); + graph.RemoveVertex("f"); + Assert.True(graph.VerticesCount == 6, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 6, "Wrong edges count."); + Assert.True(graph.HasVertex("v") == false, "Vertex v must have been deleted."); + Assert.True(graph.HasVertex("f") == false, "Vertex f must have been deleted."); + + // TEST RE-ADD REMOVED NODES AND EDGES + graph.AddVertex("v"); + graph.AddVertex("f"); + graph.AddEdge("d", "f"); + graph.AddEdge("c", "f"); + graph.AddEdge("c", "v"); + graph.AddEdge("v", "f"); + + Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 10, "Wrong edges count."); + Assert.True(graph.HasVertex("v") == true, "Vertex v does not exist."); + Assert.True(graph.HasVertex("f") == true, "Vertex f does not exist."); + + // RE-TEST REMOVE AND ADD NODES AND EDGES + graph.RemoveEdge("d", "c"); + graph.RemoveEdge("c", "v"); + graph.RemoveEdge("a", "z"); + Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 7, "Wrong edges count."); + + graph.RemoveVertex("x"); + Assert.True(graph.VerticesCount == 7, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 4, "Wrong edges count."); + + graph.AddVertex("x"); + graph.AddEdge("s", "x"); + graph.AddEdge("x", "d"); + graph.AddEdge("x", "c"); + graph.AddEdge("d", "c"); + graph.AddEdge("c", "v"); + graph.AddEdge("a", "z"); + + // output: (s) (a) (x) (z) (d) (c) (f) (v) + Assert.True(graph.BreadthFirstWalk("s").SequenceEqual(new string[] { "s", "a", "x", "z", "d", "c", "f", "v" })); + + graph.Clear(); + + graph.AddVertices(new string[] { "a", "b", "c", "d", "e", "f" }); + graph.AddEdge("a", "b"); + graph.AddEdge("a", "d"); + graph.AddEdge("b", "e"); + graph.AddEdge("d", "b"); + graph.AddEdge("d", "e"); + graph.AddEdge("e", "c"); + graph.AddEdge("c", "f"); + graph.AddEdge("f", "f"); + + Assert.True(graph.VerticesCount == 6, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 8, "Wrong edges count."); + Assert.True(graph.DepthFirstWalk().SequenceEqual(new string[] { "a", "d", "e", "c", "f", "b" })); } -} - +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/GraphsUndirectedSparseGraphTest.cs b/UnitTest/DataStructuresTests/GraphsUndirectedSparseGraphTest.cs index fe57d976..8a80c337 100644 --- a/UnitTest/DataStructuresTests/GraphsUndirectedSparseGraphTest.cs +++ b/UnitTest/DataStructuresTests/GraphsUndirectedSparseGraphTest.cs @@ -2,91 +2,89 @@ using DataStructures.Graphs; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class GraphsUndirectedSparseGraphTest { - public static class GraphsUndirectedSparseGraphTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - var graph = new UndirectedSparseGraph(); - - var verticesSet1 = new[] { "a", "z", "s", "x", "d", "c", "f", "v" }; - - graph.AddVertices(verticesSet1); - - graph.AddEdge("a", "s"); - graph.AddEdge("a", "z"); - graph.AddEdge("s", "x"); - graph.AddEdge("x", "d"); - graph.AddEdge("x", "c"); - graph.AddEdge("d", "f"); - graph.AddEdge("d", "c"); - graph.AddEdge("c", "f"); - graph.AddEdge("c", "v"); - graph.AddEdge("v", "f"); - - var allEdges = graph.Edges.ToList(); - - Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 10, "Wrong edges count."); - Assert.True(graph.EdgesCount == allEdges.Count, "Wrong edges count."); - - Assert.True(graph.OutgoingEdges("a").ToList().Count == 2, "Wrong outgoing edges from 'a'."); - Assert.True(graph.OutgoingEdges("s").ToList().Count == 2, "Wrong outgoing edges from 's'."); - Assert.True(graph.OutgoingEdges("x").ToList().Count == 3, "Wrong outgoing edges from 'x'."); - Assert.True(graph.OutgoingEdges("d").ToList().Count == 3, "Wrong outgoing edges from 'd'."); - Assert.True(graph.OutgoingEdges("c").ToList().Count == 4, "Wrong outgoing edges from 'c'."); - Assert.True(graph.OutgoingEdges("v").ToList().Count == 2, "Wrong outgoing edges from 'v'."); - Assert.True(graph.OutgoingEdges("f").ToList().Count == 3, "Wrong outgoing edges from 'f'."); - Assert.True(graph.OutgoingEdges("z").ToList().Count == 1, "Wrong outgoing edges from 'z'."); - - Assert.True(graph.IncomingEdges("a").ToList().Count == 2, "Wrong incoming edges from 'a'."); - Assert.True(graph.IncomingEdges("s").ToList().Count == 2, "Wrong incoming edges from 's'."); - Assert.True(graph.IncomingEdges("x").ToList().Count == 3, "Wrong incoming edges from 'x'."); - Assert.True(graph.IncomingEdges("d").ToList().Count == 3, "Wrong incoming edges from 'd'."); - Assert.True(graph.IncomingEdges("c").ToList().Count == 4, "Wrong incoming edges from 'c'."); - Assert.True(graph.IncomingEdges("v").ToList().Count == 2, "Wrong incoming edges from 'v'."); - Assert.True(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); - Assert.True(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); - - graph.RemoveEdge("d", "c"); - graph.RemoveEdge("c", "v"); - graph.RemoveEdge("a", "z"); - Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 7, "Wrong edges count."); - - - graph.RemoveVertex("x"); - Assert.True(graph.VerticesCount == 7, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 4, "Wrong edges count."); - - graph.AddVertex("x"); - graph.AddEdge("s", "x"); - graph.AddEdge("x", "d"); - graph.AddEdge("x", "c"); - graph.AddEdge("d", "c"); - graph.AddEdge("c", "v"); - graph.AddEdge("a", "z"); - - Assert.True(graph.BreadthFirstWalk("s").SequenceEqual(new[] { "s", "a", "x", "z", "d", "c", "f", "v" })); - - graph.AddVertices(new[] { "a", "b", "c", "d", "e", "f" }); - - graph.AddEdge("a", "b"); - graph.AddEdge("a", "d"); - graph.AddEdge("b", "e"); - graph.AddEdge("d", "b"); - graph.AddEdge("d", "e"); - graph.AddEdge("e", "c"); - graph.AddEdge("c", "f"); - graph.AddEdge("f", "f"); - - Assert.True(graph.VerticesCount == 10, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 17, "Wrong edges count."); - - Assert.True(graph.DepthFirstWalk().SequenceEqual(new[] { "a", "d", "e", "c", "v", "f", "x", "s", "b", "z" })); - } + var graph = new UndirectedSparseGraph(); + + var verticesSet1 = new[] { "a", "z", "s", "x", "d", "c", "f", "v" }; + + graph.AddVertices(verticesSet1); + + graph.AddEdge("a", "s"); + graph.AddEdge("a", "z"); + graph.AddEdge("s", "x"); + graph.AddEdge("x", "d"); + graph.AddEdge("x", "c"); + graph.AddEdge("d", "f"); + graph.AddEdge("d", "c"); + graph.AddEdge("c", "f"); + graph.AddEdge("c", "v"); + graph.AddEdge("v", "f"); + + var allEdges = graph.Edges.ToList(); + + Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 10, "Wrong edges count."); + Assert.True(graph.EdgesCount == allEdges.Count, "Wrong edges count."); + + Assert.True(graph.OutgoingEdges("a").ToList().Count == 2, "Wrong outgoing edges from 'a'."); + Assert.True(graph.OutgoingEdges("s").ToList().Count == 2, "Wrong outgoing edges from 's'."); + Assert.True(graph.OutgoingEdges("x").ToList().Count == 3, "Wrong outgoing edges from 'x'."); + Assert.True(graph.OutgoingEdges("d").ToList().Count == 3, "Wrong outgoing edges from 'd'."); + Assert.True(graph.OutgoingEdges("c").ToList().Count == 4, "Wrong outgoing edges from 'c'."); + Assert.True(graph.OutgoingEdges("v").ToList().Count == 2, "Wrong outgoing edges from 'v'."); + Assert.True(graph.OutgoingEdges("f").ToList().Count == 3, "Wrong outgoing edges from 'f'."); + Assert.True(graph.OutgoingEdges("z").ToList().Count == 1, "Wrong outgoing edges from 'z'."); + + Assert.True(graph.IncomingEdges("a").ToList().Count == 2, "Wrong incoming edges from 'a'."); + Assert.True(graph.IncomingEdges("s").ToList().Count == 2, "Wrong incoming edges from 's'."); + Assert.True(graph.IncomingEdges("x").ToList().Count == 3, "Wrong incoming edges from 'x'."); + Assert.True(graph.IncomingEdges("d").ToList().Count == 3, "Wrong incoming edges from 'd'."); + Assert.True(graph.IncomingEdges("c").ToList().Count == 4, "Wrong incoming edges from 'c'."); + Assert.True(graph.IncomingEdges("v").ToList().Count == 2, "Wrong incoming edges from 'v'."); + Assert.True(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); + Assert.True(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); + + graph.RemoveEdge("d", "c"); + graph.RemoveEdge("c", "v"); + graph.RemoveEdge("a", "z"); + Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 7, "Wrong edges count."); + + + graph.RemoveVertex("x"); + Assert.True(graph.VerticesCount == 7, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 4, "Wrong edges count."); + + graph.AddVertex("x"); + graph.AddEdge("s", "x"); + graph.AddEdge("x", "d"); + graph.AddEdge("x", "c"); + graph.AddEdge("d", "c"); + graph.AddEdge("c", "v"); + graph.AddEdge("a", "z"); + + Assert.True(graph.BreadthFirstWalk("s").SequenceEqual(new[] { "s", "a", "x", "z", "d", "c", "f", "v" })); + + graph.AddVertices(new[] { "a", "b", "c", "d", "e", "f" }); + + graph.AddEdge("a", "b"); + graph.AddEdge("a", "d"); + graph.AddEdge("b", "e"); + graph.AddEdge("d", "b"); + graph.AddEdge("d", "e"); + graph.AddEdge("e", "c"); + graph.AddEdge("c", "f"); + graph.AddEdge("f", "f"); + + Assert.True(graph.VerticesCount == 10, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 17, "Wrong edges count."); + + Assert.True(graph.DepthFirstWalk().SequenceEqual(new[] { "a", "d", "e", "c", "v", "f", "x", "s", "b", "z" })); } -} - +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/GraphsUndirectedWeightedSparseGraphTest.cs b/UnitTest/DataStructuresTests/GraphsUndirectedWeightedSparseGraphTest.cs index fff21cf8..7dce2b21 100644 --- a/UnitTest/DataStructuresTests/GraphsUndirectedWeightedSparseGraphTest.cs +++ b/UnitTest/DataStructuresTests/GraphsUndirectedWeightedSparseGraphTest.cs @@ -3,175 +3,174 @@ using System.Linq; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class GraphsUndirectedWeightedSparseGraphTest { - public static class GraphsUndirectedWeightedSparseGraphTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() + var graph = new UndirectedWeightedSparseGraph(); + + var verticesSet1 = new[] { "a", "z", "s", "x", "d", "c", "f", "v" }; + + graph.AddVertices(verticesSet1); + + graph.AddEdge("a", "s", 1); + graph.AddEdge("a", "z", 2); + graph.AddEdge("s", "x", 3); + graph.AddEdge("x", "d", 1); + graph.AddEdge("x", "c", 2); + graph.AddEdge("x", "a", 3); + graph.AddEdge("d", "f", 1); + graph.AddEdge("d", "c", 2); + graph.AddEdge("d", "s", 3); + graph.AddEdge("c", "f", 1); + graph.AddEdge("c", "v", 2); + graph.AddEdge("v", "f", 1); + + var allEdges = graph.Edges.ToList(); + + Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 12, "Wrong edges count."); + Assert.True(graph.EdgesCount == allEdges.Count, "Wrong edges count."); + + Assert.True(graph.OutgoingEdges("a").ToList().Count == 3, "Wrong outgoing edges from 'a'."); + Assert.True(graph.OutgoingEdges("s").ToList().Count == 3, "Wrong outgoing edges from 's'."); + Assert.True(graph.OutgoingEdges("x").ToList().Count == 4, "Wrong outgoing edges from 'x'."); + Assert.True(graph.OutgoingEdges("d").ToList().Count == 4, "Wrong outgoing edges from 'd'."); + Assert.True(graph.OutgoingEdges("c").ToList().Count == 4, "Wrong outgoing edges from 'c'."); + Assert.True(graph.OutgoingEdges("v").ToList().Count == 2, "Wrong outgoing edges from 'v'."); + Assert.True(graph.OutgoingEdges("f").ToList().Count == 3, "Wrong outgoing edges from 'f'."); + Assert.True(graph.OutgoingEdges("z").ToList().Count == 1, "Wrong outgoing edges from 'z'."); + + Assert.True(graph.IncomingEdges("a").ToList().Count == 3, "Wrong incoming edges from 'a'."); + Assert.True(graph.IncomingEdges("s").ToList().Count == 3, "Wrong incoming edges from 's'."); + Assert.True(graph.IncomingEdges("x").ToList().Count == 4, "Wrong incoming edges from 'x'."); + Assert.True(graph.IncomingEdges("d").ToList().Count == 4, "Wrong incoming edges from 'd'."); + Assert.True(graph.IncomingEdges("c").ToList().Count == 4, "Wrong incoming edges from 'c'."); + Assert.True(graph.IncomingEdges("v").ToList().Count == 2, "Wrong incoming edges from 'v'."); + Assert.True(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); + Assert.True(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); + + // ASSERT RANDOMLY SELECTED EDGES + var f_to_c = graph.HasEdge("f", "c"); + var f_to_c_weight = graph.GetEdgeWeight("f", "c"); + Assert.True(f_to_c, "Edge f->c doesn't exist."); + Assert.True(f_to_c_weight == 1, "Edge f->c must have a weight of 2."); + Console.WriteLine("Is there an edge from f to c? " + f_to_c + ". If yes it's weight is: " + f_to_c_weight + + "."); + + // ASSERT RANDOMLY SELECTED EDGES + var d_to_s = graph.HasEdge("d", "s"); + var d_to_s_weight = graph.GetEdgeWeight("d", "s"); + Assert.True(d_to_s, "Edge d->s doesn't exist."); + Assert.True(d_to_s_weight == 3, "Edge d->s must have a weight of 3."); + + // TRY ADDING DUPLICATE EDGES BUT WITH DIFFERENT WEIGHTS + var add_d_to_s_status = graph.AddEdge("d", "s", 6); + Assert.True(add_d_to_s_status == false, "Error! Added a duplicate edge."); + + var add_c_to_f_status = graph.AddEdge("c", "f", 12); + Assert.True(add_c_to_f_status == false, "Error! Added a duplicate edge."); + + var add_s_to_x_status = graph.AddEdge("s", "x", 123); + Assert.True(add_s_to_x_status == false, "Error! Added a duplicate edge."); + + var add_x_to_d_status = graph.AddEdge("x", "d", 34); + Assert.True(add_x_to_d_status == false, "Error! Added a duplicate edge."); + + // TEST DELETING EDGES + graph.RemoveEdge("d", "c"); + Assert.True(graph.HasEdge("d", "c") == false, "Error! The edge d->c was deleted."); + + graph.RemoveEdge("c", "v"); + Assert.True(graph.HasEdge("c", "v") == false, "Error! The edge c->v was deleted."); + + graph.RemoveEdge("a", "z"); + Assert.True(graph.HasEdge("a", "z") == false, "Error! The edge a->z was deleted."); + + // ASSERT VERTICES AND EDGES COUNT + Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 9, "Wrong edges count."); + + Console.WriteLine("After removing edges (d-c), (c-v), (a-z):"); + Console.WriteLine(graph.ToReadable() + "\r\n"); + + // TEST DELETING VERTICES + graph.RemoveVertex("x"); + Assert.True(graph.HasEdge("x", "a") == false, + "Error! The edge x->a was deleted because vertex x was deleted."); + + // ASSERT VERTICES AND EDGES COUNT + Assert.True(graph.VerticesCount == 7, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 5, "Wrong edges count."); + + graph.AddVertex("x"); + graph.AddEdge("s", "x", 3); + graph.AddEdge("x", "d", 1); + graph.AddEdge("x", "c", 2); + graph.AddEdge("x", "a", 3); + graph.AddEdge("d", "c", 2); + graph.AddEdge("c", "v", 2); + graph.AddEdge("a", "z", 2); + + // BFS from A + // Walk the graph using BFS from A: + var bfsWalk = graph.BreadthFirstWalk("a"); // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in bfsWalk) + { + Console.Write("({0})", node); + } + + // DFS from A + // Walk the graph using DFS from A: + var dfsWalk = graph.DepthFirstWalk("a"); // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in dfsWalk) + { + Console.Write("({0})", node); + } + + // BFS from F + // Walk the graph using BFS from F: + bfsWalk = graph.BreadthFirstWalk("f"); // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in bfsWalk) + { + Console.Write("({0})", node); + } + + Console.WriteLine("\r\n"); + + // DFS from F + // Walk the graph using DFS from F: + dfsWalk = graph.DepthFirstWalk("f"); // output: (s) (a) (x) (z) (d) (c) (f) (v) + foreach (var node in dfsWalk) { - var graph = new UndirectedWeightedSparseGraph(); - - var verticesSet1 = new[] { "a", "z", "s", "x", "d", "c", "f", "v" }; - - graph.AddVertices(verticesSet1); - - graph.AddEdge("a", "s", 1); - graph.AddEdge("a", "z", 2); - graph.AddEdge("s", "x", 3); - graph.AddEdge("x", "d", 1); - graph.AddEdge("x", "c", 2); - graph.AddEdge("x", "a", 3); - graph.AddEdge("d", "f", 1); - graph.AddEdge("d", "c", 2); - graph.AddEdge("d", "s", 3); - graph.AddEdge("c", "f", 1); - graph.AddEdge("c", "v", 2); - graph.AddEdge("v", "f", 1); - - var allEdges = graph.Edges.ToList(); - - Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 12, "Wrong edges count."); - Assert.True(graph.EdgesCount == allEdges.Count, "Wrong edges count."); - - Assert.True(graph.OutgoingEdges("a").ToList().Count == 3, "Wrong outgoing edges from 'a'."); - Assert.True(graph.OutgoingEdges("s").ToList().Count == 3, "Wrong outgoing edges from 's'."); - Assert.True(graph.OutgoingEdges("x").ToList().Count == 4, "Wrong outgoing edges from 'x'."); - Assert.True(graph.OutgoingEdges("d").ToList().Count == 4, "Wrong outgoing edges from 'd'."); - Assert.True(graph.OutgoingEdges("c").ToList().Count == 4, "Wrong outgoing edges from 'c'."); - Assert.True(graph.OutgoingEdges("v").ToList().Count == 2, "Wrong outgoing edges from 'v'."); - Assert.True(graph.OutgoingEdges("f").ToList().Count == 3, "Wrong outgoing edges from 'f'."); - Assert.True(graph.OutgoingEdges("z").ToList().Count == 1, "Wrong outgoing edges from 'z'."); - - Assert.True(graph.IncomingEdges("a").ToList().Count == 3, "Wrong incoming edges from 'a'."); - Assert.True(graph.IncomingEdges("s").ToList().Count == 3, "Wrong incoming edges from 's'."); - Assert.True(graph.IncomingEdges("x").ToList().Count == 4, "Wrong incoming edges from 'x'."); - Assert.True(graph.IncomingEdges("d").ToList().Count == 4, "Wrong incoming edges from 'd'."); - Assert.True(graph.IncomingEdges("c").ToList().Count == 4, "Wrong incoming edges from 'c'."); - Assert.True(graph.IncomingEdges("v").ToList().Count == 2, "Wrong incoming edges from 'v'."); - Assert.True(graph.IncomingEdges("f").ToList().Count == 3, "Wrong incoming edges from 'f'."); - Assert.True(graph.IncomingEdges("z").ToList().Count == 1, "Wrong incoming edges from 'z'."); - - // ASSERT RANDOMLY SELECTED EDGES - var f_to_c = graph.HasEdge("f", "c"); - var f_to_c_weight = graph.GetEdgeWeight("f", "c"); - Assert.True(f_to_c, "Edge f->c doesn't exist."); - Assert.True(f_to_c_weight == 1, "Edge f->c must have a weight of 2."); - Console.WriteLine("Is there an edge from f to c? " + f_to_c + ". If yes it's weight is: " + f_to_c_weight + - "."); - - // ASSERT RANDOMLY SELECTED EDGES - var d_to_s = graph.HasEdge("d", "s"); - var d_to_s_weight = graph.GetEdgeWeight("d", "s"); - Assert.True(d_to_s, "Edge d->s doesn't exist."); - Assert.True(d_to_s_weight == 3, "Edge d->s must have a weight of 3."); - - // TRY ADDING DUPLICATE EDGES BUT WITH DIFFERENT WEIGHTS - var add_d_to_s_status = graph.AddEdge("d", "s", 6); - Assert.True(add_d_to_s_status == false, "Error! Added a duplicate edge."); - - var add_c_to_f_status = graph.AddEdge("c", "f", 12); - Assert.True(add_c_to_f_status == false, "Error! Added a duplicate edge."); - - var add_s_to_x_status = graph.AddEdge("s", "x", 123); - Assert.True(add_s_to_x_status == false, "Error! Added a duplicate edge."); - - var add_x_to_d_status = graph.AddEdge("x", "d", 34); - Assert.True(add_x_to_d_status == false, "Error! Added a duplicate edge."); - - // TEST DELETING EDGES - graph.RemoveEdge("d", "c"); - Assert.True(graph.HasEdge("d", "c") == false, "Error! The edge d->c was deleted."); - - graph.RemoveEdge("c", "v"); - Assert.True(graph.HasEdge("c", "v") == false, "Error! The edge c->v was deleted."); - - graph.RemoveEdge("a", "z"); - Assert.True(graph.HasEdge("a", "z") == false, "Error! The edge a->z was deleted."); - - // ASSERT VERTICES AND EDGES COUNT - Assert.True(graph.VerticesCount == 8, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 9, "Wrong edges count."); - - Console.WriteLine("After removing edges (d-c), (c-v), (a-z):"); - Console.WriteLine(graph.ToReadable() + "\r\n"); - - // TEST DELETING VERTICES - graph.RemoveVertex("x"); - Assert.True(graph.HasEdge("x", "a") == false, - "Error! The edge x->a was deleted because vertex x was deleted."); - - // ASSERT VERTICES AND EDGES COUNT - Assert.True(graph.VerticesCount == 7, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 5, "Wrong edges count."); - - graph.AddVertex("x"); - graph.AddEdge("s", "x", 3); - graph.AddEdge("x", "d", 1); - graph.AddEdge("x", "c", 2); - graph.AddEdge("x", "a", 3); - graph.AddEdge("d", "c", 2); - graph.AddEdge("c", "v", 2); - graph.AddEdge("a", "z", 2); - - // BFS from A - // Walk the graph using BFS from A: - var bfsWalk = graph.BreadthFirstWalk("a"); // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in bfsWalk) - { - Console.Write("({0})", node); - } - - // DFS from A - // Walk the graph using DFS from A: - var dfsWalk = graph.DepthFirstWalk("a"); // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in dfsWalk) - { - Console.Write("({0})", node); - } - - // BFS from F - // Walk the graph using BFS from F: - bfsWalk = graph.BreadthFirstWalk("f"); // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in bfsWalk) - { - Console.Write("({0})", node); - } - - Console.WriteLine("\r\n"); - - // DFS from F - // Walk the graph using DFS from F: - dfsWalk = graph.DepthFirstWalk("f"); // output: (s) (a) (x) (z) (d) (c) (f) (v) - foreach (var node in dfsWalk) - { - Console.Write("({0})", node); - } - - /********************************************************************/ - - graph.Clear(); - // "Cleared the graph from all vertices and edges.\r\n" - - var verticesSet2 = new[] { "a", "b", "c", "d", "e", "f" }; - - graph.AddVertices(verticesSet2); - - graph.AddEdge("a", "b", 1); - graph.AddEdge("a", "d", 2); - graph.AddEdge("b", "e", 3); - graph.AddEdge("d", "b", 1); - graph.AddEdge("d", "e", 2); - graph.AddEdge("e", "c", 3); - graph.AddEdge("c", "f", 1); - graph.AddEdge("f", "f", 1); - - Assert.True(graph.VerticesCount == 6, "Wrong vertices count."); - Assert.True(graph.EdgesCount == 8, "Wrong edges count."); - - // Walk the graph using DFS: - Assert.True(graph.DepthFirstWalk().SequenceEqual(new[] { "a", "d", "e", "c", "f", "b" })); + Console.Write("({0})", node); } + + /********************************************************************/ + + graph.Clear(); + // "Cleared the graph from all vertices and edges.\r\n" + + var verticesSet2 = new[] { "a", "b", "c", "d", "e", "f" }; + + graph.AddVertices(verticesSet2); + + graph.AddEdge("a", "b", 1); + graph.AddEdge("a", "d", 2); + graph.AddEdge("b", "e", 3); + graph.AddEdge("d", "b", 1); + graph.AddEdge("d", "e", 2); + graph.AddEdge("e", "c", 3); + graph.AddEdge("c", "f", 1); + graph.AddEdge("f", "f", 1); + + Assert.True(graph.VerticesCount == 6, "Wrong vertices count."); + Assert.True(graph.EdgesCount == 8, "Wrong edges count."); + + // Walk the graph using DFS: + Assert.True(graph.DepthFirstWalk().SequenceEqual(new[] { "a", "d", "e", "c", "f", "b" })); } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/HashTableSeparateChainingTest.cs b/UnitTest/DataStructuresTests/HashTableSeparateChainingTest.cs index 799da32a..aab77b43 100644 --- a/UnitTest/DataStructuresTests/HashTableSeparateChainingTest.cs +++ b/UnitTest/DataStructuresTests/HashTableSeparateChainingTest.cs @@ -4,147 +4,146 @@ using DataStructures.Dictionaries; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class HashTableSeparateChainingTest { - public static class HashTableSeparateChainingTest + [Fact] + public static void Adding_ThreeDifferentElements_ReturnsSuccessful() { - [Fact] - public static void Adding_ThreeDifferentElements_ReturnsSuccessful() - { - var studentsMarks = new ChainedHashTable(); + var studentsMarks = new ChainedHashTable(); - studentsMarks.Add("Name1", 1); - studentsMarks.Add("Name2", 5); - studentsMarks.Add(new KeyValuePair("Name3", 3)); + studentsMarks.Add("Name1", 1); + studentsMarks.Add("Name2", 5); + studentsMarks.Add(new KeyValuePair("Name3", 3)); - var mark = studentsMarks["Name1"]; - Assert.True(mark == 1); + var mark = studentsMarks["Name1"]; + Assert.True(mark == 1); - mark = studentsMarks["Name2"]; - Assert.True(mark == 5); + mark = studentsMarks["Name2"]; + Assert.True(mark == 5); - mark = studentsMarks["Name3"]; - Assert.True(mark == 3); + mark = studentsMarks["Name3"]; + Assert.True(mark == 3); - Assert.True(studentsMarks.Count == 3); - } + Assert.True(studentsMarks.Count == 3); + } - [Fact] - public static void Adding_TwoDuplicateElements_ReturnsException() - { - var studentsMarks = new ChainedHashTable(); - studentsMarks.Add("Name1", 1); - studentsMarks.Add("Name2", 5); + [Fact] + public static void Adding_TwoDuplicateElements_ReturnsException() + { + var studentsMarks = new ChainedHashTable(); + studentsMarks.Add("Name1", 1); + studentsMarks.Add("Name2", 5); - Action act = () => studentsMarks.Add("Name2", 7); + Action act = () => studentsMarks.Add("Name2", 7); - var exception = Assert.Throws(act); - Assert.Equal("Key already exists in the hash table.", exception.Message); - Assert.True(studentsMarks.Count == 2); - } - - [Fact] - public static void GetElement_ExistingElement_ReturnsElement() - { - var studentsMarks = new ChainedHashTable(); - studentsMarks.Add("Name1", 1); - studentsMarks.Add("Name2", 5); - - var value = studentsMarks["Name2"]; - - Assert.Equal(5, value); - Assert.True(studentsMarks.Count == 2); - } - - [Fact] - public static void GetElement_NonExistingElement_ReturnsException() - { - var studentsMarks = new ChainedHashTable(); - studentsMarks.Add("Name1", 1); - studentsMarks.Add("Name2", 5); - - int value; - Action act = () => value = studentsMarks["Name3"]; - - Assert.Throws(act); - Assert.True(studentsMarks.Count == 2); - } - - [Fact] - public static void RemovingOneElement_ThreeDifferentElements_ReturnsSuccessful() - { - var studentsMarks = new ChainedHashTable(); - studentsMarks.Add("Name1", 1); - studentsMarks.Add("Name2", 5); - studentsMarks.Add(new KeyValuePair("Name3", 3)); - - studentsMarks.Remove("Name2"); - - var mark = studentsMarks["Name1"]; - Assert.True(mark == 1); - - mark = studentsMarks["Name3"]; - Assert.True(mark == 3); - - Assert.False(studentsMarks.ContainsKey("Name2")); - - Assert.True(studentsMarks.Count == 2); - } - - [Fact] - public static void RemovingAllElement_ThreeDifferentElements_ReturnsSuccessful() - { - var studentsMarks = new ChainedHashTable(); - studentsMarks.Add("Name1", 1); - studentsMarks.Add("Name2", 5); - studentsMarks.Add(new KeyValuePair("Name3", 3)); - - studentsMarks.Remove("Name2"); - studentsMarks.Remove("Name1"); - studentsMarks.Remove("Name3"); - - Assert.True(studentsMarks.Count == 0); - } - - [Fact] - public static void CopyTo_FilledHashTable_ReturnsSuccessful() - { - var studentsMarks = new ChainedHashTable(); - studentsMarks.Add("Name1", 1); - studentsMarks.Add("Name2", 5); - studentsMarks.Add(new KeyValuePair("Name3", 3)); - - var array = new KeyValuePair[studentsMarks.Count]; - studentsMarks.CopyTo(array, 0); - - Assert.True(studentsMarks.Count == 3); - Assert.True(array.Length == 3); - var arrayKeys = array.Select(x => x.Key).OrderBy(x => x).ToArray(); - Assert.Equal("Name1", arrayKeys[0]); - Assert.Equal("Name2", arrayKeys[1]); - Assert.Equal("Name3", arrayKeys[2]); - var arrayValues = array.Select(x => x.Value).OrderBy(x => x).ToArray(); - Assert.Equal(1, arrayValues[0]); - Assert.Equal(3, arrayValues[1]); - Assert.Equal(5, arrayValues[2]); - - } - - [Fact] - public static void CopyTo_EmptyHashTable_ReturnsSuccessful() - { - var studentsMarks = new ChainedHashTable(); - studentsMarks.Add("Name1", 1); - studentsMarks.Add("Name2", 5); - studentsMarks.Add(new KeyValuePair("Name3", 3)); - - studentsMarks.Remove("Name2"); - studentsMarks.Remove("Name1"); - studentsMarks.Remove("Name3"); - - Assert.True(studentsMarks.Count == 0); - var array = new KeyValuePair[studentsMarks.Count]; - studentsMarks.CopyTo(array, 0); - } + var exception = Assert.Throws(act); + Assert.Equal("Key already exists in the hash table.", exception.Message); + Assert.True(studentsMarks.Count == 2); + } + + [Fact] + public static void GetElement_ExistingElement_ReturnsElement() + { + var studentsMarks = new ChainedHashTable(); + studentsMarks.Add("Name1", 1); + studentsMarks.Add("Name2", 5); + + var value = studentsMarks["Name2"]; + + Assert.Equal(5, value); + Assert.True(studentsMarks.Count == 2); + } + + [Fact] + public static void GetElement_NonExistingElement_ReturnsException() + { + var studentsMarks = new ChainedHashTable(); + studentsMarks.Add("Name1", 1); + studentsMarks.Add("Name2", 5); + + int value; + Action act = () => value = studentsMarks["Name3"]; + + Assert.Throws(act); + Assert.True(studentsMarks.Count == 2); + } + + [Fact] + public static void RemovingOneElement_ThreeDifferentElements_ReturnsSuccessful() + { + var studentsMarks = new ChainedHashTable(); + studentsMarks.Add("Name1", 1); + studentsMarks.Add("Name2", 5); + studentsMarks.Add(new KeyValuePair("Name3", 3)); + + studentsMarks.Remove("Name2"); + + var mark = studentsMarks["Name1"]; + Assert.True(mark == 1); + + mark = studentsMarks["Name3"]; + Assert.True(mark == 3); + + Assert.False(studentsMarks.ContainsKey("Name2")); + + Assert.True(studentsMarks.Count == 2); + } + + [Fact] + public static void RemovingAllElement_ThreeDifferentElements_ReturnsSuccessful() + { + var studentsMarks = new ChainedHashTable(); + studentsMarks.Add("Name1", 1); + studentsMarks.Add("Name2", 5); + studentsMarks.Add(new KeyValuePair("Name3", 3)); + + studentsMarks.Remove("Name2"); + studentsMarks.Remove("Name1"); + studentsMarks.Remove("Name3"); + + Assert.True(studentsMarks.Count == 0); + } + + [Fact] + public static void CopyTo_FilledHashTable_ReturnsSuccessful() + { + var studentsMarks = new ChainedHashTable(); + studentsMarks.Add("Name1", 1); + studentsMarks.Add("Name2", 5); + studentsMarks.Add(new KeyValuePair("Name3", 3)); + + var array = new KeyValuePair[studentsMarks.Count]; + studentsMarks.CopyTo(array, 0); + + Assert.True(studentsMarks.Count == 3); + Assert.True(array.Length == 3); + var arrayKeys = array.Select(x => x.Key).OrderBy(x => x).ToArray(); + Assert.Equal("Name1", arrayKeys[0]); + Assert.Equal("Name2", arrayKeys[1]); + Assert.Equal("Name3", arrayKeys[2]); + var arrayValues = array.Select(x => x.Value).OrderBy(x => x).ToArray(); + Assert.Equal(1, arrayValues[0]); + Assert.Equal(3, arrayValues[1]); + Assert.Equal(5, arrayValues[2]); + + } + + [Fact] + public static void CopyTo_EmptyHashTable_ReturnsSuccessful() + { + var studentsMarks = new ChainedHashTable(); + studentsMarks.Add("Name1", 1); + studentsMarks.Add("Name2", 5); + studentsMarks.Add(new KeyValuePair("Name3", 3)); + + studentsMarks.Remove("Name2"); + studentsMarks.Remove("Name1"); + studentsMarks.Remove("Name3"); + + Assert.True(studentsMarks.Count == 0); + var array = new KeyValuePair[studentsMarks.Count]; + studentsMarks.CopyTo(array, 0); } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/PrimeListTest.cs b/UnitTest/DataStructuresTests/PrimeListTest.cs index 1e10e618..d915eb1d 100644 --- a/UnitTest/DataStructuresTests/PrimeListTest.cs +++ b/UnitTest/DataStructuresTests/PrimeListTest.cs @@ -2,23 +2,22 @@ using DataStructures.Common; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public class PrimeListTest { - public class PrimeListTest + [Fact] + public void DoTest() { - [Fact] - public void DoTest() - { - var instance = PrimesList.Instance; - Assert.Equal(10000, instance.Count); - } + var instance = PrimesList.Instance; + Assert.Equal(10000, instance.Count); + } - [Fact] - public void PrimesListIsReadOnly() - { - var instance = PrimesList.Instance; - NotSupportedException ex = Assert.Throws(() => instance.GetAll[0] = -1); - Assert.Equal("Collection is read-only.", ex.Message); - } + [Fact] + public void PrimesListIsReadOnly() + { + var instance = PrimesList.Instance; + NotSupportedException ex = Assert.Throws(() => instance.GetAll[0] = -1); + Assert.Equal("Collection is read-only.", ex.Message); } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/PriorityQueuesTest.cs b/UnitTest/DataStructuresTests/PriorityQueuesTest.cs index 34cba369..acf138a3 100644 --- a/UnitTest/DataStructuresTests/PriorityQueuesTest.cs +++ b/UnitTest/DataStructuresTests/PriorityQueuesTest.cs @@ -3,123 +3,121 @@ using System.Diagnostics; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class PriorityQueuesTest { - public static class PriorityQueuesTest + internal class Process : IComparable { - internal class Process : IComparable + public Process(int id, Action action, string desc) { - public Process(int id, Action action, string desc) - { - Id = id; - Action = action; - Description = desc; - } + Id = id; + Action = action; + Description = desc; + } - public int Id { get; set; } - public Action Action { get; set; } - public string Description { get; set; } + public int Id { get; set; } + public Action Action { get; set; } + public string Description { get; set; } - public int CompareTo(Process other) + public int CompareTo(Process other) + { + if (other == null) { - if (other == null) - { - return -1; - } - - return Id.CompareTo(other.Id); + return -1; } + + return Id.CompareTo(other.Id); } + } - [Fact] - public static void DoTest() - { - // - // KEYED PRIORITY QUEUE - var keyedPriorityQueue = new PriorityQueue(10); + [Fact] + public static void DoTest() + { + // + // KEYED PRIORITY QUEUE + var keyedPriorityQueue = new PriorityQueue(10); - for (var i = 0; i < 20; ++i) - { - keyedPriorityQueue.Enqueue(i, i, i / 3 + 1); - } + for (var i = 0; i < 20; ++i) + { + keyedPriorityQueue.Enqueue(i, i, i / 3 + 1); + } - var keyedPQHighest = keyedPriorityQueue.Dequeue(); - Debug.Assert(keyedPQHighest == 18, "Wrong node!"); + var keyedPQHighest = keyedPriorityQueue.Dequeue(); + Debug.Assert(keyedPQHighest == 18, "Wrong node!"); - // - // Integer-index priority-queue - var alphabet = "abcdefghijklmnopqrstuvwxyz"; - var priorityQueue = new MinPriorityQueue((uint)alphabet.Length); + // + // Integer-index priority-queue + var alphabet = "abcdefghijklmnopqrstuvwxyz"; + var priorityQueue = new MinPriorityQueue((uint)alphabet.Length); - for (var i = 0; i < alphabet.Length; ++i) - { - priorityQueue.Enqueue(alphabet[i].ToString(), i / 3 + 1); - } + for (var i = 0; i < alphabet.Length; ++i) + { + priorityQueue.Enqueue(alphabet[i].ToString(), i / 3 + 1); + } - var PQMin = priorityQueue.DequeueMin(); - Debug.Assert(PQMin == "a", "Wrong node!"); + var PQMin = priorityQueue.DequeueMin(); + Debug.Assert(PQMin == "a", "Wrong node!"); - // - // Processes with priorities - var sysProcesses = new MinPriorityQueue(); + // + // Processes with priorities + var sysProcesses = new MinPriorityQueue(); - var process1 = new Process( - 432654, - () => Console.Write("I am Process #1.\r\n1 + 1 = " + (1 + 1)), - "Process 1"); + var process1 = new Process( + 432654, + () => Console.Write("I am Process #1.\r\n1 + 1 = " + (1 + 1)), + "Process 1"); - var process2 = new Process( - 123456, - () => Console.Write("Hello, World! I am Process #2"), - "Process 2"); + var process2 = new Process( + 123456, + () => Console.Write("Hello, World! I am Process #2"), + "Process 2"); - var process3 = new Process( - 345098, - () => Console.Write("I am Process #3"), - "Process 3"); + var process3 = new Process( + 345098, + () => Console.Write("I am Process #3"), + "Process 3"); - var process4 = new Process( - 109875, - () => Console.Write("I am Process #4"), - "Process 4"); + var process4 = new Process( + 109875, + () => Console.Write("I am Process #4"), + "Process 4"); - var process5 = new Process( - 13579, - () => Console.Write("I am Process #5"), - "Process 5"); + var process5 = new Process( + 13579, + () => Console.Write("I am Process #5"), + "Process 5"); - var process6 = new Process( - 24680, - () => Console.Write("I am Process #6"), - "Process 6"); + var process6 = new Process( + 24680, + () => Console.Write("I am Process #6"), + "Process 6"); - sysProcesses.Enqueue(process1, 1); - sysProcesses.Enqueue(process2, 10); - sysProcesses.Enqueue(process3, 5); - sysProcesses.Enqueue(process4, 7); - sysProcesses.Enqueue(process5, 3); - sysProcesses.Enqueue(process6, 6); + sysProcesses.Enqueue(process1, 1); + sysProcesses.Enqueue(process2, 10); + sysProcesses.Enqueue(process3, 5); + sysProcesses.Enqueue(process4, 7); + sysProcesses.Enqueue(process5, 3); + sysProcesses.Enqueue(process6, 6); - var leastPriorityProcess = sysProcesses.PeekAtMinPriority(); - Assert.True(leastPriorityProcess.Id == process1.Id, "Wrong process!"); + var leastPriorityProcess = sysProcesses.PeekAtMinPriority(); + Assert.True(leastPriorityProcess.Id == process1.Id, "Wrong process!"); - sysProcesses.DequeueMin(); + sysProcesses.DequeueMin(); - leastPriorityProcess = sysProcesses.PeekAtMinPriority(); - Assert.True(leastPriorityProcess.Id == process5.Id, "Wrong process!"); + leastPriorityProcess = sysProcesses.PeekAtMinPriority(); + Assert.True(leastPriorityProcess.Id == process5.Id, "Wrong process!"); - sysProcesses.DequeueMin(); + sysProcesses.DequeueMin(); - leastPriorityProcess = sysProcesses.PeekAtMinPriority(); - Assert.True(leastPriorityProcess.Id == process3.Id, "Wrong process!"); + leastPriorityProcess = sysProcesses.PeekAtMinPriority(); + Assert.True(leastPriorityProcess.Id == process3.Id, "Wrong process!"); - sysProcesses.DequeueMin(); + sysProcesses.DequeueMin(); - leastPriorityProcess = sysProcesses.PeekAtMinPriority(); - Assert.True(leastPriorityProcess.Id == process6.Id, "Wrong process!"); + leastPriorityProcess = sysProcesses.PeekAtMinPriority(); + Assert.True(leastPriorityProcess.Id == process6.Id, "Wrong process!"); - leastPriorityProcess.Action(); - } + leastPriorityProcess.Action(); } -} - +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/QueueTest.cs b/UnitTest/DataStructuresTests/QueueTest.cs index 4d7f6195..b062510f 100644 --- a/UnitTest/DataStructuresTests/QueueTest.cs +++ b/UnitTest/DataStructuresTests/QueueTest.cs @@ -1,41 +1,39 @@ using DataStructures.Lists; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class QueueTest { - public static class QueueTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - var queue = new Queue(); - queue.Enqueue("aaa"); - queue.Enqueue("bbb"); - queue.Enqueue("ccc"); - queue.Enqueue("ddd"); - queue.Enqueue("eee"); - queue.Enqueue("fff"); - queue.Enqueue("ggg"); - queue.Enqueue("hhh"); - Assert.Equal(8, queue.Count); + var queue = new Queue(); + queue.Enqueue("aaa"); + queue.Enqueue("bbb"); + queue.Enqueue("ccc"); + queue.Enqueue("ddd"); + queue.Enqueue("eee"); + queue.Enqueue("fff"); + queue.Enqueue("ggg"); + queue.Enqueue("hhh"); + Assert.Equal(8, queue.Count); - var array = queue.ToArray(); - // fails if wrong size - Assert.Equal(8, array.Length); + var array = queue.ToArray(); + // fails if wrong size + Assert.Equal(8, array.Length); - queue.Dequeue(); - queue.Dequeue(); - var top = queue.Dequeue(); - Assert.Equal("ccc", top); + queue.Dequeue(); + queue.Dequeue(); + var top = queue.Dequeue(); + Assert.Equal("ccc", top); - queue.Dequeue(); - queue.Dequeue(); - Assert.Equal("fff", queue.Top); + queue.Dequeue(); + queue.Dequeue(); + Assert.Equal("fff", queue.Top); - var array2 = queue.ToArray(); - // fails if wrong size - Assert.Equal(3, array2.Length); - } + var array2 = queue.ToArray(); + // fails if wrong size + Assert.Equal(3, array2.Length); } -} - +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/RedBlackTreeMapTests.cs b/UnitTest/DataStructuresTests/RedBlackTreeMapTests.cs index 20630838..65dfb37d 100644 --- a/UnitTest/DataStructuresTests/RedBlackTreeMapTests.cs +++ b/UnitTest/DataStructuresTests/RedBlackTreeMapTests.cs @@ -3,235 +3,234 @@ using System.Collections.Generic; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class RedBlackTreeMapTests { - public static class RedBlackTreeMapTests + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - // Red-Black Tree Map collection - var redBlackTree = new RedBlackTreeMap(false); + // Red-Black Tree Map collection + var redBlackTree = new RedBlackTreeMap(false); - // Testing data - var values = new KeyValuePair[10]; + // Testing data + var values = new KeyValuePair[10]; - // Prepare the values array - for (var i = 1; i <= 10; ++i) - { - var keyValPair = new KeyValuePair(i, string.Format("Integer: {0}", i)); - values[i - 1] = keyValPair; - } + // Prepare the values array + for (var i = 1; i <= 10; ++i) + { + var keyValPair = new KeyValuePair(i, string.Format("Integer: {0}", i)); + values[i - 1] = keyValPair; + } - // Test singular insert - for (var i = 0; i < 10; ++i) - { - redBlackTree.Insert(values[i].Key, values[i].Value); - } + // Test singular insert + for (var i = 0; i < 10; ++i) + { + redBlackTree.Insert(values[i].Key, values[i].Value); + } - Assert.True(redBlackTree.Count == values.Length, "Expected the same number of items."); - Assert.True(redBlackTree.Height < redBlackTree.Count, "Fail! Tree doesn't rebalance against sorted elements!"); + Assert.True(redBlackTree.Count == values.Length, "Expected the same number of items."); + Assert.True(redBlackTree.Height < redBlackTree.Count, "Fail! Tree doesn't rebalance against sorted elements!"); - redBlackTree.Clear(); + redBlackTree.Clear(); - // Test collection insert - redBlackTree.Insert(values); + // Test collection insert + redBlackTree.Insert(values); - Assert.True(redBlackTree.Height < redBlackTree.Count, "Fail! Tree doesn't rebalance against sorted elements!"); + Assert.True(redBlackTree.Height < redBlackTree.Count, "Fail! Tree doesn't rebalance against sorted elements!"); - // Test enumeration of key-value pairs is still in oreder - var enumerator = redBlackTree.GetInOrderEnumerator(); - for (var i = 0; i < 10; ++i) + // Test enumeration of key-value pairs is still in oreder + var enumerator = redBlackTree.GetInOrderEnumerator(); + for (var i = 0; i < 10; ++i) + { + if (enumerator.MoveNext()) { - if (enumerator.MoveNext()) + var curr = enumerator.Current; + if (curr.Key != values[i].Key || curr.Value != values[i].Value) { - var curr = enumerator.Current; - if (curr.Key != values[i].Key || curr.Value != values[i].Value) - { - throw new Exception(); - } + throw new Exception(); } } + } - // Test against re-shuffled insertions (not like above order) - redBlackTree = new RedBlackTreeMap(false); - - redBlackTree.Insert(4, "int4"); - redBlackTree.Insert(5, "int5"); - redBlackTree.Insert(7, "int7"); + // Test against re-shuffled insertions (not like above order) + redBlackTree = new RedBlackTreeMap(false); + + redBlackTree.Insert(4, "int4"); + redBlackTree.Insert(5, "int5"); + redBlackTree.Insert(7, "int7"); + redBlackTree.Insert(2, "int2"); + redBlackTree.Insert(1, "int1"); + redBlackTree.Insert(3, "int3"); + redBlackTree.Insert(6, "int6"); + //redBlackTree.Insert(0, "int0"); + redBlackTree.Insert(8, "int8"); + redBlackTree.Insert(10, "int10"); + redBlackTree.Insert(9, "int9"); + + Assert.True(redBlackTree.Count == values.Length, "Expected the same number of items."); + Assert.True(redBlackTree.Height < redBlackTree.Count, "Fail! Tree doesn't rebalance against sorted elements!"); + + // ASSERT INSERTING DUPLICATES WOULD BREAK + bool insertDuplicatePassed; + try + { + // 2 already exists in tree redBlackTree.Insert(2, "int2"); - redBlackTree.Insert(1, "int1"); - redBlackTree.Insert(3, "int3"); - redBlackTree.Insert(6, "int6"); - //redBlackTree.Insert(0, "int0"); - redBlackTree.Insert(8, "int8"); - redBlackTree.Insert(10, "int10"); - redBlackTree.Insert(9, "int9"); - - Assert.True(redBlackTree.Count == values.Length, "Expected the same number of items."); - Assert.True(redBlackTree.Height < redBlackTree.Count, "Fail! Tree doesn't rebalance against sorted elements!"); - - // ASSERT INSERTING DUPLICATES WOULD BREAK - bool insertDuplicatePassed; - try - { - // 2 already exists in tree - redBlackTree.Insert(2, "int2"); - insertDuplicatePassed = true; - } - catch - { - insertDuplicatePassed = false; - } - - Assert.True(insertDuplicatePassed == false, "Fail! The tree doesn't allow duplicates"); + insertDuplicatePassed = true; + } + catch + { + insertDuplicatePassed = false; + } - // Test find - Assert.True(redBlackTree.Find(5).Key == 5, "Wrong find result!"); - Assert.True(redBlackTree.FindMin().Key == 1, "Wrong min!"); - Assert.True(redBlackTree.FindMax().Key == 10, "Wrong max!"); + Assert.True(insertDuplicatePassed == false, "Fail! The tree doesn't allow duplicates"); - // Assert find raises exception on non-existing elements - var threwKeyNotFoundError = false; + // Test find + Assert.True(redBlackTree.Find(5).Key == 5, "Wrong find result!"); + Assert.True(redBlackTree.FindMin().Key == 1, "Wrong min!"); + Assert.True(redBlackTree.FindMax().Key == 10, "Wrong max!"); - try - { - redBlackTree.Find(999999999); - } - catch (KeyNotFoundException) - { - threwKeyNotFoundError = true; - } + // Assert find raises exception on non-existing elements + var threwKeyNotFoundError = false; - Assert.True(threwKeyNotFoundError, "Expected to catch KeyNotFoundException."); + try + { + redBlackTree.Find(999999999); + } + catch (KeyNotFoundException) + { + threwKeyNotFoundError = true; + } - // PRINT TREE - //Console.WriteLine("********************"); - //Console.WriteLine(" [*] RED-BLACK TREE:\r\n"); - //Console.WriteLine("********************"); - //Console.WriteLine(redBlackTree.DrawTree()); - //Console.WriteLine("\r\n"); + Assert.True(threwKeyNotFoundError, "Expected to catch KeyNotFoundException."); - // Assert count - Assert.True(redBlackTree.Count == 10); + // PRINT TREE + //Console.WriteLine("********************"); + //Console.WriteLine(" [*] RED-BLACK TREE:\r\n"); + //Console.WriteLine("********************"); + //Console.WriteLine(redBlackTree.DrawTree()); + //Console.WriteLine("\r\n"); - // Assert existence and nonexistence of some items - Assert.True(redBlackTree.Contains(1)); - Assert.True(redBlackTree.Contains(3)); - Assert.True(redBlackTree.Contains(999) == false); + // Assert count + Assert.True(redBlackTree.Count == 10); - // ASSERT THAT EACH LEVEL HAS A DIFFERENT COLOR - // TODO: Wrong color element "int4" - // AssetLevelsDifferentColors(redBlackTree); + // Assert existence and nonexistence of some items + Assert.True(redBlackTree.Contains(1)); + Assert.True(redBlackTree.Contains(3)); + Assert.True(redBlackTree.Contains(999) == false); - // Do some deletions - redBlackTree.Remove(7); - redBlackTree.Remove(1); - redBlackTree.Remove(3); + // ASSERT THAT EACH LEVEL HAS A DIFFERENT COLOR + // TODO: Wrong color element "int4" + // AssetLevelsDifferentColors(redBlackTree); - // Assert count - Assert.True(redBlackTree.Count == 7); + // Do some deletions + redBlackTree.Remove(7); + redBlackTree.Remove(1); + redBlackTree.Remove(3); - // Assert nonexistence of previously existing items - Assert.True(redBlackTree.Contains(1) == false); - Assert.True(redBlackTree.Contains(3) == false); + // Assert count + Assert.True(redBlackTree.Count == 7); - // Remove root value - var oldRootKey = redBlackTree.Root.Key; - redBlackTree.Remove(redBlackTree.Root.Key); + // Assert nonexistence of previously existing items + Assert.True(redBlackTree.Contains(1) == false); + Assert.True(redBlackTree.Contains(3) == false); - // Assert count - Assert.True(redBlackTree.Count == 6); + // Remove root value + var oldRootKey = redBlackTree.Root.Key; + redBlackTree.Remove(redBlackTree.Root.Key); - // Assert nonexistence of old root's key - Assert.True(redBlackTree.Contains(oldRootKey) == false); + // Assert count + Assert.True(redBlackTree.Count == 6); - // PRINT TREE - //Console.WriteLine("********************"); - //Console.WriteLine(" [*] RED-BLACK TREE:\r\n"); - //Console.WriteLine("********************"); - //Console.WriteLine(redBlackTree.DrawTree(includeValues: true)); - //Console.WriteLine("\r\n"); + // Assert nonexistence of old root's key + Assert.True(redBlackTree.Contains(oldRootKey) == false); - //Console.ReadLine(); - } //end-do-test + // PRINT TREE + //Console.WriteLine("********************"); + //Console.WriteLine(" [*] RED-BLACK TREE:\r\n"); + //Console.WriteLine("********************"); + //Console.WriteLine(redBlackTree.DrawTree(includeValues: true)); + //Console.WriteLine("\r\n"); + //Console.ReadLine(); + } //end-do-test - /// - /// Testing helper to assert that all items at every level of the tree has the same color and each level has different color than the other levels - /// - private static void AssetLevelsDifferentColors(RedBlackTreeMap redBlackTree) - where TKey : IComparable - { - var root = redBlackTree.Root; - var height = GetMaxHeight(root); - var levels = new List>>(); + /// + /// Testing helper to assert that all items at every level of the tree has the same color and each level has different color than the other levels + /// + private static void AssetLevelsDifferentColors(RedBlackTreeMap redBlackTree) + where TKey : IComparable + { + var root = redBlackTree.Root; - // Initialize the list - for (var i = 0; i < height; ++i) - { - levels.Add(new List>()); - } + var height = GetMaxHeight(root); + var levels = new List>>(); - var levelsIndex = 0; - var nodesInNextLevel = 0; - var nodesInCurrentLevel = 1; + // Initialize the list + for (var i = 0; i < height; ++i) + { + levels.Add(new List>()); + } - var queue = new Queue>(); - queue.Enqueue(root); + var levelsIndex = 0; + var nodesInNextLevel = 0; + var nodesInCurrentLevel = 1; - while (queue.Count > 0) - { - var curr = queue.Dequeue(); - nodesInCurrentLevel--; + var queue = new Queue>(); + queue.Enqueue(root); - if (curr != null) - { - levels[levelsIndex].Add(curr); - queue.Enqueue(curr.LeftChild); - queue.Enqueue(curr.RightChild); - nodesInNextLevel += 2; - } + while (queue.Count > 0) + { + var curr = queue.Dequeue(); + nodesInCurrentLevel--; - if (nodesInCurrentLevel == 0) - { - levelsIndex++; - nodesInCurrentLevel = nodesInNextLevel; - nodesInNextLevel = 0; - } + if (curr != null) + { + levels[levelsIndex].Add(curr); + queue.Enqueue(curr.LeftChild); + queue.Enqueue(curr.RightChild); + nodesInNextLevel += 2; } - // [*] Assert that levels have different alternating colors: - - var color = RedBlackTreeColors.Black; - for (var i = 0; i < levels.Count; ++i) + if (nodesInCurrentLevel == 0) { - for (var j = 0; j < levels[i].Count; ++j) - { - Assert.True(levels[i][j].Color == color); - - //if (levels[i][j].Color != color) - //Console.WriteLine(" [-] Level: {0}. Node Value: {1}. Node color: {2}. Expected color: {3}.", i, levels[i][j].Value, levels[i][j].Color, color.ToString()); - } - - color = color == RedBlackTreeColors.Black ? RedBlackTreeColors.Red : RedBlackTreeColors.Black; + levelsIndex++; + nodesInCurrentLevel = nodesInNextLevel; + nodesInNextLevel = 0; } - } //end-test-case + } + // [*] Assert that levels have different alternating colors: - /// - /// Helper function to calculate the Maximum Height - /// - private static int GetMaxHeight(RedBlackTreeMapNode tree) - where TKey : IComparable + var color = RedBlackTreeColors.Black; + for (var i = 0; i < levels.Count; ++i) { - if (tree == null) + for (var j = 0; j < levels[i].Count; ++j) { - return 0; + Assert.True(levels[i][j].Color == color); + + //if (levels[i][j].Color != color) + //Console.WriteLine(" [-] Level: {0}. Node Value: {1}. Node color: {2}. Expected color: {3}.", i, levels[i][j].Value, levels[i][j].Color, color.ToString()); } - return 1 + Math.Max(GetMaxHeight(tree.LeftChild), GetMaxHeight(tree.RightChild)); + color = color == RedBlackTreeColors.Black ? RedBlackTreeColors.Red : RedBlackTreeColors.Black; } + } //end-test-case + + + /// + /// Helper function to calculate the Maximum Height + /// + private static int GetMaxHeight(RedBlackTreeMapNode tree) + where TKey : IComparable + { + if (tree == null) + { + return 0; + } + + return 1 + Math.Max(GetMaxHeight(tree.LeftChild), GetMaxHeight(tree.RightChild)); } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/RedBlackTreeTest.cs b/UnitTest/DataStructuresTests/RedBlackTreeTest.cs index 43104915..0f75c556 100644 --- a/UnitTest/DataStructuresTests/RedBlackTreeTest.cs +++ b/UnitTest/DataStructuresTests/RedBlackTreeTest.cs @@ -4,11 +4,11 @@ using System.Linq; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public class RedBlackTreeTest { - public class RedBlackTreeTest - { - /** Input tree for test cases, (r -> red, b -> black): + /** Input tree for test cases, (r -> red, b -> black): ** 11(b) ** / \ ** (r)3 13(b) @@ -17,54 +17,54 @@ public class RedBlackTreeTest ** / \ ** (r)5 8(r) **/ - private RedBlackTree redBlackTree; + private RedBlackTree redBlackTree; - public RedBlackTreeTest() - { - redBlackTree = new RedBlackTree(false); - - redBlackTree.Insert(11); - redBlackTree.Insert(3); - redBlackTree.Insert(13); - redBlackTree.Insert(1); - redBlackTree.Insert(7); - redBlackTree.Insert(15); - redBlackTree.Insert(5); - redBlackTree.Insert(8); - } + public RedBlackTreeTest() + { + redBlackTree = new RedBlackTree(false); + + redBlackTree.Insert(11); + redBlackTree.Insert(3); + redBlackTree.Insert(13); + redBlackTree.Insert(1); + redBlackTree.Insert(7); + redBlackTree.Insert(15); + redBlackTree.Insert(5); + redBlackTree.Insert(8); + } - [Fact] - public void Insert_CheckCorrectConstructionOfInputTree() - { - RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); + [Fact] + public void Insert_CheckCorrectConstructionOfInputTree() + { + RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); - Assert.Equal(8, redBlackTree.Count); - Assert.Equal(11, redBlackTree.Root.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); + Assert.Equal(8, redBlackTree.Count); + Assert.Equal(11, redBlackTree.Root.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); - Assert.Equal(3, redBlackTree.Root.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); + Assert.Equal(3, redBlackTree.Root.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); - Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); + Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); - Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); + Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); - Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); + Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); - Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.RightChild.Color); + Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.RightChild.Color); - Assert.Equal(13, redBlackTree.Root.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); + Assert.Equal(13, redBlackTree.Root.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); - Assert.Equal(15, redBlackTree.Root.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.Color); - } + Assert.Equal(15, redBlackTree.Root.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.Color); + } - /** Insert 4, (r -> red, b -> black): + /** Insert 4, (r -> red, b -> black): ** 11(b) ===> 7(b) ** / \ ===> / \ ** (r)3 13(b) ===> (r)3 11(r) @@ -73,43 +73,43 @@ public void Insert_CheckCorrectConstructionOfInputTree() ** / \ ===> / \ ** (r)5 8(r) ===> 4(r) 15(r) **/ - [Fact] - public void Insert_ParentSiblingIsRed() - { - redBlackTree.Insert(4); + [Fact] + public void Insert_ParentSiblingIsRed() + { + redBlackTree.Insert(4); - RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); + RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); - Assert.Equal(9, redBlackTree.Count); - Assert.Equal(7, redBlackTree.Root.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); + Assert.Equal(9, redBlackTree.Count); + Assert.Equal(7, redBlackTree.Root.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); - Assert.Equal(3, redBlackTree.Root.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); + Assert.Equal(3, redBlackTree.Root.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); - Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); + Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); - Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); + Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); - Assert.Equal(4, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); + Assert.Equal(4, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); - Assert.Equal(11, redBlackTree.Root.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.Color); + Assert.Equal(11, redBlackTree.Root.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.Color); - Assert.Equal(8, redBlackTree.Root.RightChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.LeftChild.Color); + Assert.Equal(8, redBlackTree.Root.RightChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.LeftChild.Color); - Assert.Equal(13, redBlackTree.Root.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.RightChild.Color); + Assert.Equal(13, redBlackTree.Root.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.RightChild.Color); - Assert.Equal(15, redBlackTree.Root.RightChild.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.RightChild.Color); - } + Assert.Equal(15, redBlackTree.Root.RightChild.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.RightChild.Color); + } - /** Insert 14, (r -> red, b -> black): + /** Insert 14, (r -> red, b -> black): ** 11(b) ===> 11(b) ** / \ ===> / \ ** (r)3 13(b) ===> (r)3 14(b) @@ -118,43 +118,43 @@ public void Insert_ParentSiblingIsRed() ** / \ ===> / \ ** (r)5 8(r) ===> (r)5 8(r) **/ - [Fact] - public void Insert_ParentSiblingIsBlackAndNewElementIsLeftChild() - { - redBlackTree.Insert(14); + [Fact] + public void Insert_ParentSiblingIsBlackAndNewElementIsLeftChild() + { + redBlackTree.Insert(14); - RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); + RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); - Assert.Equal(9, redBlackTree.Count); - Assert.Equal(11, redBlackTree.Root.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); + Assert.Equal(9, redBlackTree.Count); + Assert.Equal(11, redBlackTree.Root.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); - Assert.Equal(3, redBlackTree.Root.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); + Assert.Equal(3, redBlackTree.Root.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); - Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); + Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); - Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); + Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); - Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); + Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); - Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.RightChild.Color); + Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.RightChild.Color); - Assert.Equal(14, redBlackTree.Root.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); + Assert.Equal(14, redBlackTree.Root.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); - Assert.Equal(13, redBlackTree.Root.RightChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.LeftChild.Color); + Assert.Equal(13, redBlackTree.Root.RightChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.LeftChild.Color); - Assert.Equal(15, redBlackTree.Root.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.Color); - } + Assert.Equal(15, redBlackTree.Root.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.Color); + } - /** Insert 16, (r -> red, b -> black): + /** Insert 16, (r -> red, b -> black): ** 11(b) ===> 11(b) ** / \ ===> / \ ** (r)3 13(b) ===> (r)3 15(b) @@ -163,56 +163,56 @@ public void Insert_ParentSiblingIsBlackAndNewElementIsLeftChild() ** / \ ===> / \ ** (r)5 8(r) ===> (r)5 8(r) **/ - [Fact] - public void Insert_ParentSiblingIsBlackAndNewElementIsRightChild() - { - redBlackTree.Insert(16); + [Fact] + public void Insert_ParentSiblingIsBlackAndNewElementIsRightChild() + { + redBlackTree.Insert(16); - RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); + RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); - Assert.Equal(9, redBlackTree.Count); - Assert.Equal(11, redBlackTree.Root.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); + Assert.Equal(9, redBlackTree.Count); + Assert.Equal(11, redBlackTree.Root.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); - Assert.Equal(3, redBlackTree.Root.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); + Assert.Equal(3, redBlackTree.Root.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); - Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); + Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); - Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); + Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); - Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); + Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); - Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.RightChild.Color); + Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.RightChild.Color); - Assert.Equal(15, redBlackTree.Root.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); + Assert.Equal(15, redBlackTree.Root.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); - Assert.Equal(13, redBlackTree.Root.RightChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.LeftChild.Color); + Assert.Equal(13, redBlackTree.Root.RightChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.LeftChild.Color); - Assert.Equal(16, redBlackTree.Root.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.Color); - } + Assert.Equal(16, redBlackTree.Root.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.Color); + } - [Fact] - public void Insert_ThrowExceptionWhenNotAllowDuplicate() - { - var redBlackTreeWithoutDuplicates = new RedBlackTree(false); + [Fact] + public void Insert_ThrowExceptionWhenNotAllowDuplicate() + { + var redBlackTreeWithoutDuplicates = new RedBlackTree(false); - redBlackTreeWithoutDuplicates.Insert(1); - redBlackTreeWithoutDuplicates.Insert(2); - redBlackTreeWithoutDuplicates.Insert(3); + redBlackTreeWithoutDuplicates.Insert(1); + redBlackTreeWithoutDuplicates.Insert(2); + redBlackTreeWithoutDuplicates.Insert(3); - //TODO Create more specyfic exception type for this kind of errors, with inheritance from InvalidOperationException. - Assert.Throws(() => redBlackTreeWithoutDuplicates.Insert(2)); - } + //TODO Create more specyfic exception type for this kind of errors, with inheritance from InvalidOperationException. + Assert.Throws(() => redBlackTreeWithoutDuplicates.Insert(2)); + } - /** Remove 13, (r -> red, b -> black): + /** Remove 13, (r -> red, b -> black): ** 11(b) ===> 11(b) ** / \ ===> / \ ** (r)3 13(b) ===> (r)3 15(b) @@ -221,37 +221,37 @@ public void Insert_ThrowExceptionWhenNotAllowDuplicate() ** / \ ===> / \ ** (r)5 8(r) ===> (r)5 8(r) **/ - [Fact] - public void Remove_SiblingIsRed() - { - redBlackTree.Remove(13); + [Fact] + public void Remove_SiblingIsRed() + { + redBlackTree.Remove(13); - RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); + RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); - Assert.Equal(7, redBlackTree.Count); - Assert.Equal(11, redBlackTree.Root.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); + Assert.Equal(7, redBlackTree.Count); + Assert.Equal(11, redBlackTree.Root.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); - Assert.Equal(3, redBlackTree.Root.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); + Assert.Equal(3, redBlackTree.Root.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); - Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); + Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); - Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); + Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); - Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); + Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); - Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.RightChild.Color); + Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.RightChild.Color); - Assert.Equal(15, redBlackTree.Root.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); - } + Assert.Equal(15, redBlackTree.Root.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); + } - /** Remove 3, (r -> red, b -> black): + /** Remove 3, (r -> red, b -> black): ** 11(b) ===> 11(b) ** / \ ===> / \ ** (r)3 13(b) ===> (r)5 13(b) @@ -260,37 +260,37 @@ public void Remove_SiblingIsRed() ** / \ ===> \ ** (r)5 8(r) ===> 8(r) **/ - [Fact] - public void Remove_SiblingIsBlackAndBothChildAreBlack() - { - redBlackTree.Remove(3); + [Fact] + public void Remove_SiblingIsBlackAndBothChildAreBlack() + { + redBlackTree.Remove(3); - RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); + RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); - Assert.Equal(7, redBlackTree.Count); - Assert.Equal(11, redBlackTree.Root.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); + Assert.Equal(7, redBlackTree.Count); + Assert.Equal(11, redBlackTree.Root.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); - Assert.Equal(5, redBlackTree.Root.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); + Assert.Equal(5, redBlackTree.Root.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); - Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); + Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); - Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); + Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); - Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.RightChild.Color); + Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.RightChild.Color); - Assert.Equal(13, redBlackTree.Root.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); + Assert.Equal(13, redBlackTree.Root.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); - Assert.Equal(15, redBlackTree.Root.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.Color); - } + Assert.Equal(15, redBlackTree.Root.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.Color); + } - /** Remove 7, (r -> red, b -> black): + /** Remove 7, (r -> red, b -> black): ** 11(b) ===> 11(b) ** / \ ===> / \ ** (r)3 13(b) ===> (r)3 13(b) @@ -299,37 +299,37 @@ public void Remove_SiblingIsBlackAndBothChildAreBlack() ** / \ ===> / ** (r)5 8(r) ===> 5(r) **/ - [Fact] - public void Remove_SiblingIsBlackAndRightChildIsRed() - { - redBlackTree.Remove(7); + [Fact] + public void Remove_SiblingIsBlackAndRightChildIsRed() + { + redBlackTree.Remove(7); - RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); + RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); - Assert.Equal(7, redBlackTree.Count); - Assert.Equal(11, redBlackTree.Root.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); + Assert.Equal(7, redBlackTree.Count); + Assert.Equal(11, redBlackTree.Root.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); - Assert.Equal(3, redBlackTree.Root.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); + Assert.Equal(3, redBlackTree.Root.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); - Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); + Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); - Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); + Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); - Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); + Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); - Assert.Equal(13, redBlackTree.Root.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); + Assert.Equal(13, redBlackTree.Root.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); - Assert.Equal(15, redBlackTree.Root.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.Color); - } + Assert.Equal(15, redBlackTree.Root.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.Color); + } - /** Remove 11, (r -> red, b -> black): + /** Remove 11, (r -> red, b -> black): ** 11(b) ===> 13(b) ** / \ ===> / \ ** (r)3 13(b) ===> (r)3 15(b) @@ -338,44 +338,44 @@ public void Remove_SiblingIsBlackAndRightChildIsRed() ** / \ ===> / \ ** (r)5 8(r) ===> 5(r) 8(r) **/ - [Fact] - public void Remove_CurrentRoot() - { - redBlackTree.Remove(11); + [Fact] + public void Remove_CurrentRoot() + { + redBlackTree.Remove(11); - RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); + RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); - Assert.Equal(7, redBlackTree.Count); - Assert.Equal(13, redBlackTree.Root.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); + Assert.Equal(7, redBlackTree.Count); + Assert.Equal(13, redBlackTree.Root.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); - Assert.Equal(3, redBlackTree.Root.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); + Assert.Equal(3, redBlackTree.Root.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); - Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); + Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); - Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); + Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); - Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); + Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); - Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.RightChild.Color); + Assert.Equal(8, redBlackTree.Root.LeftChild.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.RightChild.Color); - Assert.Equal(15, redBlackTree.Root.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); - } + Assert.Equal(15, redBlackTree.Root.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); + } - [Fact] - public void Remove_ThrowExceptionWhenTryRemoveNonExistentNode() - { - //TODO Create more specyfic exception type for this kind of errors, with inheritance from ArgumentException. - Assert.Throws(() =>redBlackTree.Remove(999)); - } + [Fact] + public void Remove_ThrowExceptionWhenTryRemoveNonExistentNode() + { + //TODO Create more specyfic exception type for this kind of errors, with inheritance from ArgumentException. + Assert.Throws(() =>redBlackTree.Remove(999)); + } - /** Remove 8, (r -> red, b -> black): + /** Remove 8, (r -> red, b -> black): ** 11(b) ===> 11(b) ** / \ ===> / \ ** (r)3 13(b) ===> (r)3 13(b) @@ -384,193 +384,192 @@ public void Remove_ThrowExceptionWhenTryRemoveNonExistentNode() ** / \ ===> / ** (r)5 8(r) ===> 5(r) **/ - [Fact] - public void Remove_NodeWithoutChildren() - { - redBlackTree.Remove(8); + [Fact] + public void Remove_NodeWithoutChildren() + { + redBlackTree.Remove(8); - RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); + RedBlackTreeRule.CheckRedBlackTreeRules(redBlackTree); - Assert.Equal(7, redBlackTree.Count); - Assert.Equal(11, redBlackTree.Root.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); + Assert.Equal(7, redBlackTree.Count); + Assert.Equal(11, redBlackTree.Root.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.Color); - Assert.Equal(3, redBlackTree.Root.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); + Assert.Equal(3, redBlackTree.Root.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.Color); - Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); + Assert.Equal(1, redBlackTree.Root.LeftChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.LeftChild.Color); - Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); + Assert.Equal(7, redBlackTree.Root.LeftChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.LeftChild.RightChild.Color); - Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); + Assert.Equal(5, redBlackTree.Root.LeftChild.RightChild.LeftChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.LeftChild.RightChild.LeftChild.Color); - Assert.Null(redBlackTree.Root.LeftChild.RightChild.RightChild); + Assert.Null(redBlackTree.Root.LeftChild.RightChild.RightChild); - Assert.Equal(13, redBlackTree.Root.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); + Assert.Equal(13, redBlackTree.Root.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Black, redBlackTree.Root.RightChild.Color); - Assert.Equal(15, redBlackTree.Root.RightChild.RightChild.Value); - Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.Color); - } + Assert.Equal(15, redBlackTree.Root.RightChild.RightChild.Value); + Assert.Equal(RedBlackTreeColors.Red, redBlackTree.Root.RightChild.RightChild.Color); + } - [Fact] - public void Remove_OneAndOnlyTreeNode() - { - var oneElementTree = new RedBlackTree(); - Assert.Equal(0, oneElementTree.Count); - Assert.Null(oneElementTree.Root); - Assert.True(oneElementTree.IsEmpty); - - oneElementTree.Insert(1); - Assert.Equal(1, oneElementTree.Count); - Assert.NotNull(oneElementTree.Root); - Assert.False(oneElementTree.IsEmpty); - - oneElementTree.Remove(1); - Assert.Equal(0, oneElementTree.Count); - Assert.Null(oneElementTree.Root); - Assert.True(oneElementTree.IsEmpty); - } + [Fact] + public void Remove_OneAndOnlyTreeNode() + { + var oneElementTree = new RedBlackTree(); + Assert.Equal(0, oneElementTree.Count); + Assert.Null(oneElementTree.Root); + Assert.True(oneElementTree.IsEmpty); + + oneElementTree.Insert(1); + Assert.Equal(1, oneElementTree.Count); + Assert.NotNull(oneElementTree.Root); + Assert.False(oneElementTree.IsEmpty); + + oneElementTree.Remove(1); + Assert.Equal(0, oneElementTree.Count); + Assert.Null(oneElementTree.Root); + Assert.True(oneElementTree.IsEmpty); } +} - /// - /// Contains set of method that facilitate work. Only for unit tests. - /// - internal static class RedBlackTreeHelper +/// +/// Contains set of method that facilitate work. Only for unit tests. +/// +internal static class RedBlackTreeHelper +{ + public static IEnumerable> GetNodes(this RedBlackTreeNode node) + where T : IComparable { - public static IEnumerable> GetNodes(this RedBlackTreeNode node) - where T : IComparable + if (node.LeftChild != null) { - if (node.LeftChild != null) - { - yield return node.LeftChild; - - foreach (var child in node.LeftChild.GetNodes()) - { - yield return child; - } - } - - if (node.RightChild != null) - { - yield return node.RightChild; - - foreach (var child in node.RightChild.GetNodes()) - { - yield return child; - } - } + yield return node.LeftChild; - if (node.Parent == null) + foreach (var child in node.LeftChild.GetNodes()) { - yield return node; + yield return child; } } - public static IEnumerable>> GetPathToLeaves(this RedBlackTreeNode root) - where T : IComparable + if (node.RightChild != null) { - if (root.Parent != null) - { - throw new ArgumentException("The given node is not root."); - } + yield return node.RightChild; - var leaves = root.GetNodes().Where(node => node.IsLeafNode); - var paths = new List>>(); - foreach (var leaf in leaves) + foreach (var child in node.RightChild.GetNodes()) { - paths.Add(new List>() { leaf }); - } - - for (var index = 0; index < paths.Count; index++) - { - var path = paths[index]; - - while (path.Last().Parent != null) - { - path.Add(path.Last().Parent); - } + yield return child; } + } - return paths; + if (node.Parent == null) + { + yield return node; } } - /// - /// Contains method to check asked red black tree fulfills red black tree rules. Only for unit tests. - /// - internal static class RedBlackTreeRule + public static IEnumerable>> GetPathToLeaves(this RedBlackTreeNode root) + where T : IComparable { - public static void CheckRedBlackTreeRules(RedBlackTree redBlackTree) + if (root.Parent != null) { - CheckIsEveryNodeRedOrBlack(redBlackTree); - CheckRootIsBlack(redBlackTree); - CheckNodeIsRedIfBothChildrenAreBlack(redBlackTree); - CheckPathToEveryLeafHasSameNumberOfBlackNode(redBlackTree); + throw new ArgumentException("The given node is not root."); } - private static void CheckIsEveryNodeRedOrBlack(RedBlackTree redBlackTree) + var leaves = root.GetNodes().Where(node => node.IsLeafNode); + var paths = new List>>(); + foreach (var leaf in leaves) { - var nodes = redBlackTree.Root.GetNodes().ToList(); + paths.Add(new List>() { leaf }); + } - if (!nodes.Any(node => node.IsBlack || node.IsRed)) + for (var index = 0; index < paths.Count; index++) + { + var path = paths[index]; + + while (path.Last().Parent != null) { - throw new RedBlackTreeViolationRuleException(); + path.Add(path.Last().Parent); } } - private static void CheckRootIsBlack(RedBlackTree redBlackTree) + return paths; + } +} + +/// +/// Contains method to check asked red black tree fulfills red black tree rules. Only for unit tests. +/// +internal static class RedBlackTreeRule +{ + public static void CheckRedBlackTreeRules(RedBlackTree redBlackTree) + { + CheckIsEveryNodeRedOrBlack(redBlackTree); + CheckRootIsBlack(redBlackTree); + CheckNodeIsRedIfBothChildrenAreBlack(redBlackTree); + CheckPathToEveryLeafHasSameNumberOfBlackNode(redBlackTree); + } + + private static void CheckIsEveryNodeRedOrBlack(RedBlackTree redBlackTree) + { + var nodes = redBlackTree.Root.GetNodes().ToList(); + + if (!nodes.Any(node => node.IsBlack || node.IsRed)) { - if (!redBlackTree.Root.IsBlack) - { - throw new RedBlackTreeViolationRuleException(); - } + throw new RedBlackTreeViolationRuleException(); } + } - private static void CheckNodeIsRedIfBothChildrenAreBlack(RedBlackTree redBlackTree) + private static void CheckRootIsBlack(RedBlackTree redBlackTree) + { + if (!redBlackTree.Root.IsBlack) { - var nodes = redBlackTree.Root.GetNodes().ToList(); + throw new RedBlackTreeViolationRuleException(); + } + } + + private static void CheckNodeIsRedIfBothChildrenAreBlack(RedBlackTree redBlackTree) + { + var nodes = redBlackTree.Root.GetNodes().ToList(); - foreach (var redNode in nodes.Where(node => node.IsRed)) + foreach (var redNode in nodes.Where(node => node.IsRed)) + { + if (redNode.RightChild != null + && !redNode.RightChild.IsBlack) { - if (redNode.RightChild != null - && !redNode.RightChild.IsBlack) - { - throw new RedBlackTreeViolationRuleException(); - } + throw new RedBlackTreeViolationRuleException(); + } - if (redNode.LeftChild != null - && !redNode.LeftChild.IsBlack) - { - throw new RedBlackTreeViolationRuleException(); - } + if (redNode.LeftChild != null + && !redNode.LeftChild.IsBlack) + { + throw new RedBlackTreeViolationRuleException(); } } + } - private static void CheckPathToEveryLeafHasSameNumberOfBlackNode(RedBlackTree redBlackTree) - { - var paths = redBlackTree.Root.GetPathToLeaves(); + private static void CheckPathToEveryLeafHasSameNumberOfBlackNode(RedBlackTree redBlackTree) + { + var paths = redBlackTree.Root.GetPathToLeaves(); - if (paths != null) + if (paths != null) + { + var blacks = paths.FirstOrDefault().Count(node => node.IsBlack); + foreach (var path in paths) { - var blacks = paths.FirstOrDefault().Count(node => node.IsBlack); - foreach (var path in paths) + if (blacks != path.Count(node => node.IsBlack)) { - if (blacks != path.Count(node => node.IsBlack)) - { - throw new RedBlackTreeViolationRuleException(); - } + throw new RedBlackTreeViolationRuleException(); } } } } - - /// - /// Exception class throw when any of red black tree rule is violation. Only for unit tests. - /// - internal class RedBlackTreeViolationRuleException : Exception - { } } + +/// +/// Exception class throw when any of red black tree rule is violation. Only for unit tests. +/// +internal class RedBlackTreeViolationRuleException : Exception +{ } \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/SLinkedListTest.cs b/UnitTest/DataStructuresTests/SLinkedListTest.cs index 0eeee70a..6c5b6b32 100644 --- a/UnitTest/DataStructuresTests/SLinkedListTest.cs +++ b/UnitTest/DataStructuresTests/SLinkedListTest.cs @@ -1,65 +1,63 @@ using DataStructures.Lists; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class SLinkedListTest { - public static class SLinkedListTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - SLinkedList listOfNumbers1 = new SLinkedList(); - - listOfNumbers1.Append(10); - listOfNumbers1.Append(124); - listOfNumbers1.Prepend(654); - listOfNumbers1.Prepend(8); - listOfNumbers1.Append(127485693); - listOfNumbers1.Append(34); - listOfNumbers1.Append(823); - - listOfNumbers1.RemoveAt(0); - listOfNumbers1.RemoveAt(3); - listOfNumbers1.RemoveAt(4); - listOfNumbers1.RemoveAt(2); - listOfNumbers1.RemoveAt(2); - listOfNumbers1.RemoveAt(0); - - listOfNumbers1.Prepend(3); - listOfNumbers1.Prepend(2); - listOfNumbers1.Prepend(1); - - // Print List and Count - - listOfNumbers1.InsertAt(444, listOfNumbers1.Count); - listOfNumbers1.InsertAt(555, listOfNumbers1.Count); - listOfNumbers1.InsertAt(222, 2); - - var arrayVersion = listOfNumbers1.ToArray(); - Assert.True(arrayVersion.Length == listOfNumbers1.Count); - - /************************************************************************************/ - - var listOfNumbers2 = new SLinkedList(); - - listOfNumbers2.Append(23); - listOfNumbers2.Append(42); - listOfNumbers2.Append(4); - listOfNumbers2.Append(16); - listOfNumbers2.Append(8); - listOfNumbers2.Append(15); - listOfNumbers2.Append(9); - listOfNumbers2.Append(55); - listOfNumbers2.Append(0); - listOfNumbers2.Append(34); - listOfNumbers2.Append(12); - listOfNumbers2.Append(2); - - listOfNumbers2.SelectionSort(); - var intArray = listOfNumbers2.ToArray(); - - Assert.True(intArray[0] == 0 && intArray[intArray.Length - 1] == 55, "Wrong sorting!"); - } + SLinkedList listOfNumbers1 = new SLinkedList(); + + listOfNumbers1.Append(10); + listOfNumbers1.Append(124); + listOfNumbers1.Prepend(654); + listOfNumbers1.Prepend(8); + listOfNumbers1.Append(127485693); + listOfNumbers1.Append(34); + listOfNumbers1.Append(823); + + listOfNumbers1.RemoveAt(0); + listOfNumbers1.RemoveAt(3); + listOfNumbers1.RemoveAt(4); + listOfNumbers1.RemoveAt(2); + listOfNumbers1.RemoveAt(2); + listOfNumbers1.RemoveAt(0); + + listOfNumbers1.Prepend(3); + listOfNumbers1.Prepend(2); + listOfNumbers1.Prepend(1); + + // Print List and Count + + listOfNumbers1.InsertAt(444, listOfNumbers1.Count); + listOfNumbers1.InsertAt(555, listOfNumbers1.Count); + listOfNumbers1.InsertAt(222, 2); + + var arrayVersion = listOfNumbers1.ToArray(); + Assert.True(arrayVersion.Length == listOfNumbers1.Count); + + /************************************************************************************/ + + var listOfNumbers2 = new SLinkedList(); + + listOfNumbers2.Append(23); + listOfNumbers2.Append(42); + listOfNumbers2.Append(4); + listOfNumbers2.Append(16); + listOfNumbers2.Append(8); + listOfNumbers2.Append(15); + listOfNumbers2.Append(9); + listOfNumbers2.Append(55); + listOfNumbers2.Append(0); + listOfNumbers2.Append(34); + listOfNumbers2.Append(12); + listOfNumbers2.Append(2); + + listOfNumbers2.SelectionSort(); + var intArray = listOfNumbers2.ToArray(); + + Assert.True(intArray[0] == 0 && intArray[intArray.Length - 1] == 55, "Wrong sorting!"); } -} - +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/SkipListTest.cs b/UnitTest/DataStructuresTests/SkipListTest.cs index 97ab6378..a9eb860d 100644 --- a/UnitTest/DataStructuresTests/SkipListTest.cs +++ b/UnitTest/DataStructuresTests/SkipListTest.cs @@ -1,35 +1,34 @@ using DataStructures.Lists; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class SkipListTest { - public static class SkipListTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - var skipList = new SkipList(); + var skipList = new SkipList(); - for (int i = 100; i >= 50; --i) - skipList.Add(i); + for (int i = 100; i >= 50; --i) + skipList.Add(i); - for (int i = 0; i <= 35; ++i) - skipList.Add(i); + for (int i = 0; i <= 35; ++i) + skipList.Add(i); - for (int i = -15; i <= 0; ++i) - skipList.Add(i); + for (int i = -15; i <= 0; ++i) + skipList.Add(i); - for (int i = -15; i >= -35; --i) - skipList.Add(i); + for (int i = -15; i >= -35; --i) + skipList.Add(i); - Assert.True(skipList.Count == 124); + Assert.True(skipList.Count == 124); - skipList.Clear(); + skipList.Clear(); - for (int i = 100; i >= 0; --i) - skipList.Add(i); + for (int i = 100; i >= 0; --i) + skipList.Add(i); - Assert.True(skipList.Count == 101); - } + Assert.True(skipList.Count == 101); } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/SortedDictionaryTests.cs b/UnitTest/DataStructuresTests/SortedDictionaryTests.cs index ff84a30e..daf4e33a 100644 --- a/UnitTest/DataStructuresTests/SortedDictionaryTests.cs +++ b/UnitTest/DataStructuresTests/SortedDictionaryTests.cs @@ -2,133 +2,130 @@ using System.Linq; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class SortedDictionaryTests { - public static class SortedDictionaryTests + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() + var sortedDict = new DataStructures.SortedCollections.SortedDictionary(); + + string[] keys = new string[13] { + "A", "B", "C", "D", "E", "ABC", "Ahmad", "Bic", + "Carter", "Konstantinos", "Olympos", "Tareq", "Ziad" + }; + + int[] values = new int[13] { + 26, 27, 28, 29, 30, 40, 10, 11, + 12, 13, 14, 15, 16 + }; + + // + // Test Add + for (int i = 0; i < 13; ++i) + { + // insert + sortedDict.Add(keys[i], values[i]); + } + + // + // Assert correct number of elements + Assert.True(sortedDict.Count == 13, "Wrong number of elements in dictionary."); + + // + // Test get via index-access notation + Assert.True(sortedDict["A"] == 26); + Assert.True(sortedDict["B"] == 27); + Assert.True(sortedDict["C"] == 28); + Assert.True(sortedDict["D"] == 29); + Assert.True(sortedDict["E"] == 30); + Assert.True(sortedDict["ABC"] == 40); + Assert.True(sortedDict["Ahmad"] == 10); + Assert.True(sortedDict["Bic"] == 11); + Assert.True(sortedDict["Carter"] == 12); + Assert.True(sortedDict["Konstantinos"] == 13); + Assert.True(sortedDict["Olympos"] == 14); + Assert.True(sortedDict["Tareq"] == 15); + Assert.True(sortedDict["Ziad"] == 16); + + // + // Test update + int bak1 = sortedDict["Ahmad"]; + int bak2 = sortedDict["ABC"]; + sortedDict["Ahmad"] = 100; + sortedDict["ABC"] = 200; + + Assert.True(sortedDict["ABC"] == 200, "Expcted ABC to be set to 200."); + Assert.True(sortedDict["Ahmad"] == 100, "Expected Ahmad to be set to 100."); + + // Restore + sortedDict["Ahmad"] = bak1; + sortedDict["ABC"] = bak2; + + // + // Test TryGetValue for existing items + int existingItemKeyValue; + var tryGetStatus = sortedDict.TryGetValue("Ziad", out existingItemKeyValue); + Assert.True(tryGetStatus, "Expected the TryGet returned status to be true."); + Assert.True(existingItemKeyValue == 16, "Expected Ziad to be set to 16."); + + // + // Test TryGetValue for non-existing items + int nonExistingItemKeyValue; + tryGetStatus = sortedDict.TryGetValue("SomeNonExistentKey", out nonExistingItemKeyValue); + Assert.False(tryGetStatus, "Expected the TryGet returned status to be false."); + Assert.True(existingItemKeyValue == 16, "Expected the returned value for a non-existent key to be 0."); + + // + // Test Remove + var previousCount = sortedDict.Count; + var removeStatus = sortedDict.Remove("Ziad"); + Assert.True(removeStatus, "Expected removeStatus to be true."); + Assert.False(sortedDict.ContainsKey("Ziad"), "Expected Ziad to be removed."); + Assert.True(sortedDict.Count == previousCount - 1, "Expected Count to decrease after Remove operation."); + + // + // Test CopyTo returns a sorted array of key-value pairs (sorted by key). + var array = new KeyValuePair[sortedDict.Count]; + sortedDict.CopyTo(array, 0); + + // Prepare the sort testing data + var keyValuePairsList = new List>(sortedDict.Count); + for (int i = 0; i < sortedDict.Count; ++i) { - var sortedDict = new DataStructures.SortedCollections.SortedDictionary(); - - string[] keys = new string[13] { - "A", "B", "C", "D", "E", "ABC", "Ahmad", "Bic", - "Carter", "Konstantinos", "Olympos", "Tareq", "Ziad" - }; - - int[] values = new int[13] { - 26, 27, 28, 29, 30, 40, 10, 11, - 12, 13, 14, 15, 16 - }; - - // - // Test Add - for (int i = 0; i < 13; ++i) - { - // insert - sortedDict.Add(keys[i], values[i]); - } - - // - // Assert correct number of elements - Assert.True(sortedDict.Count == 13, "Wrong number of elements in dictionary."); - - // - // Test get via index-access notation - Assert.True(sortedDict["A"] == 26); - Assert.True(sortedDict["B"] == 27); - Assert.True(sortedDict["C"] == 28); - Assert.True(sortedDict["D"] == 29); - Assert.True(sortedDict["E"] == 30); - Assert.True(sortedDict["ABC"] == 40); - Assert.True(sortedDict["Ahmad"] == 10); - Assert.True(sortedDict["Bic"] == 11); - Assert.True(sortedDict["Carter"] == 12); - Assert.True(sortedDict["Konstantinos"] == 13); - Assert.True(sortedDict["Olympos"] == 14); - Assert.True(sortedDict["Tareq"] == 15); - Assert.True(sortedDict["Ziad"] == 16); - - // - // Test update - int bak1 = sortedDict["Ahmad"]; - int bak2 = sortedDict["ABC"]; - sortedDict["Ahmad"] = 100; - sortedDict["ABC"] = 200; - - Assert.True(sortedDict["ABC"] == 200, "Expcted ABC to be set to 200."); - Assert.True(sortedDict["Ahmad"] == 100, "Expected Ahmad to be set to 100."); - - // Restore - sortedDict["Ahmad"] = bak1; - sortedDict["ABC"] = bak2; - - // - // Test TryGetValue for existing items - int existingItemKeyValue; - var tryGetStatus = sortedDict.TryGetValue("Ziad", out existingItemKeyValue); - Assert.True(tryGetStatus, "Expected the TryGet returned status to be true."); - Assert.True(existingItemKeyValue == 16, "Expected Ziad to be set to 16."); - - // - // Test TryGetValue for non-existing items - int nonExistingItemKeyValue; - tryGetStatus = sortedDict.TryGetValue("SomeNonExistentKey", out nonExistingItemKeyValue); - Assert.False(tryGetStatus, "Expected the TryGet returned status to be false."); - Assert.True(existingItemKeyValue == 16, "Expected the returned value for a non-existent key to be 0."); - - // - // Test Remove - var previousCount = sortedDict.Count; - var removeStatus = sortedDict.Remove("Ziad"); - Assert.True(removeStatus, "Expected removeStatus to be true."); - Assert.False(sortedDict.ContainsKey("Ziad"), "Expected Ziad to be removed."); - Assert.True(sortedDict.Count == previousCount - 1, "Expected Count to decrease after Remove operation."); - - // - // Test CopyTo returns a sorted array of key-value pairs (sorted by key). - var array = new KeyValuePair[sortedDict.Count]; - sortedDict.CopyTo(array, 0); - - // Prepare the sort testing data - var keyValuePairsList = new List>(sortedDict.Count); - for (int i = 0; i < sortedDict.Count; ++i) - { - if (keys[i] == "Ziad") // deleted previously from sortedDictionary - continue; - keyValuePairsList.Add(new KeyValuePair(keys[i], values[i])); - } - - // Sort dictionary - keyValuePairsList = keyValuePairsList.OrderBy(item => item.Key, new KeyComparer()).ToList(); - - // begin sorting test - for (int i = 0; i < sortedDict.Count; i++) - { - // Keys - string key1 = array[i].Key; - string key2 = keyValuePairsList[i].Key; - - // Values - int val1 = array[i].Value; - int val2 = keyValuePairsList[i].Value; - - Assert.True(key1.Equals(key2, System.StringComparison.Ordinal), "Unmatched order of items!"); - Assert.Equal(val1, val2); - } - - // - // Test Clear - sortedDict.Clear(); - Assert.True(sortedDict.Count == 0, "Expected sortedDict to be empty!"); + if (keys[i] == "Ziad") // deleted previously from sortedDictionary + continue; + keyValuePairsList.Add(new KeyValuePair(keys[i], values[i])); } + // Sort dictionary + keyValuePairsList = keyValuePairsList.OrderBy(item => item.Key, new KeyComparer()).ToList(); - private class KeyComparer : IComparer + // begin sorting test + for (int i = 0; i < sortedDict.Count; i++) { - public int Compare(string x, string y) => string.CompareOrdinal(x, y); + // Keys + string key1 = array[i].Key; + string key2 = keyValuePairsList[i].Key; + + // Values + int val1 = array[i].Value; + int val2 = keyValuePairsList[i].Value; + + Assert.True(key1.Equals(key2, System.StringComparison.Ordinal), "Unmatched order of items!"); + Assert.Equal(val1, val2); } + + // + // Test Clear + sortedDict.Clear(); + Assert.True(sortedDict.Count == 0, "Expected sortedDict to be empty!"); } -} + private class KeyComparer : IComparer + { + public int Compare(string x, string y) => string.CompareOrdinal(x, y); + } +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/SortedListTests.cs b/UnitTest/DataStructuresTests/SortedListTests.cs index a79f991d..34e535a0 100644 --- a/UnitTest/DataStructuresTests/SortedListTests.cs +++ b/UnitTest/DataStructuresTests/SortedListTests.cs @@ -2,124 +2,122 @@ using System; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class SortedListTests { - public static class SortedListTests + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() + // New empty sorted list + var sortedList = new SortedList(); + + // Expeted outcome + var expectedSort = new int[15] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35 }; + + // Insert items in arbitrary-order + sortedList.Add(35); + sortedList.Add(5); + sortedList.Add(10); + sortedList.Add(15); + sortedList.Add(20); + sortedList.Add(1); + sortedList.Add(6); + sortedList.Add(2); + sortedList.Add(7); + sortedList.Add(3); + sortedList.Add(8); + sortedList.Add(4); + sortedList.Add(9); + sortedList.Add(30); + sortedList.Add(25); + + + // + // Helper variables + int index = 0; + var enumerator = sortedList.GetEnumerator(); + + // + // Begin comparison + // Compare length and count + Assert.Equal(sortedList.Count, expectedSort.Length); + + // + // Compare sort order + while (enumerator.MoveNext() && index < expectedSort.Length) { - // New empty sorted list - var sortedList = new SortedList(); - - // Expeted outcome - var expectedSort = new int[15] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35 }; - - // Insert items in arbitrary-order - sortedList.Add(35); - sortedList.Add(5); - sortedList.Add(10); - sortedList.Add(15); - sortedList.Add(20); - sortedList.Add(1); - sortedList.Add(6); - sortedList.Add(2); - sortedList.Add(7); - sortedList.Add(3); - sortedList.Add(8); - sortedList.Add(4); - sortedList.Add(9); - sortedList.Add(30); - sortedList.Add(25); - - - // - // Helper variables - int index = 0; - var enumerator = sortedList.GetEnumerator(); - - // - // Begin comparison - // Compare length and count - Assert.Equal(sortedList.Count, expectedSort.Length); - - // - // Compare sort order - while (enumerator.MoveNext() && index < expectedSort.Length) - { - Assert.Equal(enumerator.Current, expectedSort[index]); - index++; - } - - // - // Assert index access - index = 0; - while (index < sortedList.Count && index < expectedSort.Length) - { - Assert.Equal(sortedList[index], expectedSort[index]); - index++; - } - - // - // Assert removal of items correctly - Assert.True(sortedList.Contains(10), "Expected 10 to exist in sortedList."); - var remove10Status = sortedList.Remove(10); - Assert.True(remove10Status, "Expected 10 to be removed successfully."); - Assert.False(sortedList.Contains(10), "Expected 10 to be removed from sortedList."); - - // - // Assert non-removal of non-existing items - Assert.False(sortedList.Contains(999999999), "Expected 999999999 to not exist in sortedList."); - var remove999999999Status = sortedList.Remove(999999999); - Assert.False(remove999999999Status, "Expected 999999999 to not be removed successfully."); - Assert.False(sortedList.Contains(999999999), "Expected 999999999 to not exist in sortedList."); - - // - // Assert throws exception - var threwException = false; - - try - { - sortedList.RemoveAt(sortedList.Count * 2); // illegal index - } - catch (IndexOutOfRangeException) - { - threwException = true; - } - - Assert.True(threwException, "Expected to throw an exception on illegal index."); - - // - // Assert indexOf returns correct information - Assert.True(0 == sortedList.IndexOf(1), "Expected 1 to be the smallest number and hence at index 0."); - Assert.True(-1 == sortedList.IndexOf(987654321), "Expected 987654321 not to be in sortedList."); - - // - // Assert correct sort after updating on index - // Add back 10 - sortedList.Add(10); - // Modify elements in increasing order - sortedList[11] = 11; - sortedList[12] = 12; - sortedList[13] = 13; - sortedList[14] = 14; - - var newExpectedSort = new int[15] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; - - index = 0; - enumerator = sortedList.GetEnumerator(); - - // Compare length and count - Assert.True(sortedList.Count == newExpectedSort.Length, "Wrong number of items."); - - // Compare sort order - while (enumerator.MoveNext() && index < newExpectedSort.Length) - { - // TODO: Verify - Assert.True(enumerator.Current == newExpectedSort[index], "Wrong sorting order."); - index++; - } + Assert.Equal(enumerator.Current, expectedSort[index]); + index++; + } + + // + // Assert index access + index = 0; + while (index < sortedList.Count && index < expectedSort.Length) + { + Assert.Equal(sortedList[index], expectedSort[index]); + index++; + } + + // + // Assert removal of items correctly + Assert.True(sortedList.Contains(10), "Expected 10 to exist in sortedList."); + var remove10Status = sortedList.Remove(10); + Assert.True(remove10Status, "Expected 10 to be removed successfully."); + Assert.False(sortedList.Contains(10), "Expected 10 to be removed from sortedList."); + + // + // Assert non-removal of non-existing items + Assert.False(sortedList.Contains(999999999), "Expected 999999999 to not exist in sortedList."); + var remove999999999Status = sortedList.Remove(999999999); + Assert.False(remove999999999Status, "Expected 999999999 to not be removed successfully."); + Assert.False(sortedList.Contains(999999999), "Expected 999999999 to not exist in sortedList."); + + // + // Assert throws exception + var threwException = false; + + try + { + sortedList.RemoveAt(sortedList.Count * 2); // illegal index + } + catch (IndexOutOfRangeException) + { + threwException = true; } - } -} + Assert.True(threwException, "Expected to throw an exception on illegal index."); + + // + // Assert indexOf returns correct information + Assert.True(0 == sortedList.IndexOf(1), "Expected 1 to be the smallest number and hence at index 0."); + Assert.True(-1 == sortedList.IndexOf(987654321), "Expected 987654321 not to be in sortedList."); + + // + // Assert correct sort after updating on index + // Add back 10 + sortedList.Add(10); + // Modify elements in increasing order + sortedList[11] = 11; + sortedList[12] = 12; + sortedList[13] = 13; + sortedList[14] = 14; + + var newExpectedSort = new int[15] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + + index = 0; + enumerator = sortedList.GetEnumerator(); + + // Compare length and count + Assert.True(sortedList.Count == newExpectedSort.Length, "Wrong number of items."); + + // Compare sort order + while (enumerator.MoveNext() && index < newExpectedSort.Length) + { + // TODO: Verify + Assert.True(enumerator.Current == newExpectedSort[index], "Wrong sorting order."); + index++; + } + } +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/StackTest.cs b/UnitTest/DataStructuresTests/StackTest.cs index 31a34165..cf503e58 100644 --- a/UnitTest/DataStructuresTests/StackTest.cs +++ b/UnitTest/DataStructuresTests/StackTest.cs @@ -1,47 +1,45 @@ using DataStructures.Lists; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class StackTest { - public static class StackTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() - { - int top; - Stack stack = new Stack(); + int top; + Stack stack = new Stack(); - stack.Push(1); - stack.Push(2); - stack.Push(3); - stack.Push(4); - stack.Push(5); - stack.Push(6); + stack.Push(1); + stack.Push(2); + stack.Push(3); + stack.Push(4); + stack.Push(5); + stack.Push(6); - // Wrong top value. - Assert.Equal(6, stack.Top); + // Wrong top value. + Assert.Equal(6, stack.Top); - var array = stack.ToArray(); + var array = stack.ToArray(); - // Wrong size! - Assert.Equal(array.Length, stack.Count); + // Wrong size! + Assert.Equal(array.Length, stack.Count); - top = stack.Pop(); + top = stack.Pop(); - // Wrong top value. - Assert.Equal(5, stack.Top); + // Wrong top value. + Assert.Equal(5, stack.Top); - stack.Pop(); - stack.Pop(); + stack.Pop(); + stack.Pop(); - // Wrong top value. - Assert.Equal(3, stack.Top); + // Wrong top value. + Assert.Equal(3, stack.Top); - var array2 = stack.ToArray(); + var array2 = stack.ToArray(); - // Wrong size! - Assert.Equal(array2.Length, stack.Count); - } + // Wrong size! + Assert.Equal(array2.Length, stack.Count); } -} - +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/TernarySearchTreeTest.cs b/UnitTest/DataStructuresTests/TernarySearchTreeTest.cs index 28377873..fa9f6fd5 100644 --- a/UnitTest/DataStructuresTests/TernarySearchTreeTest.cs +++ b/UnitTest/DataStructuresTests/TernarySearchTreeTest.cs @@ -4,33 +4,32 @@ using System.Text; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class TernarySearchTreeTest { - public static class TernarySearchTreeTest - { - // c - // / | \ - // a u h - // | | | \ - // t t e u - // / / | / | - // s p e i s - [Fact] - public static void DoTest() - { - string[] words = new string[] { "cute", "cup", "at", "as", "he", "us", "i" }; + // c + // / | \ + // a u h + // | | | \ + // t t e u + // / / | / | + // s p e i s + [Fact] + public static void DoTest() + { + string[] words = new string[] { "cute", "cup", "at", "as", "he", "us", "i" }; - TernarySearchTree tree = new TernarySearchTree(); + TernarySearchTree tree = new TernarySearchTree(); - tree.Insert(words); + tree.Insert(words); - Assert.Equal('c', tree.Root.Value); - Assert.Equal('h', tree.Root.GetRightChild.Value); - Assert.Equal('e', tree.Root.GetRightChild.GetMiddleChild.Value); - Assert.Equal('p', tree.Root.GetMiddleChild.GetMiddleChild.GetLeftChild.Value); - Assert.Equal('s', tree.Root.GetLeftChild.GetMiddleChild.GetLeftChild.Value); + Assert.Equal('c', tree.Root.Value); + Assert.Equal('h', tree.Root.GetRightChild.Value); + Assert.Equal('e', tree.Root.GetRightChild.GetMiddleChild.Value); + Assert.Equal('p', tree.Root.GetMiddleChild.GetMiddleChild.GetLeftChild.Value); + Assert.Equal('s', tree.Root.GetLeftChild.GetMiddleChild.GetLeftChild.Value); - } } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/TrieMapTest.cs b/UnitTest/DataStructuresTests/TrieMapTest.cs index 25a4dd4d..5832a4ce 100644 --- a/UnitTest/DataStructuresTests/TrieMapTest.cs +++ b/UnitTest/DataStructuresTests/TrieMapTest.cs @@ -4,137 +4,136 @@ using DataStructures.Trees; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class TrieMapTest { - public static class TrieMapTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() + var trieMap = new TrieMap(); + + // Insert some how to words + const string prefixHowTo = "How to make"; + var wordHowToSand = prefixHowTo + " a sandwitch"; + var wordHowToRobot = prefixHowTo + " a robot"; + var wordHowToOmelet = prefixHowTo + " an omelet"; + var wordHowToProp = prefixHowTo + " a proposal"; + var listOfHow = new List { wordHowToSand, wordHowToRobot, wordHowToOmelet, wordHowToProp }; + trieMap.Add(wordHowToOmelet, 7); + trieMap.Add(wordHowToSand, 11); + trieMap.Add(wordHowToRobot, 15); + trieMap.Add(wordHowToProp, 19); + + // Count of words = 4 + Debug.Assert(trieMap.Count == 4); + + // Insert some dictionary words + var prefixAct = "act"; + var wordActs = prefixAct + "s"; + var wordActor = prefixAct + "or"; + var wordActing = prefixAct + "ing"; + var wordActress = prefixAct + "ress"; + var wordActive = prefixAct + "ive"; + var listOfActWords = new List { wordActs, wordActor, wordActing, wordActress, wordActive }; + trieMap.Add(wordActress, 82); + trieMap.Add(wordActive, 65); + trieMap.Add(wordActing, 34); + trieMap.Add(wordActs, 81); + trieMap.Add(wordActor, 32); + + // Count of words = 9 + Assert.Equal(9, trieMap.Count); + + // ASSERT THE WORDS IN TRIE. + + // Search for a word that doesn't exist + Assert.False(trieMap.ContainsWord(prefixHowTo)); + + // Search for prefix + Assert.True(trieMap.ContainsPrefix(prefixHowTo)); + + // Search for a prefix using a word + Assert.True(trieMap.ContainsPrefix(wordHowToSand)); + + // Get all words that start with the how-to prefix + var someHowToWords = trieMap.SearchByPrefix(prefixHowTo).ToList(); + Assert.Equal(someHowToWords.Count, listOfHow.Count); + + // Assert there are only two words under the prefix "acti" -> active, & acting + var someActiWords = trieMap.SearchByPrefix("acti").Select(item => item.Key).ToList(); + Assert.Equal(2, someActiWords.Count); + Assert.Contains(wordActing, someActiWords); + Assert.Contains(wordActive, someActiWords); + + // Assert that "acto" is not a word + Assert.False(trieMap.ContainsWord("acto")); + + // + // TEST GETTING VALUES ASSOCIATED TO WORDS + int actressRecord; + trieMap.SearchByWord(wordActress, out actressRecord); + Assert.Equal(82, actressRecord); + int howToProposeRequests; + trieMap.SearchByWord(wordHowToProp, out howToProposeRequests); + Assert.Equal(19, howToProposeRequests); + + // + // TEST DELETING SOMETHINGS + + // Removing a prefix should fail + bool removingActoFails; + try + { + // try removing a non-terminal word + trieMap.Remove("acto"); + removingActoFails = false; + } + catch + { + // if exception occured then code works, word doesn't exist. + removingActoFails = true; + } + + Assert.True(removingActoFails); + Assert.Equal(9, trieMap.Count); + + // Removing a word should work + bool removingActingPasses; + try + { + // try removing a non-terminal word + trieMap.Remove(wordActing); + removingActingPasses = true; + } + catch + { + // if exception occured then code DOESN'T work, word does exist. + removingActingPasses = false; + } + + Assert.True(removingActingPasses); + Assert.Equal(8, trieMap.Count); + someActiWords = trieMap.SearchByPrefix("acti").Select(item => item.Key).ToList(); + Assert.Single(someActiWords); + Assert.Contains(wordActive, someActiWords); + + // + // TEST ENUMERATOR + var enumerator = trieMap.GetEnumerator(); + var allWords = new List(); + while (enumerator.MoveNext()) + { + allWords.Add(enumerator.Current.Key); + } + + // Assert size + Assert.Equal(allWords.Count, trieMap.Count); + + // Assert each element + foreach (var word in allWords) { - var trieMap = new TrieMap(); - - // Insert some how to words - const string prefixHowTo = "How to make"; - var wordHowToSand = prefixHowTo + " a sandwitch"; - var wordHowToRobot = prefixHowTo + " a robot"; - var wordHowToOmelet = prefixHowTo + " an omelet"; - var wordHowToProp = prefixHowTo + " a proposal"; - var listOfHow = new List { wordHowToSand, wordHowToRobot, wordHowToOmelet, wordHowToProp }; - trieMap.Add(wordHowToOmelet, 7); - trieMap.Add(wordHowToSand, 11); - trieMap.Add(wordHowToRobot, 15); - trieMap.Add(wordHowToProp, 19); - - // Count of words = 4 - Debug.Assert(trieMap.Count == 4); - - // Insert some dictionary words - var prefixAct = "act"; - var wordActs = prefixAct + "s"; - var wordActor = prefixAct + "or"; - var wordActing = prefixAct + "ing"; - var wordActress = prefixAct + "ress"; - var wordActive = prefixAct + "ive"; - var listOfActWords = new List { wordActs, wordActor, wordActing, wordActress, wordActive }; - trieMap.Add(wordActress, 82); - trieMap.Add(wordActive, 65); - trieMap.Add(wordActing, 34); - trieMap.Add(wordActs, 81); - trieMap.Add(wordActor, 32); - - // Count of words = 9 - Assert.Equal(9, trieMap.Count); - - // ASSERT THE WORDS IN TRIE. - - // Search for a word that doesn't exist - Assert.False(trieMap.ContainsWord(prefixHowTo)); - - // Search for prefix - Assert.True(trieMap.ContainsPrefix(prefixHowTo)); - - // Search for a prefix using a word - Assert.True(trieMap.ContainsPrefix(wordHowToSand)); - - // Get all words that start with the how-to prefix - var someHowToWords = trieMap.SearchByPrefix(prefixHowTo).ToList(); - Assert.Equal(someHowToWords.Count, listOfHow.Count); - - // Assert there are only two words under the prefix "acti" -> active, & acting - var someActiWords = trieMap.SearchByPrefix("acti").Select(item => item.Key).ToList(); - Assert.Equal(2, someActiWords.Count); - Assert.Contains(wordActing, someActiWords); - Assert.Contains(wordActive, someActiWords); - - // Assert that "acto" is not a word - Assert.False(trieMap.ContainsWord("acto")); - - // - // TEST GETTING VALUES ASSOCIATED TO WORDS - int actressRecord; - trieMap.SearchByWord(wordActress, out actressRecord); - Assert.Equal(82, actressRecord); - int howToProposeRequests; - trieMap.SearchByWord(wordHowToProp, out howToProposeRequests); - Assert.Equal(19, howToProposeRequests); - - // - // TEST DELETING SOMETHINGS - - // Removing a prefix should fail - bool removingActoFails; - try - { - // try removing a non-terminal word - trieMap.Remove("acto"); - removingActoFails = false; - } - catch - { - // if exception occured then code works, word doesn't exist. - removingActoFails = true; - } - - Assert.True(removingActoFails); - Assert.Equal(9, trieMap.Count); - - // Removing a word should work - bool removingActingPasses; - try - { - // try removing a non-terminal word - trieMap.Remove(wordActing); - removingActingPasses = true; - } - catch - { - // if exception occured then code DOESN'T work, word does exist. - removingActingPasses = false; - } - - Assert.True(removingActingPasses); - Assert.Equal(8, trieMap.Count); - someActiWords = trieMap.SearchByPrefix("acti").Select(item => item.Key).ToList(); - Assert.Single(someActiWords); - Assert.Contains(wordActive, someActiWords); - - // - // TEST ENUMERATOR - var enumerator = trieMap.GetEnumerator(); - var allWords = new List(); - while (enumerator.MoveNext()) - { - allWords.Add(enumerator.Current.Key); - } - - // Assert size - Assert.Equal(allWords.Count, trieMap.Count); - - // Assert each element - foreach (var word in allWords) - { - Assert.True(listOfActWords.Contains(word) || listOfHow.Contains(word)); - } + Assert.True(listOfActWords.Contains(word) || listOfHow.Contains(word)); } } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/TrieTest.cs b/UnitTest/DataStructuresTests/TrieTest.cs index 0ab79f3b..77d6eeba 100644 --- a/UnitTest/DataStructuresTests/TrieTest.cs +++ b/UnitTest/DataStructuresTests/TrieTest.cs @@ -4,139 +4,138 @@ using DataStructures.Trees; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public static class TrieTest { - public static class TrieTest + [Fact] + public static void DoTest() { - [Fact] - public static void DoTest() + var trie = new Trie(); + + // Insert some how to words + var prefix_howTo = "How to make"; + + var word_howToSand = prefix_howTo + " a sandwitch"; + var word_howToRobot = prefix_howTo + " a robot"; + var word_howToOmelet = prefix_howTo + " an omelet"; + var word_howToProp = prefix_howTo + " a proposal"; + var listOfHow = new List() { word_howToSand, word_howToRobot, word_howToOmelet, word_howToProp }; + + trie.Add(word_howToOmelet); + trie.Add(word_howToSand); + trie.Add(word_howToRobot); + trie.Add(word_howToProp); + + // Count of words = 4 + Assert.Equal(4, trie.Count); + + // Insert some dictionary words + var prefix_act = "act"; + + var word_acts = prefix_act + "s"; + var word_actor = prefix_act + "or"; + var word_acting = prefix_act + "ing"; + var word_actress = prefix_act + "ress"; + var word_active = prefix_act + "ive"; + var listOfActWords = new List() { word_acts, word_actor, word_acting, word_actress, word_active }; + + trie.Add(word_actress); + trie.Add(word_active); + trie.Add(word_acting); + trie.Add(word_acts); + trie.Add(word_actor); + + // Count of words = 9 + Assert.Equal(9, trie.Count); + + // + // ASSERT THE WORDS IN TRIE. + + // Search for a word that doesn't exist + Assert.False(trie.ContainsWord(prefix_howTo)); + + // Search for prefix + Assert.True(trie.ContainsPrefix(prefix_howTo)); + + // Search for a prefix using a word + Assert.True(trie.ContainsPrefix(word_howToSand)); + + // Get all words that start with the how-to prefix + var someHowToWords = trie.SearchByPrefix(prefix_howTo).ToList(); + Assert.Equal(someHowToWords.Count, listOfHow.Count); + + // Assert there are only two words under the prefix "acti" -> active, & acting + var someActiWords = trie.SearchByPrefix("acti").ToList(); + Assert.True(someActiWords.Count == 2); + Assert.Contains(word_acting, someActiWords); + Assert.Contains(word_active, someActiWords); + + // Assert that "acto" is not a word + Assert.False(trie.ContainsWord("acto")); + + // Check the existance of other words + Assert.True(trie.ContainsWord(word_actress)); + Assert.True(trie.ContainsWord(word_howToProp)); + + + + // + // TEST DELETING SOMETHINGS + + // Removing a prefix should fail + var removing_acto_fails = false; + try + { + // try removing a non-terminal word + trie.Remove("acto"); + removing_acto_fails = false; + } + catch + { + // if exception occured then code works, word doesn't exist. + removing_acto_fails = true; + } + + Assert.True(removing_acto_fails); + Assert.True(trie.Count == 9); + + // Removing a word should work + var removing_acting_passes = false; + try + { + // try removing a non-terminal word + trie.Remove(word_acting); + removing_acting_passes = true; + } + catch { - var trie = new Trie(); - - // Insert some how to words - var prefix_howTo = "How to make"; - - var word_howToSand = prefix_howTo + " a sandwitch"; - var word_howToRobot = prefix_howTo + " a robot"; - var word_howToOmelet = prefix_howTo + " an omelet"; - var word_howToProp = prefix_howTo + " a proposal"; - var listOfHow = new List() { word_howToSand, word_howToRobot, word_howToOmelet, word_howToProp }; - - trie.Add(word_howToOmelet); - trie.Add(word_howToSand); - trie.Add(word_howToRobot); - trie.Add(word_howToProp); - - // Count of words = 4 - Assert.Equal(4, trie.Count); - - // Insert some dictionary words - var prefix_act = "act"; - - var word_acts = prefix_act + "s"; - var word_actor = prefix_act + "or"; - var word_acting = prefix_act + "ing"; - var word_actress = prefix_act + "ress"; - var word_active = prefix_act + "ive"; - var listOfActWords = new List() { word_acts, word_actor, word_acting, word_actress, word_active }; - - trie.Add(word_actress); - trie.Add(word_active); - trie.Add(word_acting); - trie.Add(word_acts); - trie.Add(word_actor); - - // Count of words = 9 - Assert.Equal(9, trie.Count); - - // - // ASSERT THE WORDS IN TRIE. - - // Search for a word that doesn't exist - Assert.False(trie.ContainsWord(prefix_howTo)); - - // Search for prefix - Assert.True(trie.ContainsPrefix(prefix_howTo)); - - // Search for a prefix using a word - Assert.True(trie.ContainsPrefix(word_howToSand)); - - // Get all words that start with the how-to prefix - var someHowToWords = trie.SearchByPrefix(prefix_howTo).ToList(); - Assert.Equal(someHowToWords.Count, listOfHow.Count); - - // Assert there are only two words under the prefix "acti" -> active, & acting - var someActiWords = trie.SearchByPrefix("acti").ToList(); - Assert.True(someActiWords.Count == 2); - Assert.Contains(word_acting, someActiWords); - Assert.Contains(word_active, someActiWords); - - // Assert that "acto" is not a word - Assert.False(trie.ContainsWord("acto")); - - // Check the existance of other words - Assert.True(trie.ContainsWord(word_actress)); - Assert.True(trie.ContainsWord(word_howToProp)); - - - - // - // TEST DELETING SOMETHINGS - - // Removing a prefix should fail - var removing_acto_fails = false; - try - { - // try removing a non-terminal word - trie.Remove("acto"); - removing_acto_fails = false; - } - catch - { - // if exception occured then code works, word doesn't exist. - removing_acto_fails = true; - } - - Assert.True(removing_acto_fails); - Assert.True(trie.Count == 9); - - // Removing a word should work - var removing_acting_passes = false; - try - { - // try removing a non-terminal word - trie.Remove(word_acting); - removing_acting_passes = true; - } - catch - { - // if exception occured then code DOESN'T work, word does exist. - removing_acting_passes = false; - } - - Assert.True(removing_acting_passes); - Assert.True(trie.Count == 8); - - someActiWords = trie.SearchByPrefix("acti").ToList(); - Assert.True(someActiWords.Count == 1); - Assert.Contains(word_active, someActiWords); - - - - // - // TEST ENUMERATOR - - var enumerator = trie.GetEnumerator(); - var allWords = new List(); - while (enumerator.MoveNext()) - allWords.Add(enumerator.Current); - - // Assert size - Assert.True(allWords.Count == trie.Count); - - // Assert each element - foreach (var word in allWords) - Debug.Assert(listOfActWords.Contains(word) || listOfHow.Contains(word)); + // if exception occured then code DOESN'T work, word does exist. + removing_acting_passes = false; } + + Assert.True(removing_acting_passes); + Assert.True(trie.Count == 8); + + someActiWords = trie.SearchByPrefix("acti").ToList(); + Assert.True(someActiWords.Count == 1); + Assert.Contains(word_active, someActiWords); + + + + // + // TEST ENUMERATOR + + var enumerator = trie.GetEnumerator(); + var allWords = new List(); + while (enumerator.MoveNext()) + allWords.Add(enumerator.Current); + + // Assert size + Assert.True(allWords.Count == trie.Count); + + // Assert each element + foreach (var word in allWords) + Debug.Assert(listOfActWords.Contains(word) || listOfHow.Contains(word)); } -} +} \ No newline at end of file diff --git a/UnitTest/DataStructuresTests/UndirectedWeightedDenseGraphTests.cs b/UnitTest/DataStructuresTests/UndirectedWeightedDenseGraphTests.cs index 6350e428..e0184490 100644 --- a/UnitTest/DataStructuresTests/UndirectedWeightedDenseGraphTests.cs +++ b/UnitTest/DataStructuresTests/UndirectedWeightedDenseGraphTests.cs @@ -4,200 +4,199 @@ using DataStructures.Graphs; using Xunit; -namespace UnitTest.DataStructuresTests +namespace UnitTest.DataStructuresTests; + +public class UndirectedWeightedDenseGraphTests { - public class UndirectedWeightedDenseGraphTests + [Fact] + public void IsWeighted_Should_AlwaysReturnTrue() + { + var graph = new UndirectedWeightedDenseGraph(); + Assert.True(graph.IsWeighted); + } + + [Fact] + public void AddEdge_ShouldCreateEdge_WithProvidedWeight() + { + var graph = new UndirectedWeightedDenseGraph(); + var vertices = new string[] { "a", "z", "s" }; + graph.AddVertices(vertices); + + Assert.True(graph.VerticesCount == 3); + Assert.True(graph.Vertices.SequenceEqual(vertices)); + + graph.AddEdge("a", "s", 1); + graph.AddEdge("a", "z", 2); + + Assert.True(graph.Edges.Count() == 2); + Assert.True(graph.EdgesCount == 2); + + var edgeToS = graph.GetEdge("a", "s"); + Assert.Equal("s", edgeToS.Destination); + Assert.Equal("a", edgeToS.Source); + Assert.Equal(1, edgeToS.Weight); + + var edgeToZ = graph.GetEdge("a", "z"); + Assert.Equal("z", edgeToZ.Destination); + Assert.Equal("a", edgeToZ.Source); + Assert.Equal(2, edgeToZ.Weight); + + var expectedOutgoingFromA = new List() { "z", "s" }; + Assert.True(graph.OutgoingEdges("a").Select(e => e.Destination).SequenceEqual(expectedOutgoingFromA)); + Assert.Single(graph.OutgoingEdges("s")); + Assert.Single(graph.OutgoingEdges("z")); + + var expectedIncomming = new List() { "a" }; + Assert.True(graph.IncomingEdges("s").Select(e => e.Source).SequenceEqual(expectedIncomming)); + Assert.True(graph.IncomingEdges("z").Select(e => e.Source).SequenceEqual(expectedIncomming)); + Assert.Equal(2, graph.IncomingEdges("a").Count()); + } + + [Fact] + public void GetEdge_ShouldThrowException_WhenSearchVertexNotFound() + { + var graph = new UndirectedWeightedDenseGraph(); + var vertices = new string[] { "a", "z", "s" }; + graph.AddVertices(vertices); + + graph.AddEdge("a", "s", 1); + graph.AddEdge("a", "z", 2); + + Assert.Throws(() => graph.GetEdge("a", "A")); + } + + [Fact] + public void GetEdge_ShouldReturnNull_WhenEdgeNotFound() + { + var graph = new UndirectedWeightedDenseGraph(); + var vertices = new string[] { "a", "z", "s", "b" }; + graph.AddVertices(vertices); + + graph.AddEdge("a", "s", 1); + graph.AddEdge("a", "z", 2); + + Assert.Null(graph.GetEdge("a", "b")); + } + + [Fact] + public void RemoveEdge_ShouldRemoveEdge_AndSetProperties() + { + var graph = new UndirectedWeightedDenseGraph(); + var vertices = new string[] { "a", "z", "s" }; + graph.AddVertices(vertices); + + graph.AddEdge("a", "s", 1); + graph.AddEdge("a", "z", 2); + + Assert.True(graph.Edges.Count() == 2); + Assert.True(graph.EdgesCount == 2); + + var expectedOutgoingFromA = new List() { "z", "s" }; + Assert.True(graph.OutgoingEdges("a").Select(e => e.Destination).SequenceEqual(expectedOutgoingFromA)); + Assert.True(graph.IncomingEdges("z").Any()); + + var result = graph.RemoveEdge("a", "z"); + Assert.True(result); + + Assert.True(graph.Edges.Count() == 1); + Assert.True(graph.EdgesCount == 1); + + expectedOutgoingFromA = new List() { "s" }; + Assert.True(graph.OutgoingEdges("a").Select(e => e.Destination).SequenceEqual(expectedOutgoingFromA)); + Assert.False(graph.IncomingEdges("z").Any()); + } + + [Fact] + public void RemoveEdge_ShouldThrowException_WhenVertexNotExists() + { + var graph = new UndirectedWeightedDenseGraph(); + var vertices = new string[] { "a", "z", "s" }; + graph.AddVertices(vertices); + + graph.AddEdge("a", "s", 1); + graph.AddEdge("a", "z", 2); + + Assert.Throws(() => graph.RemoveEdge("a", "A")); + Assert.Throws(() => graph.RemoveEdge("A", "a")); + } + + [Fact] + public void RemoveEdge_ShoudlReturnFalse_WhenEdgeNotExists() + { + var graph = new UndirectedWeightedDenseGraph(); + var vertices = new string[] { "a", "z", "s" }; + graph.AddVertices(vertices); + + graph.AddEdge("a", "s", 1); + + Assert.False(graph.RemoveEdge("a", "z")); + } + + [Fact] + public void OutgoingEdges_ShouldThrowException_WhenVertexIsNotExists() { - [Fact] - public void IsWeighted_Should_AlwaysReturnTrue() - { - var graph = new UndirectedWeightedDenseGraph(); - Assert.True(graph.IsWeighted); - } - - [Fact] - public void AddEdge_ShouldCreateEdge_WithProvidedWeight() - { - var graph = new UndirectedWeightedDenseGraph(); - var vertices = new string[] { "a", "z", "s" }; - graph.AddVertices(vertices); - - Assert.True(graph.VerticesCount == 3); - Assert.True(graph.Vertices.SequenceEqual(vertices)); - - graph.AddEdge("a", "s", 1); - graph.AddEdge("a", "z", 2); - - Assert.True(graph.Edges.Count() == 2); - Assert.True(graph.EdgesCount == 2); - - var edgeToS = graph.GetEdge("a", "s"); - Assert.Equal("s", edgeToS.Destination); - Assert.Equal("a", edgeToS.Source); - Assert.Equal(1, edgeToS.Weight); - - var edgeToZ = graph.GetEdge("a", "z"); - Assert.Equal("z", edgeToZ.Destination); - Assert.Equal("a", edgeToZ.Source); - Assert.Equal(2, edgeToZ.Weight); - - var expectedOutgoingFromA = new List() { "z", "s" }; - Assert.True(graph.OutgoingEdges("a").Select(e => e.Destination).SequenceEqual(expectedOutgoingFromA)); - Assert.Single(graph.OutgoingEdges("s")); - Assert.Single(graph.OutgoingEdges("z")); - - var expectedIncomming = new List() { "a" }; - Assert.True(graph.IncomingEdges("s").Select(e => e.Source).SequenceEqual(expectedIncomming)); - Assert.True(graph.IncomingEdges("z").Select(e => e.Source).SequenceEqual(expectedIncomming)); - Assert.Equal(2, graph.IncomingEdges("a").Count()); - } - - [Fact] - public void GetEdge_ShouldThrowException_WhenSearchVertexNotFound() - { - var graph = new UndirectedWeightedDenseGraph(); - var vertices = new string[] { "a", "z", "s" }; - graph.AddVertices(vertices); - - graph.AddEdge("a", "s", 1); - graph.AddEdge("a", "z", 2); - - Assert.Throws(() => graph.GetEdge("a", "A")); - } - - [Fact] - public void GetEdge_ShouldReturnNull_WhenEdgeNotFound() - { - var graph = new UndirectedWeightedDenseGraph(); - var vertices = new string[] { "a", "z", "s", "b" }; - graph.AddVertices(vertices); - - graph.AddEdge("a", "s", 1); - graph.AddEdge("a", "z", 2); - - Assert.Null(graph.GetEdge("a", "b")); - } - - [Fact] - public void RemoveEdge_ShouldRemoveEdge_AndSetProperties() - { - var graph = new UndirectedWeightedDenseGraph(); - var vertices = new string[] { "a", "z", "s" }; - graph.AddVertices(vertices); - - graph.AddEdge("a", "s", 1); - graph.AddEdge("a", "z", 2); - - Assert.True(graph.Edges.Count() == 2); - Assert.True(graph.EdgesCount == 2); - - var expectedOutgoingFromA = new List() { "z", "s" }; - Assert.True(graph.OutgoingEdges("a").Select(e => e.Destination).SequenceEqual(expectedOutgoingFromA)); - Assert.True(graph.IncomingEdges("z").Any()); - - var result = graph.RemoveEdge("a", "z"); - Assert.True(result); - - Assert.True(graph.Edges.Count() == 1); - Assert.True(graph.EdgesCount == 1); - - expectedOutgoingFromA = new List() { "s" }; - Assert.True(graph.OutgoingEdges("a").Select(e => e.Destination).SequenceEqual(expectedOutgoingFromA)); - Assert.False(graph.IncomingEdges("z").Any()); - } - - [Fact] - public void RemoveEdge_ShouldThrowException_WhenVertexNotExists() - { - var graph = new UndirectedWeightedDenseGraph(); - var vertices = new string[] { "a", "z", "s" }; - graph.AddVertices(vertices); - - graph.AddEdge("a", "s", 1); - graph.AddEdge("a", "z", 2); - - Assert.Throws(() => graph.RemoveEdge("a", "A")); - Assert.Throws(() => graph.RemoveEdge("A", "a")); - } - - [Fact] - public void RemoveEdge_ShoudlReturnFalse_WhenEdgeNotExists() - { - var graph = new UndirectedWeightedDenseGraph(); - var vertices = new string[] { "a", "z", "s" }; - graph.AddVertices(vertices); - - graph.AddEdge("a", "s", 1); - - Assert.False(graph.RemoveEdge("a", "z")); - } - - [Fact] - public void OutgoingEdges_ShouldThrowException_WhenVertexIsNotExists() - { - var graph = new UndirectedWeightedDenseGraph(); - var vertices = new string[] { "a", "z", "s" }; - graph.AddVertices(vertices); - - graph.AddEdge("a", "s", 1); - graph.AddEdge("a", "z", 2); - - Assert.Throws(() => graph.OutgoingEdges("A").Any()); - } - - [Fact] - public void IncommingEdges_ShouldThrowException_WhenVertexNotExists() - { - var graph = new UndirectedWeightedDenseGraph(); - var vertices = new string[] { "a", "z", "s" }; - graph.AddVertices(vertices); - - graph.AddEdge("a", "s", 1); - graph.AddEdge("a", "z", 2); - - Assert.Throws(() => graph.IncomingEdges("A").Any()); - } - - [Fact] - public void UpdateEdgeWeight_ShouldUpdateWeight_OfCSpecificEdge() - { - var graph = new UndirectedWeightedDenseGraph(); - var vertices = new string[] { "a", "z", "s" }; - graph.AddVertices(vertices); - - graph.AddEdge("a", "s", 1); - graph.AddEdge("a", "z", 2); - Assert.Equal(1, graph.GetEdgeWeight("a", "s")); - - graph.UpdateEdgeWeight("a", "s", 10); - Assert.Equal(10, graph.GetEdgeWeight("a", "s")); - } - - [Fact] - public void UpdateEdgeWeight_ShouldThrowException_WhenVertexNotFound() - { - var graph = new UndirectedWeightedDenseGraph(); - var vertices = new string[] { "a", "z", "s" }; - graph.AddVertices(vertices); - - graph.AddEdge("a", "s", 1); - graph.AddEdge("a", "z", 2); - - Assert.Throws(() => graph.UpdateEdgeWeight("A", "a", 10)); - Assert.Throws(() => graph.UpdateEdgeWeight("a", "A", 10)); - } - - [Fact] - public void UpdateEdgeWeight_ShouldReturnFalse_WhenEdgeNotFound() - { - var graph = new UndirectedWeightedDenseGraph(); - var vertices = new string[] { "a", "z", "s" }; - graph.AddVertices(vertices); - - graph.AddEdge("a", "s", 1); - graph.AddEdge("a", "z", 2); - - Assert.False(graph.UpdateEdgeWeight("z", "s", 10)); - } + var graph = new UndirectedWeightedDenseGraph(); + var vertices = new string[] { "a", "z", "s" }; + graph.AddVertices(vertices); + + graph.AddEdge("a", "s", 1); + graph.AddEdge("a", "z", 2); + + Assert.Throws(() => graph.OutgoingEdges("A").Any()); + } + + [Fact] + public void IncommingEdges_ShouldThrowException_WhenVertexNotExists() + { + var graph = new UndirectedWeightedDenseGraph(); + var vertices = new string[] { "a", "z", "s" }; + graph.AddVertices(vertices); + + graph.AddEdge("a", "s", 1); + graph.AddEdge("a", "z", 2); + + Assert.Throws(() => graph.IncomingEdges("A").Any()); + } + + [Fact] + public void UpdateEdgeWeight_ShouldUpdateWeight_OfCSpecificEdge() + { + var graph = new UndirectedWeightedDenseGraph(); + var vertices = new string[] { "a", "z", "s" }; + graph.AddVertices(vertices); + + graph.AddEdge("a", "s", 1); + graph.AddEdge("a", "z", 2); + Assert.Equal(1, graph.GetEdgeWeight("a", "s")); + + graph.UpdateEdgeWeight("a", "s", 10); + Assert.Equal(10, graph.GetEdgeWeight("a", "s")); + } + + [Fact] + public void UpdateEdgeWeight_ShouldThrowException_WhenVertexNotFound() + { + var graph = new UndirectedWeightedDenseGraph(); + var vertices = new string[] { "a", "z", "s" }; + graph.AddVertices(vertices); + + graph.AddEdge("a", "s", 1); + graph.AddEdge("a", "z", 2); + + Assert.Throws(() => graph.UpdateEdgeWeight("A", "a", 10)); + Assert.Throws(() => graph.UpdateEdgeWeight("a", "A", 10)); + } + + [Fact] + public void UpdateEdgeWeight_ShouldReturnFalse_WhenEdgeNotFound() + { + var graph = new UndirectedWeightedDenseGraph(); + var vertices = new string[] { "a", "z", "s" }; + graph.AddVertices(vertices); + + graph.AddEdge("a", "s", 1); + graph.AddEdge("a", "z", 2); + + Assert.False(graph.UpdateEdgeWeight("z", "s", 10)); } -} +} \ No newline at end of file