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;

namespace _20170410_AOJ_ALDS1_8A
{
    class ALDS1_8A
    {
        static void Main(string[] args)
        {
            for (;;)
            {
                string line = Console.ReadLine();
                if (string.IsNullOrEmpty(line))
                {
                    break;
                }

                BinaryTree bt = new BinaryTree();
                int n = int.Parse(line);
                for(int i=0;i<n;i++)
                {
                    string[] command = Console.ReadLine().Split(' ');
                    int key;
                    switch (command[0])
                    {
                        case "delete":
                            key = int.Parse(command[1]);
                            bt.Delete(key);
                            break;
                        case "find":
                            key = int.Parse(command[1]);
                            TreeNode tn = bt.Find(key);
                            if(tn != null)
                            {
                                Console.WriteLine("yes");
                            }
                            else
                            {
                                Console.WriteLine("no");
                            }
                            break;
                        case "insert":
                            key = int.Parse(command[1]);
                            bt.Insert(key);
                            break;
                        case "print":
                            Console.Write(" ");
                            Console.WriteLine(string.Join(" ", bt.InOrder().Select(x => x.Key.ToString()).ToArray()));
                            Console.Write(" ");
                            Console.WriteLine(string.Join(" ", bt.PreOrder().Select(x => x.Key.ToString()).ToArray()));
                            break;
                    }
                }
            }
        }
    }

    class BinaryTree
    {
        List<TreeNode> list;
        public TreeNode Root { get { return GetRoot(); } }
        public BinaryTree()
        {
            list = new List<TreeNode>();
        }

        private TreeNode GetRoot()
        {
            if (list.Count == 0) return null;

            TreeNode temp = list[0];
            while (temp.Parent != null)
            {
                temp = temp.Parent;
            }

            return temp;
        }

        public void Delete(int key)
        {
            TreeNode tn = Find(key);
            Delete(tn);
        }

        void Delete(TreeNode tn)
        {
            if (tn == null) return;

            if (tn.Left == null && tn.Right == null)
            {
                if (tn.Parent.Left == tn)
                {
                    tn.Parent.Left = null;
                }
                else if (tn.Parent.Right == tn)
                {
                    tn.Parent.Right = null;
                }
                list.Remove(tn);
            }
            else if ((tn.Left == null) ^ (tn.Right == null))
            {
                TreeNode child = (tn.Left != null) ? tn.Left : tn.Right;
                if (tn.Parent.Left == tn)
                {
                    tn.Parent.Left = child;
                }
                else if (tn.Parent.Right == tn)
                {
                    tn.Parent.Right = child;
                }
                child.Parent = tn.Parent;
                list.Remove(tn);
            }
            else
            {
                List<TreeNode> rightTree = new List<TreeNode>();
                InOrder(rightTree, tn.Right);
                TreeNode nextNode = rightTree[0];
                tn.Key = nextNode.Key;
                Delete(nextNode);
            }
        }

        public TreeNode Find(int key)
        {
            return Find(Root, key);
        }

        static TreeNode Find(TreeNode tn, int key)
        {
            TreeNode rv = null;
            if (tn != null)
            {
                if (key < tn.Key)
                {
                    rv = Find(tn.Left, key);
                }
                else if (key > tn.Key)
                {
                    rv = Find(tn.Right, key);
                }
                else
                {
                    rv = tn;
                }
            }

            return rv;
        }

        public void Insert(int z)
        {
            TreeNode tn = new TreeNode();
            tn.Key = z;
            Insert(tn);
        }

        public void Insert(TreeNode z)
        {
            TreeNode y = null;
            TreeNode x = Root;
            
            while(x!=null)
            {
                y = x;
                x = (z.Key < x.Key) ? x.Left : x.Right;
            }

            z.Parent = y;

            list.Add(z);
            if(y==null)
            {
            }
            else if(z.Key < y.Key)
            {
                y.Left = z;
                z.Parent = y;
            }
            else
            {
                y.Right = z;
                z.Parent = y;
            }
        }

        public TreeNode[] PreOrder()
        {
            List<TreeNode> list = new List<TreeNode>();
            PreOrder(list, Root);
            return list.ToArray();
        }

        static void PreOrder(List<TreeNode> list, TreeNode tn)
        {
            list.Add(tn);

            if (tn.Left != null)
            {
                PreOrder(list, tn.Left);
            }

            if (tn.Right != null)
            {
                PreOrder(list, tn.Right);
            }
        }

        public TreeNode[] InOrder()
        {
            List<TreeNode> list = new List<TreeNode>();
            InOrder(list, Root);
            return list.ToArray();
        }

        static void InOrder(List<TreeNode> list, TreeNode tn)
        {
            if (tn.Left != null)
            {
                InOrder(list, tn.Left);
            }

            list.Add(tn);

            if (tn.Right != null)
            {
                InOrder(list, tn.Right);
            }
        }

        static void PostOrder(List<TreeNode> list, TreeNode tn)
        {
            if (tn.Left != null)
            {
                PostOrder(list, tn.Left);
            }

            if (tn.Right != null)
            {
                PostOrder(list, tn.Right);
            }

            list.Add(tn);
        }
    }

    class TreeNode
    {
        public int Key { get; set; }
        public TreeNode Parent { get; set; }
        public TreeNode Left { get; set; }
        public TreeNode Right { get; set; }
        public TreeNode()
        {
        }
    }
}