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 JAVA (judge verdict: Accepted)

import java.util.Scanner;

public class Main {
	
	class Node {
		public Integer val;
		public Node left = null;
		public Node right = null;
		
		
		public Node() {
			this.val = null;
		}
		
		public Node(int val) {
			this.val = val;
		}
		
		public boolean hasLeft() {
			return this.left != null;
		}
		
		public boolean hasRight() {
			return this.right != null;
		}
		
		public boolean hasChildren() {
			return this.hasLeft() || this.hasRight();
		}
	}
	
	private Node root;
	private Node curr;
	
	public Main() {
		this.root = this.curr = new Node();
	}
	
	public Main(int val) {
		this.root = new Node(val);
		this.curr = root;
	}
	
	private void insert(int v) {
		find(v);
		
		Node n = new Node(v);
		
        if(curr.val <= v) {
            if(curr.hasRight()) {
            	n.right = curr.right;
            }
            curr.right = n;
        }
        else {
        	if(curr.hasLeft()) {
            	n.left = curr.left;
            }
            curr.left = n;
        }
	}
	
	public void preorder() {
		preorder(root);
		System.out.print("\n");
	}
	
	private void preorder(Node n) {
		if (n != null) {
			System.out.print(" " + n.val);
			preorder(n.left);
			preorder(n.right);
		}
		
	}
	
	public void inorder() {
		inorder(root);
		System.out.print("\n");
	}
	
	private void inorder(Node n) {
		if (n != null) {
			inorder(n.left);
			System.out.print(" " + n.val);
			inorder(n.right);
		}
	}
	
	public boolean find(int v) {
		return find(this.root, v);
	}
	
	private boolean find(Node n, int v) {
		if(n == null || n.val == null) {
			return false;
		}
		
        curr = n;
        
        if(v == n.val) {
            return true;
        } else {
            if(!n.hasChildren()) {
            	return false;
            } else if(v > n.val) {
                return find(n.right, v);
            } else {
                return find(n.left, v);
            }
        }
	}
	
	public void delete(int v) {
		this.delete(this.root, v);
	}
	
	private Node delete(Node n, int v) {
		if(n == null) {
			return null;
		}
		
        if(n.val > v) {
        	n.left = delete(n.left, v);
        } else if (n.val < v) {
        	n.right = delete(n.right, v);
        } else {
        	if(n.left == null) {
            	return n.right;
            } else if(n.right == null) {
            	return n.left;
            } else {
            	Node current = n.right;
            	Node parent = n;
				while (current.hasLeft()) {
					parent = current;
					current = current.left;
				}

				if (!(parent == n)) {
					
					parent.left = null;
				} else {
					parent.right = null;
				}
				n.val = current.val;
            }
        }
        
		return n;
	}

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		String unused = in.nextLine();
		Main t = new Main(Integer.parseInt(in.nextLine().split(" ")[1]));
		while (in.hasNextLine()) {
			String command = in.nextLine();
			String[] components = command.split(" ");
			switch(components[0]) {
				case "find":
					String ans = t.find(Integer.parseInt(components[1])) ? "yes" : "no";
					System.out.println(ans);
					break;
				case "delete":
					t.delete(Integer.parseInt(components[1]));
					break;
				case "insert":
					t.insert(Integer.parseInt(components[1]));
					break;
				default:
					t.inorder();
					t.preorder();
			}
		}
	}
}