Problem:
Binary Search Tree III

Write a program which performs the following operations to a binary search tree $T$ by adding delete operation to B: Binary Search Tree II.

insert $k$: Insert a node containing $k$ as key into $T$.

find $k$: Report whether $T$ has a node containing $k$.

delete $k$: Delete a node containing $k$.

print: Print the keys of the binary search tree by inorder tree walk and preorder tree walk respectively.

The operation delete $k$ for deleting a given node $z$ containing key $k$ from $T$ can be implemented by an algorithm which considers the following cases:

If $z$ has no children, we modify its parent $z.p$ to replace $z$ with NIL as its child (delete $z$).

If $z$ has only a single child, we "splice out" $z$ by making a new link between its child and its parent.

If $z$ has two children, we splice out $z$'s successor $y$ and replace $z$'s key with $y$'s key.

Input

In the first line, the number of operations $m$ is given. In the following $m$ lines, operations represented by insert $k$, find $k$, delete $k$ or print are given.

Output

For each find $k$ operation, print "yes" if $T$ has a node containing $k$, "no" if not.

In addition, for each print operation, print a list of keys obtained by inorder tree walk and preorder tree walk in a line respectively. Put a space character before each key

Constraints

The number of operations $\leq 500,000$

The number of print operations $\leq 10$.

$-2,000,000,000 \leq key \leq 2,000,000,000$

The height of the binary tree does not exceed 100 if you employ the above pseudo code.

The keys in the binary search tree are all different.

Sample Input 1

18
insert 8
insert 2
insert 3
insert 7
insert 22
insert 1
find 1
find 2
find 3
find 4
find 5
find 6
find 7
find 8
print
delete 3
delete 7
print

Sample Output 1

yes
yes
yes
no
no
no
yes
yes
1 2 3 7 8 22
8 2 1 3 7 22
1 2 8 22
8 2 1 22

Reference

Introduction to Algorithms, Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. The MIT Press.

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CompProgLib.Tree.BinaryTree;

namespace ALDS1_8_C
{
    public class Program

    {
        public static void Main(string[] args)
        {
            int n = ReadInt();
            BinaryTree<int> bt = new BinaryTree<int>();
            for (int i = 0 ; i < n ; i++)
            {
                string[] line = ReadStAr();
                switch (line[0])
                {
                    case "insert":
                        bt.Add(int.Parse(line[1]));
                        break;
                    case "delete":
                        bt.Remove(int.Parse(line[1]));
                        break;
                    case "find":
                        Console.WriteLine(bt.Contains(int.Parse(line[1])) ? "yes" : "no");
                        break;
                    case "print":
                        Console.WriteLine(" " + string.Join(" ", bt.InorderTraversal(bt.Root).Select(x => x.ToString()).ToArray()));
                        Console.WriteLine(" " + string.Join(" ", bt.PreorderTraversal(bt.Root).Select(x => x.ToString()).ToArray()));
                        break;
                }
            }

        }

        static string ReadSt() { return Console.ReadLine(); }
        static int ReadInt() { return int.Parse(Console.ReadLine()); }
        static long ReadLong() { return long.Parse(Console.ReadLine()); }
        static double ReadDouble() { return double.Parse(Console.ReadLine()); }
        static string[] ReadStAr(char sep = ' ') { return Console.ReadLine().Split(sep); }
        static int[] ReadIntAr(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Split(sep), e => int.Parse(e)); }
        static long[] ReadLongAr(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Split(sep), e => long.Parse(e)); }
        static double[] ReadDoubleAr(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Split(sep), e => double.Parse(e)); }

    }

}

namespace CompProgLib.Tree.BinaryTree
{
    public class BinaryTreeNode<T> : Node<T>
    {
        public BinaryTreeNode() : base() { }
        public BinaryTreeNode(T data) : base(data, null) { }
        public BinaryTreeNode(T data, BinaryTreeNode<T> left, BinaryTreeNode<T> right)
        {
            Value = data;
            Neighbors = new NodeList<T> { left, right };
        }

        public new BinaryTreeNode<T> Parent { set; get; }
        public BinaryTreeNode<T> Left
        {
            get
            {
                if (base.Neighbors == null) return null;
                else return (BinaryTreeNode<T>)Neighbors[0];
            }
            set
            {
                if (base.Neighbors == null) base.Neighbors = new NodeList<T>(2);
                base.Neighbors[0] = value;
                if (value != null) value.Parent = this;
            }
        }

        public BinaryTreeNode<T> Right
        {
            get
            {
                if (base.Neighbors == null) return null;
                else return (BinaryTreeNode<T>)Neighbors[1];
            }
            set
            {
                if (base.Neighbors == null) Neighbors = new NodeList<T>(2);
                base.Neighbors[1] = value;
                if (value != null) value.Parent = this;
            }
        }
    }

    public class BinaryTreeNodeList<T> : NodeList<T>
    {
        public BinaryTreeNodeList() : base() { }
        public BinaryTreeNodeList(int initialSize)
        { for (int i = 0 ; i < initialSize ; i++) Add(default(BinaryTreeNode<T>)); }

        public new BinaryTreeNode<T> FindByValue(T value)
        {
            foreach (BinaryTreeNode<T> node in this) if (node.Value.Equals(value)) return node;
            return null;
        }
    }

    public class BinaryTree<T>
    {

        public BinaryTreeNode<T> Root { get; set; }
        public int Count { get; private set; }

        public BinaryTree() { Root = null; }
        public virtual void Clear() { Root = null; }

