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)
{
this.Key = key;
this.Priority = priority;
this.Left = null;
this.Right = null;
}
}
private readonly Random randomGen;
private Node root = default!;
private int count;
#endregion
#region Properties
///
/// Count of values in the treap.
///
public int Count
{
get
{
return this.count;
}
}
///
/// Not implemented.
///
public bool IsReadOnly => false;
#endregion
#region Constructors
///
/// Constructor for treap.
///
public Treap()
{
this.randomGen = new Random();
}
#endregion
#region Public Methods
///
/// Adds value to the treap.
///
/// Value to be added.
public void Add(T value)
{
this.root = this.InsertNode(this.root, value);
this.count++;
}
///
/// Removes value from treap.
///
/// Value to be removed.
public bool Remove(T value)
{
this.root = this.RemoveNode(this.root, value);
this.count--;
return true;
}
///
/// Clears the treap.
///
public void Clear()
{
this.Clear(this.root);
this.root = default!;
this.count = 0;
}
///
/// Determines whether the treap contains the specified value.
///
/// Value to locate in the treap.
///
public bool Contains(T value)
{
return this.Find(this.root, value) != null;
}
///
/// Returns the treap structure as an ordered array.
///
/// Ordered array containing the values stored in the treap.
public T[]? ToArray()
{
if (this.root != null)
{
var array = new T[this.count];
var index = 0;
this.ToArray(this.root, ref array, ref index);
return array;
}
else
{
return default!;
}
}
///
/// 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)
{
this.ToArray(this.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 this.GetEnumerator(this.root);
}
#endregion
#region Private Methods
private Node InsertNode(Node node, T key)
{
if (node == null)
{
node = new Node(key, this.randomGen.Next(0, 100));
return node;
}
else if (key.CompareTo(node.Key) <= 0)
{
node.Left = this.InsertNode(node.Left!, key);
if (node.Left!.Priority > node.Priority)
{
node = this.RotateRight(node);
}
}
else
{
node.Right = this.InsertNode(node.Right!, key);
if (node.Right!.Priority > node.Priority)
{
node = this.RotateLeft(node);
}
}
return node;
}
private Node RemoveNode(Node node, T key)
{
if (node == null)
{
return node!;
}
if (key.CompareTo(node.Key) < 0)
{
node.Left = this.RemoveNode(node.Left!, key);
}
else if (key.CompareTo(node.Key) > 0)
{
node.Right = this.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 = this.RotateLeft(node);
node.Left = this.RemoveNode(node.Left!, key);
}
else
{
node = this.RotateRight(node);
node.Right = this.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)
{
this.Clear(node.Left);
}
if (node.Right != null)
{
this.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 = this.Find(node.Left!, key);
if (found == null)
{
found = this.Find(node.Right!, key);
}
return found;
}
else if (node.Key.CompareTo(key) > 0)
{
var found = this.Find(node.Right!, key);
if (found == null)
{
found = this.Find(node.Left!, key);
}
return found;
}
else
{
return node;
}
}
}
private void ToArray(Node node, ref T[] array, ref int index)
{
if (node != null)
{
this.ToArray(node.Left!, ref array, ref index);
array[index] = node.Key;
index++;
this.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
}