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