using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace Advanced.Algorithms.DataStructures { /// /// A binary search tree implementation. /// public class BST : IEnumerable where T : IComparable { internal BSTNode Root { get; set; } public int Count => Root == null ? 0 : Root.Count; public BST() { } /// /// Initialize the BST with given sorted keys. /// Time complexity: O(n). /// public BST(IEnumerable sortedCollection) : this() { BSTHelpers.ValidateSortedCollection(sortedCollection); var nodes = sortedCollection.Select(x => new BSTNode(null, x)).ToArray(); Root = (BSTNode)BSTHelpers.ToBST(nodes); BSTHelpers.AssignCount(Root); } /// /// Time complexity: O(n) /// public bool HasItem(T value) { if (Root == null) { return false; } return find(Root, value) != null; } /// /// Time complexity: O(n) /// internal int GetHeight() { return getHeight(Root); } //worst O(n) for unbalanced tree private int getHeight(BSTNode node) { if (node == null) { return -1; } return Math.Max(getHeight(node.Left), getHeight(node.Right)) + 1; } internal BSTNode InsertAndReturnNewNode(T value) { if (Root == null) { Root = new BSTNode(null, value); return Root; } var newNode = insert(Root, value); return newNode; } /// /// Time complexity: O(n) /// public void Insert(T value) { if (Root == null) { Root = new BSTNode(null, value); return; } var newNode = insert(Root, value); newNode.UpdateCounts(true); } //worst O(n) for unbalanced tree private BSTNode insert(BSTNode 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) { currentNode = currentNode.Right; continue; } //insert currentNode.Right = new BSTNode(currentNode, newNodeValue); return currentNode.Right; } //current node is greater than new node if (compareResult > 0) { if (currentNode.Left == null) { //insert currentNode.Left = new BSTNode(currentNode, newNodeValue); return currentNode.Left; } currentNode = currentNode.Left; } else { throw new Exception("Item exists"); } } } // /// Time complexity: O(n) /// public int IndexOf(T item) { return Root.Position(item); } /// /// Time complexity: O(n) /// public T ElementAt(int index) { if (index < 0 || index >= Count) { throw new ArgumentNullException("index"); } return Root.KthSmallest(index).Value; } /// /// Time complexity: O(n) /// public void Delete(T value) { if (Root == null) { throw new Exception("Empty BST"); } var deleted = delete(Root, value); deleted.UpdateCounts(true); } /// /// Time complexity: O(n) /// public T RemoveAt(int index) { if (index < 0 || index >= Count) { throw new ArgumentException("index"); } var nodeToDelete = Root.KthSmallest(index) as BSTNode; var deleted = delete(nodeToDelete, nodeToDelete.Value); deleted.UpdateCounts(true); return nodeToDelete.Value; } //worst O(n) for unbalanced tree private BSTNode delete(BSTNode 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; } } if (node == null) { return null; } //node is a leaf node if (node.IsLeaf) { deleteLeaf(node); return node; } //case one - right tree is null (move sub tree up) if (node.Left != null && node.Right == null) { deleteLeftNode(node); return node; } //case two - left tree is null (move sub tree up) if (node.Right != null && node.Left == null) { deleteRightNode(node); return 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 var maxLeftNode = FindMax(node.Left); node.Value = maxLeftNode.Value; //delete left max node node = node.Left; value = maxLeftNode.Value; } } private void deleteLeaf(BSTNode 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(BSTNode node) { //root if (node.Parent == null) { Root.Right.Parent = null; Root = Root.Right; } else { //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(BSTNode node) { //root if (node.Parent == null) { Root.Left.Parent = null; Root = Root.Left; } else { //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(n) /// public T FindMax() { return FindMax(Root).Value; } private BSTNode FindMax(BSTNode node) { while (true) { if (node.Right == null) return node; node = node.Right; } } /// /// Time complexity: O(n) /// public T FindMin() { return findMin(Root).Value; } private BSTNode findMin(BSTNode 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 //worst O(n) for unbalanced tree internal BSTNode FindNode(T value) { return find(Root, value); } //find the node with the given identifier among descendants of parent and parent //uses pre-order traversal //worst O(n) for unbalanced tree private BSTNode find(BSTNode 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; } } //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).Item1 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 BSTNode : BSTNodeBase where T : IComparable { internal new BSTNode Parent { get { return (BSTNode)base.Parent; } set { base.Parent = value; } } internal new BSTNode Left { get { return (BSTNode)base.Left; } set { base.Left = value; } } internal new BSTNode Right { get { return (BSTNode)base.Right; } set { base.Right = value; } } internal BSTNode(BSTNode parent, T value) { Parent = parent; Value = value; } } }