namespace System.Collections.Generic { /// /// Treap implementation. /// /// Provided type. [Serializable] public sealed class Treap : ICollection where T : IComparable { #region Fields [Serializable] private class Node { public TKey Key; public int Priority; public Node Left, Right; public Node(TKey key, int priority) { Key = key; Priority = priority; Left = null; Right = null; } } private readonly Random randomGen; private Node root; private int count; #endregion #region Properties /// /// Count of values in the treap. /// public int Count { get { return count; } } /// /// Not implemented. /// public bool IsReadOnly => false; #endregion #region Constructors /// /// Constructor for treap. /// public Treap() { randomGen = new Random(); } #endregion #region Public Methods /// /// Adds value to the treap. /// /// Value to be added. public void Add(T value) { root = InsertNode(root, value); count++; } /// /// Removes value from treap. /// /// Value to be removed. public bool Remove(T value) { root = RemoveNode(root, value); count--; return true; } /// /// Clears the treap. /// public void Clear() { Clear(root); root = null; count = 0; } /// /// Determines whether the treap contains the specified value. /// /// Value to locate in the treap. /// public bool Contains(T value) { return Find(root, value) != null; } /// /// Returns the treap structure as an ordered array. /// /// Ordered array containing the values stored in the treap. public T[] ToArray() { if (root != null) { var array = new T[count]; var index = 0; ToArray(root, ref array, ref index); return array; } else { return null; } } /// /// Copy the treap into the provided array. /// /// Array to be populated with the values contained in the array. /// Starting index of the array. public void CopyTo(T[] array, int arrayIndex) { ToArray(root, ref array, ref arrayIndex); } /// /// Enumerator that iterates over the treap. Note that the values are not guaranteed to be sorted. /// /// Enumerator that iterates over the treap. public IEnumerator GetEnumerator() { return GetEnumerator(root); } #endregion #region Private Methods private Node InsertNode(Node node, T key) { if (node == null) { node = new Node(key, randomGen.Next(0, 100)); return node; } else if (key.CompareTo(node.Key) <= 0) { node.Left = InsertNode(node.Left, key); if (node.Left.Priority > node.Priority) { node = RotateRight(node); } } else { node.Right = InsertNode(node.Right, key); if (node.Right.Priority > node.Priority) { node = RotateLeft(node); } } return node; } private Node RemoveNode(Node node, T key) { if (node == null) { return node; } if (key.CompareTo(node.Key) < 0) { node.Left = RemoveNode(node.Left, key); } else if (key.CompareTo(node.Key) > 0) { node.Right = RemoveNode(node.Right, key); } else if (node.Left == null) { node = node.Right; } else if (node.Right == null) { node = node.Left; } else if (node.Left.Priority < node.Right.Priority) { node = RotateLeft(node); node.Left = RemoveNode(node.Left, key); } else { node = RotateRight(node); node.Right = RemoveNode(node.Right, key); } return node; } private Node RotateRight(Node node) { Node temp = node.Left, temp2 = temp.Right; temp.Right = node; node.Left = temp2; return temp; } private Node RotateLeft(Node node) { Node temp = node.Right, temp2 = temp.Left; temp.Left = node; node.Right = temp2; return temp; } private void Clear(Node node) { if (node.Left != null) { Clear(node.Left); } if (node.Right != null) { Clear(node.Right); } node.Left = node.Right = null; } private Node Find(Node node, T key) { if (node == null) { return node; } else { if (node.Key.CompareTo(key) < 0) { var found = Find(node.Left, key); if (found == null) { found = Find(node.Right, key); } return found; } else if (node.Key.CompareTo(key) > 0) { var found = Find(node.Right, key); if (found == null) { found = Find(node.Left, key); } return found; } else { return node; } } } private void ToArray(Node node, ref T[] array, ref int index) { if (node != null) { ToArray(node.Left, ref array, ref index); array[index] = node.Key; index++; ToArray(node.Right, ref array, ref index); } } private IEnumerator GetEnumerator(Node currentNode) { var queue = new Queue>(); queue.Enqueue(currentNode); while (queue.Count > 0) { currentNode = queue.Dequeue(); yield return currentNode.Key; if (currentNode.Left != null) { queue.Enqueue(currentNode.Left); } if (currentNode.Right != null) { queue.Enqueue(currentNode.Right); } } } IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); } #endregion } }