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.Diagnostics;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;

/*
 */

public class ALDS1_8_C
{
    private struct Node
    {
        public int NodeId;
        public int Value;
        public int ParentId;
        public int LeftId;
        public int RightId;

        public Node(int nodeId)
        {
            NodeId = nodeId;
            Value = 0;
            ParentId = -2;
            LeftId = -1;
            RightId = -1;
        }
    }

    public static void Main(string[] args)
    {
        //var exStdIn = new System.IO.StreamReader( "input.txt" );
        //System.Console.SetIn( exStdIn );

        int n = int.Parse(Console.ReadLine());
        Node[] nodes = new Node[n];
        for (int i = 0; i < n; i++)
        {
            nodes[i] = new Node(i);
        }

        int index = 0;
        for (int i = 0; i < n; i++)
        {
            string[] str = Console.ReadLine().Split(' ');
            if (str[0] == "insert")
            {
                Insert(nodes, index, int.Parse(str[1]));
                index++;
            }
            else if (str[0] == "find")
            {
                int rootId = GetRootId(nodes);
                Find(nodes, rootId, int.Parse(str[1]));
            }
            else if (str[0] == "delete")
            {
                int rootId = GetRootId(nodes);
                Delete(nodes, rootId, int.Parse(str[1]));
            }
            else if (str[0] == "print")
            {
                int rootId = GetRootId(nodes);
                StringBuilder sb = new StringBuilder();
                Inorder(nodes, sb, rootId);
                sb.AppendLine();
                Preorder(nodes, sb, rootId);
                Console.WriteLine(sb.ToString());
            }
        }
    }

    private static int GetRootId(Node[] nodes)
    {
        int rootId = -1;
        for (int j = 0; j < nodes.Length; j++)
        {
            if (nodes[j].ParentId == -1)
            {
                rootId = j;
                break;
            }
        }
        return rootId;
    }

    private static void Insert(Node[] nodes, int index, int value)
    {
        nodes[index].Value = value;
        int parent = GetRootId(nodes);
        if (parent == -1)
        {
            nodes[index].ParentId = -1;
            return;
        }
        while (true)
        {
            Node parentNode = nodes[parent];
            if (value < parentNode.Value)
            {
                if (parentNode.LeftId != -1)
                {
                    parent = parentNode.LeftId;
                }
                else
                {
                    nodes[parent].LeftId = index;
                    nodes[index].ParentId = parent;
                    return;
                }
            }
            else
            {
                if (parentNode.RightId != -1)
                {
                    parent = parentNode.RightId;
                }
                else
                {
                    nodes[parent].RightId = index;
                    nodes[index].ParentId = parent;
                    return;
                }
            }
        }
    }

    private static void Find(Node[] nodes, int index, int value)
    {
        if (index == -1)
        {
            Console.WriteLine("no");
            return;
        }
        if (nodes[index].Value == value)
        {
            Console.WriteLine("yes");
            return;
        }

        if (value < nodes[index].Value)
        {
            Find(nodes, nodes[index].LeftId, value);
        }
        else
        {
            Find(nodes, nodes[index].RightId, value);
        }
    }

    private static void Delete(Node[] nodes, int index, int value)
    {
        if (index == -1)
        {
            return;
        }
        if (nodes[index].Value == value)
        {
            if (nodes[index].LeftId == -1 && nodes[index].RightId == -1)
            {
                int parentId = nodes[index].ParentId;
                if (parentId != -1)
                {
                    if (nodes[index].Value < nodes[parentId].Value)
                    {
                        nodes[parentId].LeftId = -1;
                    }
                    else
                    {
                        nodes[parentId].RightId = -1;
                    }
                }
                nodes[index].ParentId = -2;
            }
            else if (nodes[index].LeftId == -1)
            {
                int parentId = nodes[index].ParentId;
                int rightId = nodes[index].RightId;
                if (parentId != -1)
                {
                    if (nodes[index].Value < nodes[parentId].Value)
                    {
                        nodes[parentId].LeftId = rightId;
                        nodes[rightId].ParentId = parentId;
                    }
                    else
                    {
                        nodes[parentId].RightId = rightId;
                        nodes[rightId].ParentId = parentId;
                    }
                }
                nodes[index].RightId = -1;
                nodes[index].ParentId = -2;
            }
            else if (nodes[index].RightId == -1)
            {
                int parentId = nodes[index].ParentId;
                int leftId = nodes[index].LeftId;
                if (parentId != -1)
                {
                    if (nodes[index].Value < nodes[parentId].Value)
                    {
                        nodes[parentId].LeftId = leftId;
                        nodes[leftId].ParentId = parentId;
                    }
                    else
                    {
                        nodes[parentId].RightId = leftId;
                        nodes[leftId].ParentId = parentId;
                    }
                }
                nodes[index].LeftId = -1;
                nodes[index].ParentId = -2;
            }
            else
            {
                int targetId = nodes[index].RightId;
                while (true)
                {
                    if (nodes[targetId].LeftId != -1)
                    {
                        targetId = nodes[targetId].LeftId;
                    }
                    else
                    {
                        break;
                    }
                }
                nodes[index].Value = nodes[targetId].Value;
                Delete(nodes, targetId, nodes[targetId].Value);
            }
            return;
        }

        if (value < nodes[index].Value)
        {
            Delete(nodes, nodes[index].LeftId, value);
        }
        else
        {
            Delete(nodes, nodes[index].RightId, value);
        }
    }

    private static void Preorder(Node[] nodes, StringBuilder sb, int index)
    {
        sb.AppendFormat(" {0}", nodes[index].Value.ToString());
        if (nodes[index].LeftId != -1)
        {
            Preorder(nodes, sb, nodes[index].LeftId);
        }
        if (nodes[index].RightId != -1)
        {
            Preorder(nodes, sb, nodes[index].RightId);
        }
    }

    private static void Inorder(Node[] nodes, StringBuilder sb, int index)
    {
        if (nodes[index].LeftId != -1)
        {
            Inorder(nodes, sb, nodes[index].LeftId);
        }
        sb.AppendFormat(" {0}", nodes[index].Value.ToString());
        if (nodes[index].RightId != -1)
        {
            Inorder(nodes, sb, nodes[index].RightId);
        }
    }

    private static void Postorder(Node[] nodes, StringBuilder sb, int index)
    {
        if (nodes[index].LeftId != -1)
        {
            Postorder(nodes, sb, nodes[index].LeftId);
        }
        if (nodes[index].RightId != -1)
        {
            Postorder(nodes, sb, nodes[index].RightId);
        }
        sb.AppendFormat(" {0}", nodes[index].Value.ToString());
    }
}