/// <summary>
        /// Calculates the tree height from a specific node, recursively.
        /// </summary>
        /// <param name="node">Node</param>
        /// <returns>Height of node's longest subtree</returns>
        protected int _getTreeHeight(BSTRankedNode <T> node)
        {
            if (node == null || node.HasChildren == false)
            {
                return(0);
            }

            if (node.ChildrenCount == 2) // it has both a right child and a left child
            {
                if (node.LeftChild.SubtreeSize > node.RightChild.SubtreeSize)
                {
                    return(1 + _getTreeHeight(node.LeftChild));
                }
                else
                {
                    return(1 + _getTreeHeight(node.RightChild));
                }
            }
            else if (node.HasLeftChild)
            {
                return(1 + _getTreeHeight(node.LeftChild));
            }
            else if (node.HasRightChild)
            {
                return(1 + _getTreeHeight(node.RightChild));
            }

            // return-functions-fix
            return(0);
        }
 public BSTRankedNode(T value, int subtreeSize, BSTRankedNode <T> parent, BSTRankedNode <T> left, BSTRankedNode <T> right)
 {
     base.Value  = value;
     SubtreeSize = subtreeSize;
     Parent      = parent;
     LeftChild   = left;
     RightChild  = right;
 }
        /// <summary>
        /// Updates the Subtree Size of a tree node.
        /// Used in recusively calculating the Subtrees Sizes of nodes.
        /// </summary>
        /// <param name="node">BST Node.</param>
        protected void _updateSubtreeSize(BSTRankedNode <T> node)
        {
            if (node == null)
            {
                return;
            }

            node.SubtreeSize = _subtreeSize(node.LeftChild) + _subtreeSize(node.RightChild) + 1;

            _updateSubtreeSize(node.Parent);
        }
 /// <summary>
 /// Returns the Subtrees size for a tree node if node exists; otherwise 0 (left and right nodes of leafs).
 /// This is used in the recursive function UpdateSubtreeSize.
 /// </summary>
 /// <returns>The size.</returns>
 /// <param name="node">BST Node.</param>
 protected int _subtreeSize(BSTRankedNode <T> node)
 {
     if (node == null)
     {
         return(0);
     }
     else
     {
         return(node.SubtreeSize);
     }
 }
        /// <summary>
        /// Inserts an element to the tree
        /// </summary>
        /// <param name="item">Item to insert</param>
        public override void Insert(T item)
        {
            var newNode = new BSTRankedNode <T>(item);

            // Invoke the super BST insert node method.
            // This insert node recursively starting from the root and checks for success status (related to allowDuplicates flag).
            // The functions increments count on its own.
            var success = base._insertNode(newNode);

            if (success == false && _allowDuplicates == false)
            {
                throw new InvalidOperationException("Tree does not allow inserting duplicate elements.");
            }

            // Update the subtree-size for the newNode's parent.
            _updateSubtreeSize(newNode.Parent);
        }
        /// <summary>
        /// Remove the specified node.
        /// </summary>
        /// <param name="node">Node.</param>
        /// <returns>>True if removed successfully; false if node wasn't found.</returns>
        protected bool _remove(BSTRankedNode <T> node)
        {
            if (node == null)
            {
                return(false);
            }

            var parent = node.Parent;

            if (node.ChildrenCount == 2) // if both children are present
            {
                var successor = node.RightChild;
                node.Value = successor.Value;
                return(true && _remove(successor));
            }
            else if (node.HasLeftChild) // if the node has only a LEFT child
            {
                base._replaceNodeInParent(node, node.LeftChild);
                _updateSubtreeSize(parent);
                _count--;
            }
            else if (node.HasRightChild) // if the node has only a RIGHT child
            {
                base._replaceNodeInParent(node, node.RightChild);
                _updateSubtreeSize(parent);
                _count--;
            }
            else //this node has no children
            {
                base._replaceNodeInParent(node, null);
                _updateSubtreeSize(parent);
                _count--;
            }

            return(true);
        }