Hackbright Code Challenges

BST Add Child

BST Add Child

Whiteboard

Harder

Challenge

Medium

Concepts

BST, Recursion

Download

bst-add-child.zip

Solution

BST Add Child: Solution


In this challenge, you will write a function to append a child to a node in a Binary Search Tree.

We’ll give you a Node class with left and right attributes, as well as a data attribute:

bstadd.py
class Node(object):  # ...
    def __init__(self, data, left=None, right=None):
        """Create node, with data and optional left/right."""

        self.left = left
        self.right = right
        self.data = data

Consider this tree:

digraph tree { ordering=out node [width=0.6] 4 -> 2 4 -> space [style="invis"] 4 -> 7 2 -> { 1, 3 } 7 -> { 5, 8 } space [style="invis" width=0] }

We can build this tree using our Node class like this:

>>> t = Node(4,
...       Node(2, Node(1), Node(3)),
...       Node(7, Node(5), Node(8))
... )

If we wanted to add 0 to our tree, it would end up as the left-most child of our tree, as it comes before everything else in the tree. We’d end up with this tree:

digraph tree { ordering=out node [width=0.6] 4 -> 2 4 -> space [style="invis"] 4 -> 7 2 -> { 1, 3 } 7 -> { 5, 8 } 1 -> 0 1 -> space1 [style="invis"] space [style="invis" width=0] space1 [style="invis" width=0] }

Our insert method should do this correctly:

>>> t.insert(0)

>>> t.left.left.left.data == 0
True

>>> t.left.left.right is None
True

If we added 9, it would end up as the right-most node, as it comes after everything else in the tree:

digraph tree { ordering=out node [width=0.6] 4 -> 2 4 -> space [style="invis"] 4 -> 7 2 -> { 1, 3 } 7 -> { 5, 8 } 1 -> 0 1 -> space1 [style="invis"] 8 -> space2 [style="invis"] 8 -> 9 space [style="invis" width=0] space1 [style="invis" width=0] space2 [style="invis" width=0] }

Our insert method should do this correctly:

>>> t.insert(9)

>>> t.right.right.right.data == 9
True

>>> t.right.right.left is None
True

If we added 6, it would end up to the right of the 5:

digraph tree { ordering=out node [width=0.6] 4 -> 2 4 -> space [style="invis"] 4 -> 7 2 -> 1 2 -> space5 [style="invis"] 2 -> 3 7 -> 5 7 -> space4 [style="invis"] 7 -> 8 1 -> 0 1 -> space1 [style="invis"] 8 -> space2 [style="invis"] 8 -> 9 5 -> space3 [style=invis] 5 -> 6 space [style="invis" width=3] space1 [style="invis" width=0] space2 [style="invis" width=0] space3 [style="invis" width=0] space4 [style="invis" width=0] space5 [style="invis" width=0] }

Our insert method should do this correctly:

>>> t.insert(6)

>>> t.right.left.right.data == 6
True

>>> t.right.left.left is None
True

We’ve given you a stub of the insert method:

bstadd.py
class Node(object):  # ...
    def insert(self, new_data):
        """Insert new node with `new_data` to BST tree rooted here."""

Implement it.

It may help to practice adding a few nodes by hand to a tree to figure out the pattern for where to add a node.

Duplicate Entries

There are different ways to deal with duplicate entries in a binary tree. Some trees use a rule that allows for equality, like “if the value is less than the current value, go left” and “if the value is greater than or equal to the current value, go right”.

For this code challenge, you do not have to deal with duplicate values; you may assume that every item inserted into the tree is unique.

Balanced Binary Search Trees

A “balanced” binary search tree is one where the nodes are equitably spread out to guarantee O(log n) search. For this code challenge, you should not try to re-arrange the tree to rebalance it after adding an item; instead, you should simply find the correct place in the current tree to add it.

Rebalancing trees is an interesting advanced topic. You can consult a good algorithms book on “AVL Trees” for an introduction.