Outline
- binary search tree algorithms: add, remove, traverse
- binary node class
- binary search tree implementation
- databases
- runtime analysis
Binary search tree properties
- data (e.g. in a typical database) can be identified with a unique key
- in-class exercise: add everyone's name to a search tree
- in-class exercise: is the resulting tree balanced?
Binary search tree get operation
- if searching for a key in an empty subtree, report that the key
was not found
- if the key matches the key in the current node, return
that value
- if the key is less than the key of the current node, recursively get from
the left subtree
- if key is greater than the key of the current node, recursively get from
the right subtree
Binary search tree add operation
- if key is less than the key of the current node, recursively add to
the left subtree
- if key is greater than the key of the current node, recursively add to
the right subtree
- otherwise, add at this node:
- if there is no current node, create one and return it
- if there is a current node, replace its contents with the
new contents
- this assumes:
- the method returns a new root for the new (sub)tree with the
desired value inserted
- the caller of this method knows what to do with the new root
- in-class exercise: write the code for this method
Binary search tree remove operation
- find node with the given key
- if the node is a leaf node, just delete it, return null
- if the node only has a left subtree, return the left subtree
- if the node only has a right subtree, return the right subtree
- if the node has both subtrees, must replace it with another node
that fits in the slot
Removing a node that has both subtrees
- the rightmost node in the left subtree can be put in
place of the current node without altering the sorted property
- likewise, the leftmost node in the right subtree can be put in
place of the current node
- that node might have a left (right) subtree, which can
be used in its old position
- the rightmost node in the left subtree is the inorder predecessor
of the current node
- the leftmost node in the right subtree is the inorder successor
of the current node
- so either can be used
- in-class exercise: delete node 17 from this tree:
- in-class exercise (individually): delete node 14 from the original tree
- in-class exercise (individually): delete node 31 from the original tree
Binary node class
- a singly-linked list node has (at most) one reference to another node
- a binary tree node has (at most) two references to other nodes
- for example, see
here
- both types of nodes also need a reference to the locally stored value
- data fields are item, left,
right
- methods include constructors, accessor methods, mutator methods,
toString
- test program builds small tree, tests the methods
- in-class exercise: build the following tree using the methods
from class BinaryNode
- in-class exercise: write a recursive static method to print the
tree in postorder
Binary search tree class
- for linked lists, we have:
- a node class to define the node of a linked list and the operations
on a single node
- a linked list class to define the operations on an entire linked list
- likewise for trees, we need a class to define the operations on an
entire tree
- different classes can use the same BinaryNode class to provide
different operations on:
- binary trees in general
- binary search trees
here, the second class might be a subclass of the first class
Binary search tree implementation
root is the only data field
methods include the constructors,
add,
get (to get a specified item from a tree),
remove,
toString (inorder traversal of the tree) and pre-order
and post-order conversions to strings,
main exercises the code, ensures basic functionality
BinarySearchTree.java,
uses
TreeIterator.java,
algorithm to add a node to a binary search tree
- non-recursive public method calls recursive
private method (with same name but different signature)
with as argument the root of the tree
- the result of the recursive call is the new root
- so if the root was null, the new root is a leaf node
- recursive method base cases:
- item not in tree: return new node
- item found in tree: replace
- recursive method recursion:
- item less than current node: set left subtree to result
of adding new item to left subtree
- item greater than current node: set right subtree to result
of adding new item to right subtree
- see
BinarySearchTree.java
traversing the search tree
- toString uses a parentheses notation that is
quite messy but can be used to figure out the structure
of the tree
- three iterators: pre-order, in-order, post-order
- all using TreeIterator.java,
which is for all binary trees (not just binary search trees)
- tree iterator uses a stack (or two) to keep track of where it is
in the tree, and which node is next
- by comparison, the recursive (pre-order) traversal done by
toString is much simpler
- the constructors for the iterators all take the root of the
tree as a parameter, so they do not need explicit access to
the private (protected) class data
- this means the iterator methods must be defined
within the BinarySearchTree class or one of its subclasses,
which are the only classes that have access to the root of the tree
databases and search keys
- databases (e.g. shopping lists, address lists, payroll information)
often have one or more identifying items, called keys
- depending on the database, each key may be unique, or each
set of keys may be unique
- binary search trees can be used to store objects that have keys
- the compareTo method should compare just the keys
- the search key uniquely identifies the item (e.g. Social Security
Number in IRS records)
- the value of the item can be changed without harm
- if the search key is modified in place, the binary search tree
is no longer a search tree
- database may refer to the collection of items, to the collection
of items stored on disk, or to the program (database program) that
accesses the collection
class Taxpayer
- for class Taxpayer, the search key is the social security
number
- the compareTo method simply subtracts the SSNs
- see Taxpayer.java
algorithm to find a node in a binary search tree
- recursive algorithm
- base cases:
- subtree to search is null, return null
- root of subtree to search matches desired key, return item
- recursive cases:
- key is less than key in root of subtree, search left subtree, return
that result
- key is greater than key in root of subtree, search right subtree, return
that result
- in-class exercise (individually): write this recursive get
method (you may borrow from the iterative get method)
algorithm to remove a node from a binary search tree
- recursive algorithm
- base cases:
- subtree to search is null, done
- root of subtree to search matches desired key, delete the record
(details below)
- recursive cases:
- key is less than key in root of subtree, replace left subtree with
result of removing item from left subtree
- key is greater than key in root of subtree, replace right subtree with
result of removing item from right subtree
algorithm to delete a node from a binary search tree
- recursive algorithm that is used once the node to delete has
been identified
- base cases:
- node is a leaf: return null
- node has exactly one child: return that child
- recursive case (if the node has both children):
- find the rightmost node in the left subtree
- place the contents of that node in this node
- recursively delete that node
- claim: this maintains the essential characteristic of a binary
search tree
- in-class exercise: is the claim true, and why or why not?
code to delete a node from a binary search tree
- see BinarySearchTree.java
- the rightmost node of the left subtree is the inorder predecessor
of the current node
- all other nodes in the left subtree are less than this node
- all other nodes in the right subtree are greater than this node
efficiency of binary search tree operations
- most operations have time O(height of the tree)
- in a balanced tree, the height is O(log N), with N the number of nodes
- in-class exercise: why is this true?
- in an unbalanced tree, the height is O(N)
- adding and deleting random data may or may not give the desired result
- adding data in sorted order is guaranteed to give the
worst possible result
IRS menu
- see
Menu.java
- can add, edit, remove, or display a list of people and the tax they owe
- reads data from a file, database.csv
- each line in database.csv has comma-separted social security
numbers tax owed, and person name
- the "Binary Search Trees Assignment" asks you to print additional
information about each node