Project 2

COP 4530

1 Overview

In this project, you will develop code for a binary search tree variant called a Sequoia. Specifically,

you will need to implement member functions for two classes, Sequoia and SequoiaNode. Just like

a BST, Sequoia is the main class and represents the tree as a whole, while SequoiaNode represents

a single node in the tree.

A header file and a driver have been provided. You are allowed to add member functions to

the classes defined in the header; however, you are not allowed to change the data members of

the Sequoia or SequoiaNode classes or modify the driver file. The driver file implements several

validation functions for the Sequoia; these functions must be defined in the header, and you are

not allowed to modify them.

2 Sequoia trees

Just like their real world counterparts, Sequoias are very tall trees. Specifically, every node in a

Sequoia must be a tall node, where a tall node satisfies one of the following:

the left subtree has at least double the height of the right subtree, or

the right subtree has at least double the height of the left subtree

Sequoias are also BSTs, and every node must simultaneously satisfy the BST property:

every value in the left subtree is less than or equal to the value of this node, and

every value in the right subtree is greater than or equal to the value of this node

To maintain the tallness of the Sequoia, each node stores a height in addition to its value, parent,

left and right children. The Sequoia itself stores a root pointer and size.

3 Sequoia insertion

Inserting a node in a Sequoia tree starts by inserting the node in the same way you would insert

a node into a BST. Similar to an AVL tree, we then need to adjust the other nodes in the tree

afterwards to maintain their tallness property. Unlike an AVL tree, though, a Sequoia is quite

unbalanced in an effort to increase its height.

1

To fix the Sequoia nodes’ tallness, iterate up the tree, starting at the parent of the newly inserted

node. At each node, recalculate the height by examining the height of the left and right children.

(I recommend writing an updateHeight() function for this purpose, though this function is not

required.) Then, check whether the height of the left and right trees satisfy the tallness property.

If so, continue on to the parent of this node. Otherwise, there are two cases:

Case 1 : the left subtree height is greater than or equal to the right subtree height, but less than double

Case 2 : the right subtree height is greater than the left but not double

In case 1, we simply rotate the right child of this node to the left, and we resolve case 2 by

rotating the left child of this node to the right. In both cases, we will need to update the height

of the rotated child; however, both this node and the rotated child will be tall afterwards, and we

can continue moving up the tree. These rotations are performed exactly like the rotations for AVL

trees.

Once we have iterated all the way to the root node, we need to check the tree to see whether the

root node was rotated, and if so, update its root. The easiest way to do this is to include a loop in

the Sequoia::insert function that updates the root to be its parent if its parent is not null.

4 Sequoia insertion example

Suppose that we are inserting the value 1 into the Sequoia below. Note that each node is labelled

as value:height, and every node in the tree is tall.

We start by adding the 1 as a left child of 2. This node has height 1.

We then start adjusting the tree, beginning with node 2. The height of node 2 is still 2; however,

the node is no longer tall, as the height of its left and right subtrees are both 1 (1 6≤ 2(1)). This

qualifies as case 1 of the insertion procedure above since the left tree height is greater than or equal

to the right height and but less than double the right height, so we fix it by rotating the right child

(3) to the left and updating the height of node 3:

2

Afterwards, we see that both 2 and 3 are tall, so we continue on to node 4. Node 4 still has

height 5; however, it is also no longer tall, as the height of its left subtree is 3 and the height of its

right subtree is 4 (3 6≥ 2(4) and 4 6≥ 2(3)). This qualifies as case 2 of the insertion procedure above

(since 4 > 3 and 4 < 2(3)), so we fix it by rotating the left child (3) to the right and updating the

height of 3:

At this point, we have reached the root of the tree, so we can stop: every node satisfies the BST

property, has the correct height, and is tall. Afterwards, we need to update the root of the Sequoia

from 4 to 3.

5 Sequoia deletion

Deleting a node from a Sequoia is very similar to insertion; however, the tallness property will be

restored after at most 1 rotation. To start, delete the given node from the Sequoia in the same

manner as a BST. Then, begin iterating up the tree, starting from the parent of the deleted node.

At each node, update the height based on its children, then check whether the node is tall by

comparing the left and right subtree heights. If the tree is tall, continue to the parent of this node,

but otherwise we have the same two cases as insertion:

Case 1 : the left subtree height is greater than or equal to the right subtree height, but less than double

3

Case 2 : the right subtree height is greater than the left but not double

The cases are resolved in the same way as insertion: in case 1, we simply rotate the right child

of this node to the left, and in case 2, we rotate the left child to the right. In both cases, we will

need to update the height of the rotated child; however, this rotation will guarantee that all nodes

in the tree are now tall. As with insertion, we need to update the root in case it was rotated.

6 Sequoia deletion example

Suppose that we are deleting 9 from the Sequoia below:

We start by deleting the 9, so 8 has no children. Then, we start moving up the tree at node 8.

The height of 8 is now 1, and node 8 is tall because its left and right subtrees both have height 0

(0 ≥ 2(0)). The height of 6 is now 2, and it’s also still tall: its left subtree height is 0 and the right

subtree is 1, and 1 ≥ 2(0). Continuing to 5, the height of 5 is now 3. Its left subtree height is 1

and its right subtree height is 2, and 2 ≥ 2(1), so node 5 is tall and we continue to 3. The height

of 3 is now 4, but it is no longer tall, as its left subtree has a height of 2 and its right subtree a

height of 3 (3 6≥ 2(2) and 2 6≥ 2(3)). According to case 2, we should rotate the 1 node to the right

and update its height:

4

Every node now satisfies the BST property, has the correct height, and is tall. Lastly, we would

update the root of this tree to 1. Note that the height of this tree has not changed, so if this tree

were a subtree of a larger Sequoia, all of the other nodes would still be tall and have the correct

height.

7 Driver file

You have been provided with a simple driver file that reads in values to insert and delete from

input.txt and performs these operations on an empty Sequoia tree. The driver writes two trees to

output.txt, one per line: the first is printed after all insertions and the second after all deletions

are done.

The input.txt file will have 2 lines. The first line has all of the integers to be inserted into the

Sequoia tree, separated by spaces, and the second line has all of the integers to be removed from

the tree, separated by spaces. All of the values on the second line will also appear on the first line.

All insertions and deletions are performed in the order that the values are entered on each line.

Moreover, the driver checks that every node in the tree has the correct height and is tall after every

insertion and deletion and will print an error message and stop if some node is incorrect.

8 Submission and grading

You should your source code and header, sequoia.cpp and sequoia.h, as a zip archive. Your code

will be evaluated based on whether it produces the correct output for some number of test cases.

You may use any development environment that you like when developing the code; however, it

will be compiled and run using g++ in a Linux environment. Code that does not compile will not

receive substantial credit, so be sure that your code can be compiled using g++.

The development environment used in class is VS Code (https://code.visualstudio.com/

download). This IDE includes useful features like syntax highlighting and an integrated terminal

window that you can use to invoke a compiler.

Windows users can download MinGW (https://sourceforge.net/projects/mingw-w64) to

use g++, though you will need to add the MinGW bin directory to the Windows path in order for

the terminal to recognize the command g++ (or gdb or any of the other tools provided by MinGW).

9 Important note

You are allowed to use any code posted for this course on Canvas, and you are allowed to discuss

this project with the course TAs or professor. However, you are not allowed to use code from the

internet or your peers. Your code will be run through plagiarism-detection software, and violators

will be dealt with accordingly.

5