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

import scala.collection.mutable.Stack
import scala.io.StdIn.{readInt, readLine}

object Main extends App {

  val bst = new Bst()
  val n = readInt
  for (_ <- 0 until n) {
    val arr = readLine.split(" ")
    val cmd = arr(0)
    var value = 0
    if (arr.length > 1) {
      value = arr(1).toInt
    }
    cmd match {
      case "insert" => bst.insert(value)
      case "delete" => bst.delete(value)
      case "find" => println(if (bst.find(value)) "yes" else "no")
      case "print" => bst.printTree
    }
  }

  class Node(var value: Int) {
    var parent: Node = null
    var left: Node = null
    var right: Node = null
    var visited = false
    def hasNoChild = {left == null && right == null}
    def hasTwoChild = {left != null && right != null}
    def hasOneChild = {!hasNoChild && !hasTwoChild}
  }

  class Bst {

    var root: Node = null

    def insert(value: Int): Unit = {
      val newNode = new Node(value)
      if (root == null) {
        root = newNode
        return
      }
      var cur = root
      var prev = cur
      while (cur != null) {
        if (cur.value > value) {
          cur = cur.left
          if (cur == null) {
            prev.left = newNode
            newNode.parent = prev
          }
        } else {
          cur = cur.right
          if (cur == null) {
            prev.right = newNode
            newNode.parent = prev
          }
        }
        prev = cur
      }
    }

    def find(value: Int): Boolean = {
      val node = findNode(value)
      node != null
    }

    def findNode(value: Int): Node = {
      if (root == null) return null
      var cur = root
      while (cur != null) {
        if (cur.value == value) {
          return cur
        }
        if (cur.value > value) {
          cur = cur.left
        } else {
          cur = cur.right
        }
      }
      null
    }

    def delete(value: Int): Unit = {
      val node = findNode(value)
      if (node == null) return

      val parent = node.parent
      var child: Node = null
      if (node.hasNoChild) {
        if (parent == null) {
          root = null
        } else {
          removeNode(parent, node, child)
        }
      } else if (node.hasOneChild) {
        if (node.left != null) {
          child = node.left
        } else {
          child = node.right
        }
        if (parent == null) {
          root = child
        } else {
          removeNode(parent, node, child)
        }
      } else {
        val successor = findSuccessor(node)
        node.value = successor.value
        if (successor.hasOneChild) {
          child = successor.right
        }
        removeNode(successor.parent, successor, child)
      }
    }

    def removeNode(parent: Node, node: Node, child: Node): Unit = {
      if (parent.left == node) {
        parent.left = child
      } else {
        parent.right = child
      }
      if (child != null) {
        child.parent = parent
      }
    }

    def findSuccessor(node: Node): Node = {
      var cur = node.right
      while (cur.left != null) {
        cur = cur.left
      }
      cur
    }

    def printTree: Unit = {
      inOrder
      preOrder
    }

    def inOrder: Unit = {
      val stack = new Stack[Node]
      stack.push(root)
      while (!stack.isEmpty) {
        var cur = stack.top
        while (cur.left != null && !cur.left.visited) {
          stack.push(cur.left)
          cur = cur.left
        }
        cur = stack.pop
        print(s" ${cur.value}")
        cur.visited = true
        if (cur.right != null && !cur.right.visited) {
          stack.push(cur.right)
        }
      }
      println
    }

    def preOrder: Unit = {
      val stack = new Stack[Node]
      stack.push(root)
      while (!stack.isEmpty) {
        val cur = stack.pop
        print(s" ${cur.value}")
        cur.visited = false
        if (cur.right != null) stack.push(cur.right)
        if (cur.left != null) stack.push(cur.left)
      }
      println
    }
  }
}