using System; using System.Collections; using System.Collections.Generic; namespace Advanced.Algorithms.DataStructures.Foundation { /// /// A sorted HashSet implementation using balanced binary search tree. IEnumerable will enumerate in sorted order. /// This may be better than regular HashSet implementation which can give o(K) in worst case (but O(1) amortized when collisions K is avoided). /// /// The value datatype. public class OrderedHashSet : IEnumerable where T : IComparable { //use red-black tree as our balanced BST since it gives good performance for both deletion/insertion private readonly RedBlackTree binarySearchTree; public int Count => binarySearchTree.Count; public OrderedHashSet() { binarySearchTree = new RedBlackTree(); } /// /// Initialize the sorted hashset with given sorted key collection. /// Time complexity: log(n). /// public OrderedHashSet(IEnumerable sortedKeys) { binarySearchTree = new RedBlackTree(sortedKeys); } /// /// Time complexity: O(log(n)) /// public T this[int index] { get => ElementAt(index); } /// /// Does this hash table contains the given value. /// Time complexity: O(log(n)). /// /// The value to check. /// True if this hashset contains the given value. public bool Contains(T value) { return binarySearchTree.HasItem(value); } /// /// Add a new key. /// Time complexity: O(log(n)). /// Returns the position (index) of the key in sorted order of this OrderedHashSet. /// public int Add(T key) { return binarySearchTree.Insert(key); } /// /// Time complexity: O(log(n)) /// public T ElementAt(int index) { return binarySearchTree.ElementAt(index); } /// /// Time complexity: O(log(n)) /// public int IndexOf(T key) { return binarySearchTree.IndexOf(key); } /// /// Remove the given key if present. /// Time complexity: O(log(n)). /// Returns the position (index) of the removed key if removed. Otherwise returns -1. /// public int Remove(T key) { return binarySearchTree.Delete(key); } /// /// Remove the element at given index. /// Time complexity: O(log(n)). /// public T RemoveAt(int index) { return binarySearchTree.RemoveAt(index); } /// /// Return the next higher value after given value in this hashset. /// Time complexity: O(log(n)). /// /// Null if the given value does'nt exist or next value does'nt exist. public T NextHigher(T value) { return binarySearchTree.NextHigher(value); } /// /// Return the next lower value before given value in this HashSet. /// Time complexity: O(log(n)). /// /// Null if the given value does'nt exist or previous value does'nt exist. public T NextLower(T value) { return binarySearchTree.NextLower(value); } /// /// Time complexity: O(log(n)). /// public T Max() { return binarySearchTree.Max(); } /// /// Time complexity: O(log(n)). /// public T Min() { return binarySearchTree.Min(); } /// /// Clear the hashtable. /// Time complexity: O(1). /// internal void Clear() { binarySearchTree.Clear(); } /// /// Descending enumerable. /// public IEnumerable AsEnumerableDesc() { return GetEnumeratorDesc().AsEnumerable(); } //Implementation for the GetEnumerator method. IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public IEnumerator GetEnumerator() { return binarySearchTree.GetEnumerator(); } public IEnumerator GetEnumeratorDesc() { return binarySearchTree.GetEnumeratorDesc(); } } }