{
  "id": "P052",
  "slug": "bst-explorer",
  "key": "P052-bst-explorer",
  "title": "Binary search tree explorer",
  "summary": "A binary search tree of whole numbers: insert keys, delete them - a leaf, a node with one child, or one with two, replaced by its successor - and search with the path shown. Walk it in order, pre-order and post-order, see its size, height, smallest and largest key, and see it drawn on its side.",
  "entry": "main.eml",
  "ui": "terminal",
  "readme": "# P052 - Binary search tree explorer\n\nA binary search tree of whole numbers from -999 to 999, up to 40 keys.\nInsert keys, delete them, and search for one to see the path taken. Walk\nthe tree in order, pre-order and post-order, see its size, height, smallest\nand largest key, and see it drawn.\n\n- `main.eml` - the menu, reading keys, and the messages for each operation\n- `tree.eml` - the tree: inserting, searching, deleting, the three walks,\n  the height and the drawing\n\nHow each part works:\n\n- The tree is kept as in the corpus case `binary-search-tree`: three\n  parallel lists - the keys, each node's left child and its right child,\n  -1 for none - plus the root, so every change is one assignment to one\n  list position. Smaller keys go left and larger keys right; a key is in\n  the tree at most once.\n- Deleting a leaf cuts it off. Deleting a node with one child lets the\n  child take its place. Deleting a node with two children copies in the key\n  of its successor - the smallest key in its right subtree, found by going\n  right once and then left as far as possible - and cuts out the\n  successor, which has no left child. The order of the keys never breaks.\n- In order visits the left subtree, the node and the right subtree, which\n  gives the keys sorted. Pre-order visits the node first: inserting the\n  keys in that order builds the same tree again. Post-order visits the node\n  last: an order in which every node can go after its children.\n- The height counts levels: an empty tree has height 0 and a lone root 1.\n  The drawing turns the tree on its side - the right subtree above its\n  node and the left below, four spaces for each level down.\n\nWhat is checked: menu choices 1 to 8; keys as whole numbers from -999 to\n999, separated by spaces or commas, and a line with anything else inserts\nnothing; keys already in the tree are named and left; at most 40 keys. An\nempty answer cancels.\n\nSessions: `sessions/basic.in` loads the sample, the corpus case's keys 50\n30 70 20 40 60 80 35, and walks it.\n- Searches: 35 is found in 4 steps, and 65 falls off the right of 60.\n- Deletes, one of each kind: 20, a leaf; 40, whose one child 35 moves up;\n  and the root 50, whose two children make its successor 60 the new root.\n- Inserts: 45, 10, 90 and -5, typed with a comma and spaces, then a walk.\n\n`sessions/bad-input.in` gives:\n- menu choices 0 and x;\n- walks, a drawing, a search and a delete on the empty tree;\n- the key lines \"1 2 x\", 1000 and -1000, each inserting nothing, and an\n  empty one;\n- 5 5 3, where the second 5 is already there;\n- the keys abc and --5, with a delete and a search, both cancelled;\n- 1 to 8 inserted in order: the tree becomes a single right-leaning\n  chain of height 8, and every walk but post-order lists the keys sorted;\n- 1 to 41 inserted middle first. The first 40 build a tree of height 6,\n  the lowest any 40 keys can have, and the 41st is turned away at the\n  limit.\n\nBuilt on the verified corpus case `binary-search-tree` (a tree built by\ninsertion in parallel lists, read back by a recursive in-order walk).\n",
  "modules": [
    {
      "name": "main.eml",
      "eml": "# P052 binary search tree explorer: insert and delete keys, search with the\n# path taken, walk the tree in order, pre-order and post-order, and see it\n# drawn - with its size, height, smallest and largest key.\nimport tree\n\ndef trim(s):\n    0 => i\n    len(s) => j\n    while i < j and s[i] == \" \":\n        i + 1 => i\n    while j > i and s[j - 1] == \" \":\n        j - 1 => j\n    return s[i:j]\n\ndef words(s):\n    [] => out\n    \"\" => word\n    for c in s + \" \":\n        if c == \" \" or c == \",\":\n            if word != \"\":\n                out + [word] => out\n            \"\" => word\n        else:\n            word + c => word\n    return out\n\ndef key_of(s):\n    # A whole number from -999 to 999, as [ok, value].\n    s => digits\n    1 => sign\n    if len(s) > 1 and s[0] == \"-\":\n        s[1:len(s)] => digits\n        -1 => sign\n    if digits == \"\" or len(digits) > 3:\n        return [False, 0]\n    0 => n\n    for c in digits:\n        if not (c >= \"0\" and c <= \"9\"):\n            return [False, 0]\n        n * 10 + int(c) => n\n    return [True, sign * n]\n\ndef joined(xs, sep):\n    \"\" => s\n    for x in xs:\n        if s != \"\":\n            s + sep => s\n        s + str(x) => s\n    return s\n\ndef keys(t):\n    return tree.in_order(t, t[3], [])\n\ndef draw(t):\n    if t[3] == -1:\n        \"The tree is empty.\" ^0\n        return\n    for line in tree.sideways(t, t[3], 0, []):\n        line ^0\n\ndef insert_keys(t):\n    words(trim(input(\"keys to insert (-999 to 999)> \"))) => ws\n    if len(ws) == 0:\n        \"Cancelled.\" ^0\n        return\n    [] => values\n    for w in ws:\n        key_of(w) => k\n        if not k[0]:\n            (\"Not a key from -999 to 999: \" + w + \". Nothing was inserted.\") ^0\n            return\n        values + [k[1]] => values\n    [] => added\n    [] => there\n    0 => k\n    while k < len(values) and len(keys(t)) < 40:\n        if tree.insert(t, values[k]):\n            added + [values[k]] => added\n        else:\n            there + [values[k]] => there\n        k + 1 => k\n    if len(added) > 0:\n        (\"Inserted \" + joined(added, \" \") + \".\") ^0\n    if len(there) > 0:\n        (\"Already in the tree: \" + joined(there, \" \") + \".\") ^0\n    len(values) - k => rest\n    if rest == 1:\n        (\"The tree holds 40 keys, the most it takes; the last key typed, \" + str(values[k]) + \", was not inserted.\") ^0\n    elif rest > 1:\n        (\"The tree holds 40 keys, the most it takes; the last \" + str(rest) + \" keys typed, from \" + str(values[k]) + \" on, were not inserted.\") ^0\n    draw(t)\n\ndef ask_key(prompt):\n    while True:\n        trim(input(prompt)) => answer\n        if answer == \"\":\n            return [False, 0]\n        key_of(answer) => k\n        if k[0]:\n            return k\n        \"Type one whole number from -999 to 999.\" ^0\n\ndef delete_key(t):\n    ask_key(\"key to delete> \") => k\n    if not k[0]:\n        \"Cancelled.\" ^0\n        return\n    tree.delete(t, k[1]) => r\n    if len(r) == 0:\n        (str(k[1]) + \" is not in the tree.\") ^0\n        return\n    if r[0] == 0:\n        (\"Deleted \" + str(k[1]) + \", a leaf.\") ^0\n    elif r[0] == 1:\n        (\"Deleted \" + str(k[1]) + \"; its one child took its place.\") ^0\n    else:\n        (\"Deleted \" + str(k[1]) + \". It had two children, so \" + str(r[1]) + \" - the smallest key on its right - moved up into its place.\") ^0\n    draw(t)\n\ndef search_key(t):\n    ask_key(\"key to search for> \") => k\n    if not k[0]:\n        \"Cancelled.\" ^0\n        return\n    tree.search(t, k[1]) => r\n    if r[0]:\n        (\"Found \" + str(k[1]) + \" after \" + str(len(r[1])) + \" steps: \" + joined(r[1], \" -> \") + \".\") ^0\n    elif len(r[1]) == 0:\n        \"The tree is empty.\" ^0\n    else:\n        r[1][len(r[1]) - 1] => last\n        \"left\" => side\n        if k[1] > last:\n            \"right\" => side\n        (str(k[1]) + \" is not in the tree: \" + joined(r[1], \" -> \") + \", and \" + str(last) + \" has no child on the \" + side + \", where it would go.\") ^0\n\ndef walks(t):\n    if t[3] == -1:\n        \"The tree is empty.\" ^0\n        return\n    keys(t) => ks\n    (\"In order:   \" + joined(ks, \" \")) ^0\n    (\"Pre-order:  \" + joined(tree.pre_order(t, t[3], []), \" \")) ^0\n    (\"Post-order: \" + joined(tree.post_order(t, t[3], []), \" \")) ^0\n    (str(len(ks)) + \" keys, height \" + str(tree.height(t, t[3])) + \", smallest \" + str(ks[0]) + \", largest \" + str(ks[len(ks) - 1]) + \".\") ^0\n\ndef sample():\n    # The corpus case's keys, in its order.\n    tree.new_tree() => t\n    for v in [50, 30, 70, 20, 40, 60, 80, 35]:\n        tree.insert(t, v)\n    \"The sample: 50 30 70 20 40 60 80 35, inserted in that order.\" ^0\n    return t\n\n\"== Binary search tree ==\" ^0\n\"Smaller keys go left, larger keys right. The tree is drawn on its side: right is up.\" ^0\ntree.new_tree() => t\nTrue => running\nwhile running:\n    \"\" ^0\n    \"1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\" ^0\n    trim(input(\"choice> \")) => choice\n    if choice == \"1\":\n        insert_keys(t)\n    elif choice == \"2\":\n        delete_key(t)\n    elif choice == \"3\":\n        search_key(t)\n    elif choice == \"4\":\n        walks(t)\n    elif choice == \"5\":\n        draw(t)\n    elif choice == \"6\":\n        sample() => t\n        draw(t)\n    elif choice == \"7\":\n        tree.new_tree() => t\n        \"The tree is empty now.\" ^0\n    elif choice == \"8\":\n        False => running\n    else:\n        \"Pick a number from 1 to 8.\" ^0\n\"Bye.\" ^0\n",
      "python": "import tree\n\ndef trim(s):\n    i = 0\n    j = len(s)\n    while i < j and s[i] == \" \":\n        i = i + 1\n    while j > i and s[j - 1] == \" \":\n        j = j - 1\n    return s[i:j]\n\ndef words(s):\n    out = []\n    word = \"\"\n    for c in s + \" \":\n        if c == \" \" or c == \",\":\n            if word != \"\":\n                out = out + [word]\n            word = \"\"\n        else:\n            word = word + c\n    return out\n\ndef key_of(s):\n    digits = s\n    sign = 1\n    if len(s) > 1 and s[0] == \"-\":\n        digits = s[1:len(s)]\n        sign = -1\n    if digits == \"\" or len(digits) > 3:\n        return [False, 0]\n    n = 0\n    for c in digits:\n        if not (c >= \"0\" and c <= \"9\"):\n            return [False, 0]\n        n = n * 10 + int(c)\n    return [True, sign * n]\n\ndef joined(xs, sep):\n    s = \"\"\n    for x in xs:\n        if s != \"\":\n            s = s + sep\n        s = s + str(x)\n    return s\n\ndef keys(t):\n    return tree.in_order(t, t[3], [])\n\ndef draw(t):\n    if t[3] == -1:\n        print(\"The tree is empty.\")\n        return\n    for line in tree.sideways(t, t[3], 0, []):\n        print(line)\n\ndef insert_keys(t):\n    ws = words(trim(input(\"keys to insert (-999 to 999)> \")))\n    if len(ws) == 0:\n        print(\"Cancelled.\")\n        return\n    values = []\n    for w in ws:\n        k = key_of(w)\n        if not k[0]:\n            print(\"Not a key from -999 to 999: \" + w + \". Nothing was inserted.\")\n            return\n        values = values + [k[1]]\n    added = []\n    there = []\n    k = 0\n    while k < len(values) and len(keys(t)) < 40:\n        if tree.insert(t, values[k]):\n            added = added + [values[k]]\n        else:\n            there = there + [values[k]]\n        k = k + 1\n    if len(added) > 0:\n        print(\"Inserted \" + joined(added, \" \") + \".\")\n    if len(there) > 0:\n        print(\"Already in the tree: \" + joined(there, \" \") + \".\")\n    rest = len(values) - k\n    if rest == 1:\n        print(\"The tree holds 40 keys, the most it takes; the last key typed, \" + str(values[k]) + \", was not inserted.\")\n    elif rest > 1:\n        print(\"The tree holds 40 keys, the most it takes; the last \" + str(rest) + \" keys typed, from \" + str(values[k]) + \" on, were not inserted.\")\n    draw(t)\n\ndef ask_key(prompt):\n    while True:\n        answer = trim(input(prompt))\n        if answer == \"\":\n            return [False, 0]\n        k = key_of(answer)\n        if k[0]:\n            return k\n        print(\"Type one whole number from -999 to 999.\")\n\ndef delete_key(t):\n    k = ask_key(\"key to delete> \")\n    if not k[0]:\n        print(\"Cancelled.\")\n        return\n    r = tree.delete(t, k[1])\n    if len(r) == 0:\n        print(str(k[1]) + \" is not in the tree.\")\n        return\n    if r[0] == 0:\n        print(\"Deleted \" + str(k[1]) + \", a leaf.\")\n    elif r[0] == 1:\n        print(\"Deleted \" + str(k[1]) + \"; its one child took its place.\")\n    else:\n        print(\"Deleted \" + str(k[1]) + \". It had two children, so \" + str(r[1]) + \" - the smallest key on its right - moved up into its place.\")\n    draw(t)\n\ndef search_key(t):\n    k = ask_key(\"key to search for> \")\n    if not k[0]:\n        print(\"Cancelled.\")\n        return\n    r = tree.search(t, k[1])\n    if r[0]:\n        print(\"Found \" + str(k[1]) + \" after \" + str(len(r[1])) + \" steps: \" + joined(r[1], \" -> \") + \".\")\n    elif len(r[1]) == 0:\n        print(\"The tree is empty.\")\n    else:\n        last = r[1][len(r[1]) - 1]\n        side = \"left\"\n        if k[1] > last:\n            side = \"right\"\n        print(str(k[1]) + \" is not in the tree: \" + joined(r[1], \" -> \") + \", and \" + str(last) + \" has no child on the \" + side + \", where it would go.\")\n\ndef walks(t):\n    if t[3] == -1:\n        print(\"The tree is empty.\")\n        return\n    ks = keys(t)\n    print(\"In order:   \" + joined(ks, \" \"))\n    print(\"Pre-order:  \" + joined(tree.pre_order(t, t[3], []), \" \"))\n    print(\"Post-order: \" + joined(tree.post_order(t, t[3], []), \" \"))\n    print(str(len(ks)) + \" keys, height \" + str(tree.height(t, t[3])) + \", smallest \" + str(ks[0]) + \", largest \" + str(ks[len(ks) - 1]) + \".\")\n\ndef sample():\n    t = tree.new_tree()\n    for v in [50, 30, 70, 20, 40, 60, 80, 35]:\n        tree.insert(t, v)\n    print(\"The sample: 50 30 70 20 40 60 80 35, inserted in that order.\")\n    return t\n\nprint(\"== Binary search tree ==\")\nprint(\"Smaller keys go left, larger keys right. The tree is drawn on its side: right is up.\")\nt = tree.new_tree()\nrunning = True\nwhile running:\n    print(\"\")\n    print(\"1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\")\n    choice = trim(input(\"choice> \"))\n    if choice == \"1\":\n        insert_keys(t)\n    elif choice == \"2\":\n        delete_key(t)\n    elif choice == \"3\":\n        search_key(t)\n    elif choice == \"4\":\n        walks(t)\n    elif choice == \"5\":\n        draw(t)\n    elif choice == \"6\":\n        t = sample()\n        draw(t)\n    elif choice == \"7\":\n        t = tree.new_tree()\n        print(\"The tree is empty now.\")\n    elif choice == \"8\":\n        running = False\n    else:\n        print(\"Pick a number from 1 to 8.\")\nprint(\"Bye.\")\n"
    },
    {
      "name": "tree.eml",
      "eml": "# P052 binary search tree - the tree is the corpus case binary-search-tree's\n# three parallel lists, indexed by node number with -1 for \"no child\":\n# [values, lefts, rights, root]. Smaller keys go left, larger keys right,\n# and a key is in the tree at most once. A deleted node's slot is simply\n# no longer linked; nothing is moved.\n\ndef new_tree():\n    return [[], [], [], -1]\n\ndef added_node(t, key):\n    len(t[0]) => k\n    t[0] + [key] => t[0]\n    t[1] + [-1] => t[1]\n    t[2] + [-1] => t[2]\n    return k\n\ndef insert(t, key):\n    # True when key was added, False when it was there already.\n    if t[3] == -1:\n        added_node(t, key) => t[3]\n        return True\n    t[3] => n\n    while True:\n        if key == t[0][n]:\n            return False\n        if key < t[0][n]:\n            if t[1][n] == -1:\n                added_node(t, key) => t[1][n]\n                return True\n            t[1][n] => n\n        else:\n            if t[2][n] == -1:\n                added_node(t, key) => t[2][n]\n                return True\n            t[2][n] => n\n\ndef search(t, key):\n    # [found, the keys passed on the way down].\n    [] => path\n    t[3] => n\n    while n != -1:\n        path + [t[0][n]] => path\n        if key == t[0][n]:\n            return [True, path]\n        if key < t[0][n]:\n            t[1][n] => n\n        else:\n            t[2][n] => n\n    return [False, path]\n\ndef relink(t, parent, old, new):\n    # Points whatever pointed at node old - the root, or a child link of\n    # parent - at node new instead.\n    if parent == -1:\n        new => t[3]\n    elif t[1][parent] == old:\n        new => t[1][parent]\n    else:\n        new => t[2][parent]\n\ndef delete(t, key):\n    # Returns [] when key is not in the tree, otherwise [children, key moved\n    # up]: a node with no child or one child is cut out and its child (if\n    # any) takes its place; a node with two children takes the key of its\n    # successor - the smallest key on its right - and that successor, which\n    # has no left child, is cut out instead.\n    -1 => parent\n    t[3] => n\n    while n != -1 and t[0][n] != key:\n        n => parent\n        if key < t[0][n]:\n            t[1][n] => n\n        else:\n            t[2][n] => n\n    if n == -1:\n        return []\n    if t[1][n] != -1 and t[2][n] != -1:\n        n => sp\n        t[2][n] => s\n        while t[1][s] != -1:\n            s => sp\n            t[1][s] => s\n        t[0][s] => t[0][n]\n        relink(t, sp, s, t[2][s])\n        return [2, t[0][n]]\n    t[1][n] => child\n    0 => kids\n    if child != -1:\n        1 => kids\n    else:\n        t[2][n] => child\n        if child != -1:\n            1 => kids\n    relink(t, parent, n, child)\n    return [kids, key]\n\ndef in_order(t, n, out):\n    # Left subtree, the node, right subtree: the keys in sorted order.\n    if n == -1:\n        return out\n    in_order(t, t[1][n], out) => out\n    out + [t[0][n]] => out\n    return in_order(t, t[2][n], out)\n\ndef pre_order(t, n, out):\n    # The node before its subtrees: inserting the keys in this order builds\n    # the same tree again.\n    if n == -1:\n        return out\n    out + [t[0][n]] => out\n    pre_order(t, t[1][n], out) => out\n    return pre_order(t, t[2][n], out)\n\ndef post_order(t, n, out):\n    # Both subtrees before the node: an order in which every node can be\n    # taken away after its children.\n    if n == -1:\n        return out\n    post_order(t, t[1][n], out) => out\n    post_order(t, t[2][n], out) => out\n    return out + [t[0][n]]\n\ndef height(t, n):\n    # Levels: an empty tree has height 0, a lone root 1.\n    if n == -1:\n        return 0\n    height(t, t[1][n]) => a\n    height(t, t[2][n]) => b\n    if a > b:\n        return a + 1\n    return b + 1\n\ndef sideways(t, n, depth, lines):\n    # The tree turned on its side: the right subtree above its node, the\n    # left below, four spaces for each level down.\n    if n == -1:\n        return lines\n    sideways(t, t[2][n], depth + 1, lines) => lines\n    lines + [\"    \" * depth + str(t[0][n])] => lines\n    return sideways(t, t[1][n], depth + 1, lines)\n",
      "python": "def new_tree():\n    return [[], [], [], -1]\n\ndef added_node(t, key):\n    k = len(t[0])\n    t[0] = t[0] + [key]\n    t[1] = t[1] + [-1]\n    t[2] = t[2] + [-1]\n    return k\n\ndef insert(t, key):\n    if t[3] == -1:\n        t[3] = added_node(t, key)\n        return True\n    n = t[3]\n    while True:\n        if key == t[0][n]:\n            return False\n        if key < t[0][n]:\n            if t[1][n] == -1:\n                t[1][n] = added_node(t, key)\n                return True\n            n = t[1][n]\n        else:\n            if t[2][n] == -1:\n                t[2][n] = added_node(t, key)\n                return True\n            n = t[2][n]\n\ndef search(t, key):\n    path = []\n    n = t[3]\n    while n != -1:\n        path = path + [t[0][n]]\n        if key == t[0][n]:\n            return [True, path]\n        if key < t[0][n]:\n            n = t[1][n]\n        else:\n            n = t[2][n]\n    return [False, path]\n\ndef relink(t, parent, old, new):\n    if parent == -1:\n        t[3] = new\n    elif t[1][parent] == old:\n        t[1][parent] = new\n    else:\n        t[2][parent] = new\n\ndef delete(t, key):\n    parent = -1\n    n = t[3]\n    while n != -1 and t[0][n] != key:\n        parent = n\n        if key < t[0][n]:\n            n = t[1][n]\n        else:\n            n = t[2][n]\n    if n == -1:\n        return []\n    if t[1][n] != -1 and t[2][n] != -1:\n        sp = n\n        s = t[2][n]\n        while t[1][s] != -1:\n            sp = s\n            s = t[1][s]\n        t[0][n] = t[0][s]\n        relink(t, sp, s, t[2][s])\n        return [2, t[0][n]]\n    child = t[1][n]\n    kids = 0\n    if child != -1:\n        kids = 1\n    else:\n        child = t[2][n]\n        if child != -1:\n            kids = 1\n    relink(t, parent, n, child)\n    return [kids, key]\n\ndef in_order(t, n, out):\n    if n == -1:\n        return out\n    out = in_order(t, t[1][n], out)\n    out = out + [t[0][n]]\n    return in_order(t, t[2][n], out)\n\ndef pre_order(t, n, out):\n    if n == -1:\n        return out\n    out = out + [t[0][n]]\n    out = pre_order(t, t[1][n], out)\n    return pre_order(t, t[2][n], out)\n\ndef post_order(t, n, out):\n    if n == -1:\n        return out\n    out = post_order(t, t[1][n], out)\n    out = post_order(t, t[2][n], out)\n    return out + [t[0][n]]\n\ndef height(t, n):\n    if n == -1:\n        return 0\n    a = height(t, t[1][n])\n    b = height(t, t[2][n])\n    if a > b:\n        return a + 1\n    return b + 1\n\ndef sideways(t, n, depth, lines):\n    if n == -1:\n        return lines\n    lines = sideways(t, t[2][n], depth + 1, lines)\n    lines = lines + [\"    \" * depth + str(t[0][n])]\n    return sideways(t, t[1][n], depth + 1, lines)\n"
    }
  ],
  "sessions": [
    {
      "name": "bad-input",
      "input": "0\nx\n4\n5\n3\n7\n2\n7\n1\n1 2 x\n1\n1000\n1\n-1000\n1\n\n1\n5 5 3\n2\nabc\n\n3\n--5\n\n7\n1\n1 2 3 4 5 6 7 8\n4\n7\n1\n21 10 31 5 15 26 36 2 7 12 18 23 28 33 39 1 3 6 8 11 13 16 19 22 24 27 29 32 34 37 40 4 9 14 17 20 25 30 35 38 41\n4\n7\n5\n8\n",
      "screen": "== Binary search tree ==\nSmaller keys go left, larger keys right. The tree is drawn on its side: right is up.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 0\nPick a number from 1 to 8.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> x\nPick a number from 1 to 8.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 4\nThe tree is empty.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 5\nThe tree is empty.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 3\nkey to search for> 7\nThe tree is empty.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 2\nkey to delete> 7\n7 is not in the tree.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 1\nkeys to insert (-999 to 999)> 1 2 x\nNot a key from -999 to 999: x. Nothing was inserted.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 1\nkeys to insert (-999 to 999)> 1000\nNot a key from -999 to 999: 1000. Nothing was inserted.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 1\nkeys to insert (-999 to 999)> -1000\nNot a key from -999 to 999: -1000. Nothing was inserted.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 1\nkeys to insert (-999 to 999)> \nCancelled.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 1\nkeys to insert (-999 to 999)> 5 5 3\nInserted 5 3.\nAlready in the tree: 5.\n5\n    3\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 2\nkey to delete> abc\nType one whole number from -999 to 999.\nkey to delete> \nCancelled.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 3\nkey to search for> --5\nType one whole number from -999 to 999.\nkey to search for> \nCancelled.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 7\nThe tree is empty now.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 1\nkeys to insert (-999 to 999)> 1 2 3 4 5 6 7 8\nInserted 1 2 3 4 5 6 7 8.\n                            8\n                        7\n                    6\n                5\n            4\n        3\n    2\n1\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 4\nIn order:   1 2 3 4 5 6 7 8\nPre-order:  1 2 3 4 5 6 7 8\nPost-order: 8 7 6 5 4 3 2 1\n8 keys, height 8, smallest 1, largest 8.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 7\nThe tree is empty now.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 1\nkeys to insert (-999 to 999)> 21 10 31 5 15 26 36 2 7 12 18 23 28 33 39 1 3 6 8 11 13 16 19 22 24 27 29 32 34 37 40 4 9 14 17 20 25 30 35 38 41\nInserted 21 10 31 5 15 26 36 2 7 12 18 23 28 33 39 1 3 6 8 11 13 16 19 22 24 27 29 32 34 37 40 4 9 14 17 20 25 30 35 38.\nThe tree holds 40 keys, the most it takes; the last key typed, 41, was not inserted.\n                40\n            39\n                    38\n                37\n        36\n                    35\n                34\n            33\n                32\n    31\n                    30\n                29\n            28\n                27\n        26\n                    25\n                24\n            23\n                22\n21\n                    20\n                19\n            18\n                    17\n                16\n        15\n                    14\n                13\n            12\n                11\n    10\n                    9\n                8\n            7\n                6\n        5\n                    4\n                3\n            2\n                1\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 4\nIn order:   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40\nPre-order:  21 10 5 2 1 3 4 7 6 8 9 15 12 11 13 14 18 16 17 19 20 31 26 23 22 24 25 28 27 29 30 36 33 32 34 35 39 37 38 40\nPost-order: 1 4 3 2 6 9 8 7 5 11 14 13 12 17 16 20 19 18 15 10 22 25 24 23 27 30 29 28 26 32 35 34 33 38 37 40 39 36 31 21\n40 keys, height 6, smallest 1, largest 40.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 7\nThe tree is empty now.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 5\nThe tree is empty.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 8\nBye.\n",
      "interpreter": "equal"
    },
    {
      "name": "basic",
      "input": "6\n4\n3\n35\n3\n65\n2\n20\n2\n40\n2\n50\n1\n45, 10 90 -5\n4\n8\n",
      "screen": "== Binary search tree ==\nSmaller keys go left, larger keys right. The tree is drawn on its side: right is up.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 6\nThe sample: 50 30 70 20 40 60 80 35, inserted in that order.\n        80\n    70\n        60\n50\n        40\n            35\n    30\n        20\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 4\nIn order:   20 30 35 40 50 60 70 80\nPre-order:  50 30 20 40 35 70 60 80\nPost-order: 20 35 40 30 60 80 70 50\n8 keys, height 4, smallest 20, largest 80.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 3\nkey to search for> 35\nFound 35 after 4 steps: 50 -> 30 -> 40 -> 35.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 3\nkey to search for> 65\n65 is not in the tree: 50 -> 70 -> 60, and 60 has no child on the right, where it would go.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 2\nkey to delete> 20\nDeleted 20, a leaf.\n        80\n    70\n        60\n50\n        40\n            35\n    30\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 2\nkey to delete> 40\nDeleted 40; its one child took its place.\n        80\n    70\n        60\n50\n        35\n    30\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 2\nkey to delete> 50\nDeleted 50. It had two children, so 60 - the smallest key on its right - moved up into its place.\n        80\n    70\n60\n        35\n    30\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 1\nkeys to insert (-999 to 999)> 45, 10 90 -5\nInserted 45 10 90 -5.\n            90\n        80\n    70\n60\n            45\n        35\n    30\n        10\n            -5\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 4\nIn order:   -5 10 30 35 45 60 70 80 90\nPre-order:  60 30 10 -5 35 45 70 80 90\nPost-order: -5 10 45 35 30 90 80 70 60\n9 keys, height 4, smallest -5, largest 90.\n\n1) insert  2) delete  3) search  4) walks  5) draw  6) sample  7) clear  8) quit\nchoice> 8\nBye.\n",
      "interpreter": "equal"
    }
  ],
  "builtOn": [
    {
      "slug": "binary-search-tree",
      "caseId": "081-binary-search-tree",
      "title": "Binary search tree"
    }
  ],
  "updated": "2026-10-10"
}
