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