Problem:
Binary Search Tree II

Write a program which performs the following operations to a binary search tree $T$ by adding the find operation to A: Binary Search Tree I.

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

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

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

Input

In the first line, the number of operations $m$ is given. In the following $m$ lines, operations represented by insert $k$, find $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

10
insert 30
insert 88
insert 12
insert 1
insert 20
find 12
insert 17
insert 25
find 16
print

Sample Output 1

yes
no
1 12 17 20 25 30 88
30 12 1 20 17 25 88

Reference

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

Solution in Kotlin (judge verdict: Accepted)

import java.lang.Exception

var nodeList = arrayListOf<Treee>()

fun main(args: Array<String>) {

    val count = readLine()!!.toLong()
    for (i in 1..count) {
        val order = readLine()!!
        when {
            order.contains("insert") -> {
                insert(order.split(" ")[1].toInt())
            }
            order.contains("find") -> {
                println(find(order.split(" ")[1].toInt()))
            }
            order.contains("print") -> {
                printByInorder(nodeList[0])
                println()
                printByPreorder(nodeList[0])
                println()
            }
        }
    }
}


fun find(searchKey: Int): String {
    if (nodeList.count() == 0) return "no"

    var x = nodeList[0]

    while (true) {
        if (searchKey == x.key) {
            return "yes"
        }

        if (x.key < searchKey) {
            if (x.right == null) {
                return "no"
            }
            x = x.right!!
        }

        if (x.key > searchKey) {
            if (x.left == null) {
                return "no"
            }
            x = x.left!!
        }
    }
}

fun insert(addedKey: Int) {
    val addedNode = Treee(nodeList.count(), key = addedKey)

    if (nodeList.count() == 0) {
        nodeList.add(addedNode)
        return
    }

    // ルートノーのから開始
    var x = nodeList[0]
    while (true) {
        if (x.key < addedKey) {

            // 右に配置
            if (x.right == null) {
                x.right = addedNode
                break

            } else {
                x = x.right!!
            }
        } else if (x.key > addedKey) {

            // 左に配置
            if (x.left == null) {
                x.left = addedNode
                break;

            } else {
                x = x.left!!
            }

        } else {
            throw Exception("key is duplicated!!!")
        }
    }

    nodeList.add(addedNode)
}

fun printByPreorder(node: Treee) {

    print(" ${node.key}")

    if (node.left != null) {
        printByPreorder(node.left!!)
    }

    if (node.right != null) {
        printByPreorder(node.right!!)
    }
}


fun printByInorder(node: Treee) {

    if (node.left != null) {
        printByInorder(node.left!!)
    }

    print(" ${node.key}")

    if (node.right != null) {
        printByInorder(node.right!!)
    }
}

data class Treee(
    var id: Int,
    var parent: Int = -1,
    var left: Treee? = null,
    var right: Treee? = null,
    var key: Int
)