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();
}
}
}