A binary search tree (BST) is a specialized form of a standard binary tree. We have already built a binary tree inside of our heaps class so the structure will feel familiar as we implement our changes to make a true BST. Binary search trees are a very efficient storage system for data storage, lookup, and removal with the time complexity of all operations directly proportional to the height of the tree. Since a binary tree can have at most two children, we eliminate half the remaining tree with each iteration of a function or in Big O notation, O(log n), where n is the number of nodes in the tree. This is true as long as the tree is reasonably balanced. If addition into the tree is performed on sorted data, it will result in a tree that always only uses either the left or right branch, leading the height of the tree to be as large as the data set and bringing the time complexity to O(n) time.
The basic rules of a binary search tree are:
- The left child and its subtree contain values less than the parent node’s values
- The right child and its subtree contain values greater than the parent node’s values
- Each left and right subtree is in itself an implementation of a BST
Throughout this implementation, we will create methods to add, remove, search, and print a BST as well as retrieve the minimum value in our tree.
At the conclusion of our Tree lesson, we provided a generic implementation of a Tree to start you down the path of creating generic data structures. In this lesson, we will be creating a generic BST throughout and teaching you how to add additional restrictions to your generics to ensure your code isn’t broken by someone trying to pass in custom objects.
Create two empty classes,
BinaryNode class, right after the class name and before the curly brackets, at a set of angle brackets and the generic type
T between them.
Do the same for
We want the generic in
BinarySearchTree to conform to two protocols,
CustomStringConvertible. We will use these when adding/finding/removing items from the BST and printing the tree.
When requiring conformance to multiple protocols, use the
& operator between the protocols, this is called protocol composition and ensures that the object conforms to the combined requirements of the protocols.
BinaryNode class, add three instance variables:
leftChild, an optional
rightChild, an optional
And an initializer with a parameter,
data of type
T, that sets
BinarySearchTree class, add a private instance variable,
root as a
BinaryNode optional, remember you need to include the generic reference
<T> beside the class name, this ensures our
BinaryNodes are of the same type,
At the bottom of the file, create a new variable,
numberTree, equal to a new
BinarySearchTree with the type
Int passed into the angle brackets of the class instantiation.