In this lab, you'll implement the set abstract data type using a binary
search tree as the concrete data type. The set will store std::strings and
order them asciibetically: all the values in a node's left subtree will be less
than the value stored in that node, and all the values in the right subtree will
be greater.
This tree is not necessarily balanced. There will be cases where it has poor (O(n)) performance.
Run git pull upstream master in your Git repo to get the starter code.
- Implement a set in the
.hand.cppfiles provided:- Declare a binary tree node type called
NodeinNode.h. - Implement any
Nodemember functions (or helper functions) inNode.cpp. - Implement the
Setmember functions declared inSet.hinSet.cpp.
- Declare a binary tree node type called
- You can't use any container classes from the standard library.
- Make sure your final code doesn't print anything unexpected.
- Make sure you don't have any memory leaks.
Implement the following Set member functions in Set.cpp. Most of these are
standard set operations, but this set also has a special operation called swivel
that can bring any value up to be the root of the tree.
- The default constructor creates an empty set.
- The copy constructor creates a copy of an existing set.
- The move constructor takes the nodes from a set that's about to be deleted.
- The destructor deletes all the nodes in the set.
clear()removes all the values from the set. It returns the number of values that were removed.contains(value)checks if a value is present in the set.count()returns the total number of values in the set.debug()does whatever you want it to. Implement this if you want some other output when testing locally; otherwise ignore it. This function isn't tested.insert(value)adds a value to the set. If the value is already present, it does nothing. It returns the number of values that were added.print()prints the structure of the set in tree notation, as defined below, followed by a single newline.swivel(value)behaves likecontains()in that it returns whether or not a value is in the set. But it also modifies the tree: if the value is present in the set, the node holding the value swivels up repeatedly (see below) until it become the root. If the value isn't present, the last node it searched swivels up instead.remove(value)removes a value from the set and returns the number of values that were removed. Implement it withswivel():- First, call
swivel()on the value to be removed. - If the value wasn't found, stop here. Otherwise, the value to remove is now the root of the tree.
- If the value to remove is on a node with less than two children, remove that node. If the node had a child, the child becomes the new root.
- If the value is on a node with two children, removing it will leave you with two "subtrees." The left subtree will contain values smaller than the value that was removed, and the right subtree will contain greater values. Swivel the smallest value in the right subtree up to become the root. Afterwards, it will not have a left child; attach the left subtree as its left child.
- First, call
In a binary tree, a parent-child link can "swivel," or rotate. The result is a new layout for the binary tree. The search tree ordering is preserved, but the old child node is now the parent, and the old parent is now the child:
d b
/ \ / \
b e <=> a d
/ \ / \
a c c e
Note that when nodes b and d swivel, node c's parent changes as well!
Any node in the tree can become the root by swiveling up repeatedly. Node c,
for example, could become the root after swiveling up twice:
d d c
/ \ / \ / \
b e => c e => b d
/ \ / / \
a c b a e
/
a
A binary tree might look something like this:
d
/ \
b e
/ \ \
a c f
But we need an easy way to print a tree to the console. So we'll define a tree notation that lets us write a tree structure as a single line. In this notation, the tree pictured above would look like this:
((a b c) d (- e f))
More formally:
- The tree notation for a leaf node is simply its value.
- The tree notation for a non-existent node is a hyphen (
-; ASCII value 45). - The tree notation for a non-leaf node is:
- A left parenthesis, followed by
- the tree notation for its left subtree, followed by
- a space, followed by
- the node's value, followed by
- a space, followed by
- the tree notation for its right subtree, followed by
- a right parenthesis.
- The tree notation for an empty tree is
-.
- Recursion works even better with trees than it does with linked lists.
- The standard string comparison operators will give you the correct ordering.
- The
insert()andremove()functions will always return one or zero. - The
swivel()function only looks at one node at each level in the tree, just like likecontains(). If the value to swivel isn't present, the "last node searched" will have at least one null child. - You'll need at least a default constructor,
insert(), andprint()before you can pass any tests on Gradescope.