using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Advanced.Algorithms.DataStructures
{
///
/// A treap tree implementation.
///
public class TreapTree : BSTBase, IEnumerable where T : IComparable
{
private Random rndGenerator = new Random();
internal TreapTreeNode Root { get; set; }
public int Count => Root == null ? 0 : Root.Count;
public TreapTree() { }
///
/// Initialize the BST with given sorted keys.
/// Time complexity: O(n).
///
/// The initial sorted collection.
public TreapTree(IEnumerable sortedCollection) : this()
{
ValidateSortedCollection(sortedCollection);
var nodes = sortedCollection.Select(x => new TreapTreeNode(null, x, rndGenerator.Next())).ToArray();
Root = (TreapTreeNode)ToBST(nodes);
assignCount(Root);
heapify(Root);
}
///
/// Time complexity: O(log(n))
///
public bool HasItem(T value)
{
if (Root == null)
{
return false;
}
return find(Root, value) != null;
}
///
/// Time complexity: O(log(n))
///
internal int GetHeight()
{
return getHeight(Root);
}
//O(log(n)) worst O(n) for unbalanced tree
private int getHeight(TreapTreeNode node)
{
if (node == null)
{
return -1;
}
return Math.Max(getHeight(node.Left), getHeight(node.Right)) + 1;
}
///
/// Time complexity: O(log(n))
///
public void Insert(T value)
{
if (Root == null)
{
Root = new TreapTreeNode(null, value, rndGenerator.Next());
return;
}
var newNode = insert(Root, value);
heapify(newNode);
}
//O(log(n)) always
private TreapTreeNode insert(TreapTreeNode currentNode, T newNodeValue)
{
while (true)
{
var compareResult = currentNode.Value.CompareTo(newNodeValue);
//current node is less than new item
if (compareResult < 0)
{
//no right child
if (currentNode.Right == null)
{
//insert
currentNode.Right = new TreapTreeNode(currentNode, newNodeValue, rndGenerator.Next());
return currentNode.Right;
}
currentNode = currentNode.Right;
}
//current node is greater than new node
else if (compareResult > 0)
{
if (currentNode.Left == null)
{
//insert
currentNode.Left = new TreapTreeNode(currentNode, newNodeValue, rndGenerator.Next());
return currentNode.Left;
}
currentNode = currentNode.Left;
}
else
{
throw new Exception("Item exists");
}
}
}
///
/// Time complexity: O(log(n))
///
public int IndexOf(T item)
{
return Root.Position(item);
}
///
/// Time complexity: O(log(n))
///
public T ElementAt(int index)
{
if (index < 0 || index >= Count)
{
throw new ArgumentNullException("index");
}
return Root.KthSmallest(index).Value;
}
///
/// Time complexity: O(log(n))
///
public void Delete(T value)
{
if (Root == null)
{
throw new Exception("Empty TreapTree");
}
delete(Root, value);
}
///
/// Time complexity: O(log(n))
///
public T RemoveAt(int index)
{
if (index < 0 || index >= Count)
{
throw new ArgumentException("index");
}
var nodeToDelete = Root.KthSmallest(index) as TreapTreeNode;
delete(nodeToDelete, nodeToDelete.Value);
return nodeToDelete.Value;
}
//O(log(n)) worst O(n) for unbalanced tree
private void delete(TreapTreeNode node, T value)
{
while (true)
{
if (node != null)
{
var compareResult = node.Value.CompareTo(value);
//node is less than the search value so move right to find the deletion node
if (compareResult < 0)
{
node = node.Right ?? throw new Exception("Item do not exist");
continue;
}
//node is less than the search value so move left to find the deletion node
if (compareResult > 0)
{
node = node.Left ?? throw new Exception("Item do not exist");
continue;
}
}
//node is a leaf node
if (node != null && node.IsLeaf)
{
deleteLeaf(node);
}
else
{
//case one - right tree is null (move sub tree up)
if (node?.Left != null && node.Right == null)
{
deleteLeftNode(node);
}
//case two - left tree is null (move sub tree up)
else if (node?.Right != null && node.Left == null)
{
deleteRightNode(node);
}
//case three - two child trees
//replace the node value with maximum element of left subtree (left max node)
//and then delete the left max node
else
{
if (node != null)
{
var maxLeftNode = findMax(node.Left);
node.Value = maxLeftNode.Value;
//delete left max node
node = node.Left;
value = maxLeftNode.Value;
}
continue;
}
}
break;
}
node.UpdateCounts(true);
}
private void deleteLeaf(TreapTreeNode node)
{
//if node is root
if (node.Parent == null)
{
Root = null;
}
//assign nodes parent.left/right to null
else if (node.IsLeftChild)
{
node.Parent.Left = null;
}
else
{
node.Parent.Right = null;
}
}
private void deleteRightNode(TreapTreeNode node)
{
//root
if (node.Parent == null)
{
Root.Right.Parent = null;
Root = Root.Right;
return;
}
//node is left child of parent
if (node.IsLeftChild)
{
node.Parent.Left = node.Right;
}
//node is right child of parent
else
{
node.Parent.Right = node.Right;
}
node.Right.Parent = node.Parent;
}
private void deleteLeftNode(TreapTreeNode node)
{
//root
if (node.Parent == null)
{
Root.Left.Parent = null;
Root = Root.Left;
return;
}
//node is left child of parent
if (node.IsLeftChild)
{
node.Parent.Left = node.Left;
}
//node is right child of parent
else
{
node.Parent.Right = node.Left;
}
node.Left.Parent = node.Parent;
}
///
/// Time complexity: O(log(n))
///
public T FindMax()
{
return findMax(Root).Value;
}
private TreapTreeNode findMax(TreapTreeNode node)
{
while (true)
{
if (node.Right == null) return node;
node = node.Right;
}
}
///
/// Time complexity: O(log(n))
///
public T FindMin()
{
return findMin(Root).Value;
}
private TreapTreeNode findMin(TreapTreeNode node)
{
while (true)
{
if (node.Left == null)
{
return node;
}
node = node.Left;
}
}
//find the node with the given identifier among descendants of parent and parent
//uses pre-order traversal
//O(log(n)) worst O(n) for unbalanced tree
private TreapTreeNode find(TreapTreeNode parent, T value)
{
while (true)
{
if (parent == null)
{
return null;
}
if (parent.Value.CompareTo(value) == 0)
{
return parent;
}
var left = find(parent.Left, value);
if (left != null)
{
return left;
}
parent = parent.Right;
}
}
//reorder the tree node so that heap property is valid
private void heapify(TreapTreeNode node)
{
while (node.Parent != null)
{
node.UpdateCounts();
if (node.Priority < node.Parent.Priority)
{
node = node.IsLeftChild ? rightRotate(node.Parent) : leftRotate(node.Parent);
}
else
{
break;
}
}
node.UpdateCounts(true);
}
///
/// Rotates current root right and returns the new root node
///
private TreapTreeNode rightRotate(TreapTreeNode currentRoot)
{
var prevRoot = currentRoot;
var leftRightChild = prevRoot.Left.Right;
var newRoot = currentRoot.Left;
//make left child as root
prevRoot.Left.Parent = prevRoot.Parent;
if (prevRoot.Parent != null)
{
if (prevRoot.Parent.Left == prevRoot)
{
prevRoot.Parent.Left = prevRoot.Left;
}
else
{
prevRoot.Parent.Right = prevRoot.Left;
}
}
//move prev root as right child of current root
newRoot.Right = prevRoot;
prevRoot.Parent = newRoot;
//move right child of left child of prev root to left child of right child of new root
newRoot.Right.Left = leftRightChild;
if (newRoot.Right.Left != null)
{
newRoot.Right.Left.Parent = newRoot.Right;
}
newRoot.Left.UpdateCounts();
newRoot.Right.UpdateCounts();
newRoot.UpdateCounts();
if (prevRoot == Root)
{
Root = newRoot;
}
return newRoot;
}
///
/// Rotates the current root left and returns new root
///
private TreapTreeNode leftRotate(TreapTreeNode currentRoot)
{
var prevRoot = currentRoot;
var rightLeftChild = prevRoot.Right.Left;
var newRoot = currentRoot.Right;
//make right child as root
prevRoot.Right.Parent = prevRoot.Parent;
if (prevRoot.Parent != null)
{
if (prevRoot.Parent.Left == prevRoot)
{
prevRoot.Parent.Left = prevRoot.Right;
}
else
{
prevRoot.Parent.Right = prevRoot.Right;
}
}
//move prev root as left child of current root
newRoot.Left = prevRoot;
prevRoot.Parent = newRoot;
//move left child of right child of prev root to right child of left child of new root
newRoot.Left.Right = rightLeftChild;
if (newRoot.Left.Right != null)
{
newRoot.Left.Right.Parent = newRoot.Left;
}
newRoot.Left.UpdateCounts();
newRoot.Right.UpdateCounts();
newRoot.UpdateCounts();
if (prevRoot == Root)
{
Root = newRoot;
}
return newRoot;
}
//find the node with the given identifier among descendants of parent and parent
//uses pre-order traversal
//O(log(n)) worst O(n) for unbalanced tree
private BSTNodeBase find(T value)
{
return Root.Find(value) as BSTNodeBase;
}
///
/// Get the next lower value to given value in this BST.
/// Time complexity: O(n).
///
public T NextLower(T value)
{
var node = find(value);
if (node == null)
{
return default(T);
}
var next = (node as BSTNodeBase).NextLower();
return next != null ? next.Value : default(T);
}
///
/// Get the next higher value to given value in this BST.
/// Time complexity: O(n).
///
public T NextHigher(T value)
{
var node = find(value);
if (node == null)
{
return default(T);
}
var next = (node as BSTNodeBase).NextHigher();
return next != null ? next.Value : default(T);
}
///
/// Descending enumerable.
///
public IEnumerable AsEnumerableDesc()
{
return GetEnumeratorDesc().AsEnumerable();
}
public IEnumerator GetEnumeratorDesc()
{
return new BSTEnumerator(Root, false);
}
//Implementation for the GetEnumerator method.
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator GetEnumerator()
{
return new BSTEnumerator(Root);
}
}
internal class TreapTreeNode : BSTNodeBase where T : IComparable
{
internal new TreapTreeNode Parent
{
get { return (TreapTreeNode)base.Parent; }
set { base.Parent = value; }
}
internal new TreapTreeNode Left
{
get { return (TreapTreeNode)base.Left; }
set { base.Left = value; }
}
internal new TreapTreeNode Right
{
get { return (TreapTreeNode)base.Right; }
set { base.Right = value; }
}
internal int Priority { get; set; }
internal TreapTreeNode(TreapTreeNode parent, T value, int priority)
{
Parent = parent;
Value = value;
Priority = priority;
}
}
}