        public List<T> PreorderTraversal(BinaryTreeNode<T> current)
        {
            List<T> res = new List<T>();
            PreorderTraversal(current, res);
            return res;
        }
        private void PreorderTraversal(BinaryTreeNode<T> current, List<T> res)
        {
            if (current != null)
            {
                res.Add(current.Value);
                PreorderTraversal(current.Left, res);
                PreorderTraversal(current.Right, res);
            }
        }

        public List<T> InorderTraversal(BinaryTreeNode<T> current)
        {
            List<T> res = new List<T>();
            InorderTraversal(current, res);
            return res;
        }
        private void InorderTraversal(BinaryTreeNode<T> current, List<T> res)
        {
            if (current != null)
            {
                InorderTraversal(current.Left, res);
                res.Add(current.Value);
                InorderTraversal(current.Right, res);
            }
        }

        public List<T> PostorderTraversal(BinaryTreeNode<T> current)
        {
            List<T> res = new List<T>();
            PostorderTraversal(current, res);
            return res;
        }
        private void PostorderTraversal(BinaryTreeNode<T> current, List<T> res)
        {
            if (current != null)
            {
                PostorderTraversal(current.Left, res);
                PostorderTraversal(current.Right, res);
                res.Add(current.Value);
            }
        }

        public virtual void Add(T data)
        {

            BinaryTreeNode<T> n = new BinaryTreeNode<T>(data);
            int result;
            System.Collections.Comparer comparer = new System.Collections.Comparer(System.Globalization.CultureInfo.CurrentCulture);

            BinaryTreeNode<T> current = Root, parent = null;
            while (current != null)
            {
                result = comparer.Compare(current.Value, data);
                if (result == 0)
                    return;
                else if (result > 0)
                {
                    parent = current;
                    current = current.Left;
                }
                else if (result < 0)
                {
                    parent = current;
                    current = current.Right;
                }
            }

            Count++;
            if (parent == null)
                Root = n;
            else
            {
                result = comparer.Compare(parent.Value, data);
                if (result > 0)
                    parent.Left = n;
                else
                    parent.Right = n;
            }
        }

        public bool Remove(T data)
        {

            System.Collections.Comparer comparer = new System.Collections.Comparer(System.Globalization.CultureInfo.CurrentCulture);
            if (Root == null) return false;

            BinaryTreeNode<T> current = Root;
            int result = comparer.Compare(current.Value, data);
            while (result != 0)
            {
                if (result > 0)
                {
                    current = current.Left;
                }
                else if (result < 0)
                {
                    current = current.Right;
                }
                if (current == null)
                    return false;
                else
                    result = comparer.Compare(current.Value, data);
            }

            Count--;

            DeleteNode(current);
            return true;
        }

        private void DeleteNode(BinaryTreeNode<T> current)
        {
            int result;
            System.Collections.Comparer comparer = new System.Collections.Comparer(System.Globalization.CultureInfo.CurrentCulture);

            if (current.Left == null && current.Right == null)
            {
                if (current.Parent == null) Root = null;
                else
                {
                    result = comparer.Compare(current.Parent.Value, current.Value);
                    if (result > 0)
                        current.Parent.Left = null;
                    else if (result < 0)
                        current.Parent.Right = null;
                }
            }
            else if (current.Left == null && current.Right != null)
            {
                if (current.Parent == null)
                {
                    Root = current.Right;
                    Root.Parent = null;
                }
                else
                {
                    result = comparer.Compare(current.Parent.Value, current.Value);
                    if (result > 0)
                        current.Parent.Left = current.Right;
                    else if (result < 0)
                        current.Parent.Right = current.Right;
                }
            }
            else if (current.Left != null && current.Right == null)
            {
                if (current.Parent == null)
                {
                    Root = current.Left;
                    Root.Parent = null;
                }
                else
                {
                    result = comparer.Compare(current.Parent.Value, current.Value);
                    if (result > 0)
                        current.Parent.Left = current.Left;
                    else if (result < 0)
                        current.Parent.Right = current.Left;
                }
            }
            else
            {
                BinaryTreeNode<T> nextnode = current.Right, nextnodeParent = current;
                while(nextnode != null)
                {
                    nextnodeParent = nextnode;
                    nextnode = nextnode.Left;
                } 
                
                T tmp = nextnodeParent.Value;
                DeleteNode(nextnodeParent);
                current.Value = tmp;
               
            }
        }


        public bool Contains(T data)
        {
            BinaryTreeNode<T> current = Root;
            int result;

            System.Collections.Comparer comparer = new System.Collections.Comparer(System.Globalization.CultureInfo.CurrentCulture);
            while (current != null)
            {
                result = comparer.Compare(current.Value, data);
                if (result == 0)
                    return true;
                else if (result > 0)
                    current = current.Left;
                else if (result < 0)
                    current = current.Right;
            }

            return false;
        }

    }

}

namespace CompProgLib.Tree
{
    public class Node<T>
    {
        public T Value { get; set; }
        public Node<T> Parent { get; set; }
        protected NodeList<T> Neighbors { get; set; }

        public Node() { }
        public Node(T data) : this(data, null) { }
        public Node(T data, NodeList<T> neighbors)
        {
            Value = data;
            Neighbors = neighbors;
        }
    }

    public class NodeList<T> : List<Node<T>>
    {
        public NodeList() : base() { }
        public NodeList(int initialSize)
        { for (int i = 0 ; i < initialSize ; i++) Add(default(Node<T>)); }

        public Node<T> FindByValue(T value)
        {
            foreach (Node<T> node in this) if (node.Value.Equals(value)) return node;
            return null;
        }
    }
}