$29
Assignment Overview
# Red/Black Tree
![500px-Red-black_tree_example.svg.png](https://s3.amazonaws.com/mimirplatform.production/files/1f173bcd-00a3-4581-88f0-f82d243d789f/500px-Red-black_tree_example.svg.png)
A Red Black Tree is a type of self-balancing binary search tree (BST). A BST is a binary tree with the property that given a node contained therein, its left and right children store values less and greater than it respectively. This allows for, on average, logarithmic time complexity of searches. BSTs can, as has been discussed in class, become unbalanced when subject to certain sequences of insertions or removals. A self balancing BST seeks to remedy this issue by ensuring that given a node, its left and right branches are of relatively equal size. A Red Black tree ensures this balance by assigning a color (red or black) to each node and applying rules to the ways in which these colors are distributed. These rules are as follows:
1. Each node must be either Red or Black.
2. The root of the tree must always be Black.
3. A Red node must always have a Black parent node, and a Black child node (as shown above, null nodes are assumed to be Black).
4. Every path from the root of the tree to a null pointer must pass through the <span style="text-decoration: underline;">same number</span> of black nodes.
The method by which these rules maintain balance is best discussed in further depth than feasible in a project description, and can be readily found online. A few links, though, may be helpful.
[Here is a visualization tool](https://www.cs.usfca.edu/~galles/visualization/RedBlack.html) which is very useful for testing insertions and removals. We used this while developing the project.
[Information on static methods in python.](https://pythonbasics.org/static-method/)
[Information on python generators and yield statements.](https://realpython.com/introduction-to-python-generators/#building-generators-with-generator-expressions) (This is more than you need to use for this project.)
[Here is some information](https://www.geeksforgeeks.org/red-black-tree-vs-avl-tree/) on the differences between Red Black trees and AVL trees, which this project was based on in previous semesters.
Assignment Notes
IMPORTANT: Don't create new objects without good reason. Never in the course of this project should one create a new tree, and new nodes should only be created within insert(). Doing so in other situations is very likey to violate complexity requirements, and never necessary.
Remember to write docstrings. Project 1 provides examples of how they should be written. Docstrings should include a description of the function they pertain to, its parameters, and its return type.
An RBtree is strictly typed, and will not contain mismatched types. However, the structure should be type agnostic and able to contain any standard type.
Several of the method implemented are static methods - the reason for this is that while they are members of the RBtree class, they act only on the RBnode class, and are not called on an RBtree . I.e. rather than calling on `self` (an RBtree instance) with `self.get_uncle(node)`, one would call the function `RBtree.get_uncle(node)`.
The methods below are given in a suggested logical order of implementation.
IT IS HIGHLY RECOMMENDED YOU REFER TO THE SECTIONS OF ZYBOOKS RELEVANT TO THE PROJECT BEFORE AND DURING IMPLEMENTATION!
remove() and prepare_removal() are large functions. Consider ways in which one may divide it into multiple functions (hint: look at zybooks).
As the above note should indicate, feel free to implement helper functions as necessary- as long as they obey time and space complexity requirements.
For traversals, use of recursion is highly recommended.
This project will not have an application problem due to the complexity and difficulty of implemeting Red Black trees. With that said, <span style="text-decoration: underline;">_make sure you start this project early._</span>
Types:
T : Generic Type
RBnode : Described below
Assignment Specifications
# class RBnode:
This class describes the nodes contained in an RBtree .
_DO NOT MODIFY this class_
Attributes
value : Value contained in a node. Is also used as a key insertion, removal, and other pertinent operations.
is_red: Boolean identifier for node color (if it is not red, it is black)
parent: Parent of the node
left: Left child of the node
right: Right child of the node
__init__ (self, value, is_red=True, parent=None, left=None, right=None)
val : T
is_red : bool
parent : RBnode
left : RBnode
right : RBnode
Instantiates an RBnode , assigning its member variables.
return: None
_Time Complexity: O(1)_
__eq__ (self, other)
other : RBnode
Assesses equality of data contained in a node, checking both value and is_red
return: bool
_Time Complexity: O(1)_
__str__ (self)
Representation of val and is_red as a string
return: str
_Time Complexity: O(1)_
__repr__ (self)
Representation as a string utilizing __str__
return: str
_Time Complexity: O(1)_
subtree_size (self)
Size of a subtree rooted at _self_
return: int
_Time Complexity: O(n)_
subtree_size (self)
Height of a subtree rooted at _self_
return: int
_Time Complexity: O(n)_
subtree_red_black_property (self)
Determines whether the subtree rooted at _self_ adheres to Red Black properties
return: bool
_Time Complexity: O(n)_
# class RBtree:
_DO NOT MODIFY the following attributes/functions_
Attributes
root : root of an RBtree , of type RBnode
size : number of nodes contained in the tree
__init__ (self, root=None)
root : RBnode
Instantiates an RBtree , creating a deepcopy of the subtree rooted at a provided node. This provided node defaults to None .
Size is assigned based on the described subtree.
_Time Complexity: O(n) -_ where _n _is the size of the rooted subtree provided
__eq__ (self, other)
other : RBtree
Determines equality between RBtree instances.
return: bool
_Time Complexity: O(min(N, M)) --> M is size of other _
__str__ (self)
Represents the RBtree as a string, for use in debugging
return: str
_Time Complexity: O(N)_
__repr__ (self)
Represents the list as a string utilizing __str__
return: str
_Time Complexity: O(N)_
_IMPLEMENT the following functions_
set_child (parent, child, is_left) --> static method
parent : RBnode
child : RBnode
is_left : bool
Sets the childparameter of _parent _to _child_. Which child is determined by the identifier _is_left. _The parent parameter of the new child node should be updated as required.
return: None
_Time Complexity: O(1), Space Complexity: O(1)_
replace_child (parent, current_child, new_child) --> static method
parent : RBnode
current_child : RBnode
new_child : RBnode
Replaces parent 's child current_child with new_child .
return: None
_Time Complexity: O(1), Space Complexity: O(1)_
get_sibling (node) --> static method
node : RBnode
Given a node, returns the other child of that node's parent, or None should no parent exist.
_Time Complexity: O(1), Space Complexity: O(1)_
get_uncle (node) --> static method
node : RBnode
Given a node, returns the sibling of that node's parent, or None should no such node exist.
_Time Complexity: O(1), Space Complexity: O(1)_
get_grandparent (node) --> static method
node : RBnode
Given a node, returns the parent of that node's parent, or None should no such node exist.
_Time Complexity: O(1), Space Complexity: O(1)_
left_rotate (self, node)
node : RBnode
Performs a left tree rotation on the subtree rooted at _node_.
return: None
_Time Complexity: O(1), Space Complexity: O(1)_
right_rotate (self, node)
node : RBnode
Performs a right tree rotation on the subtree rooted at _node._
return: None
_Time Complexity: O(1), Space Complexity: O(1)_
insertion_repair (self, node)
node : RBnode
This method is not tested explicitly, but should be called after insertion on the node which was inserted, and should rebalance the tree by ensuring adherance to Red/Black properties.
It is highly recommended you utilize recursion.
return: None
_Time Complexity: O(log(n)), Space Complexity: O(1)_
prepare_removal (self, node)
node : RBnode
This method is not tested explicitly, but should be called prior to removal, on a node that is to be removed. It should ensure balance is maintained after the removal.
return: None
_Time Complexity: O(log(n)), Space Complexity: O(1)_
insert (self, node, val)
node: RBnode
val: Type T
Inserts an RBnode object to the subtree rooted at _node_ with value _val_.
Should a node with value _val_ already exist in the tree, do nothing.
It is _highly recommended _you implement this function recursively. To do so non-recursively will be significantly harder, and we won't assist you in doing so in the helproom or on piazza.
return: None
_Time Complexity: O(log(n)), Space Complexity: O(1)_
search (self, node, val)
node: RBnode
val: Type T
Searches the subtree rooted at _node_ for a node containing value _val. _If such a node exists, return that node- otherwise return the node which would be parent to a node with value _val_ should such a node be inserted.
This is probably best to implement recursively, but not required.
_Time Complexity: O(log(n)), Space Complexity: O(1)_
min (self, node)
node: RBnode
Returns the minimum value stored in the subtree rooted at _node_. ( None if the subtree is empty).
_Time Complexity: O(log(n)), Space Complexity: O(1)_
max (self, node)
node: RBnode
Returns the maximum value stored in a subtree rooted at _node_. ( None if the subtree is empty).
_Time Complexity: O(log(n)), Space Complexity: O(1)_
inorder (self, node)
node: RBnode
Returns a _generator_ object describing an inorder traversal of the subtree rooted at _node._
Points will be deducted if the return of this function is not a generator object (hint: yield and yield from )
_Time Complexity: O(n), Space Complexity: O(n)_
preorder (self, node)
node: RBnode
Returns a _generator_ object describing a preorder traversal of the subtree rooted at _node._
Points will be deducted if the return of this function is not a generator object (hint: yield and yield from )
_Time Complexity: O(n), Space Complexity: O(n)_
postorder (self, node)
node: RBnode
Returns a _generator _object describing a postorder traversal of the subtree rooted at _node._
Points will be deducted if the return of this function is not a generator object (hint: yield and yield from )
_TIme Complexity: O(n), Space Complexity: O(n)_
bfs (self, node)
node: RBnode
Returns a _generator _object describing a breadth first traversal of the subtree rooted at _node_.
Hint: the _queue _class has been imported already, feel free to use it.
Points will be deducted if the return of this function is not a generator object (hint: yield and yield from )
_Time Complexity: O(n), Space Complexity: O(n)_
remove (self, node, val)
node: RBnode
val: Type T
Removes node with value _val _from the subtree rooted at _node_. If no such node exists, do nothing.
If the node to be removed is an internal node with two children, swap its value with that of the maximum of its left subtree, then remove the node its value was swapped to.
Using search() might be a good idea.
This function is complicated and hard, don't be afraid to ask for help. We strongly recommend referring to zybooks.
Note this function uses inorder traversals for testing, so your tests will not pass if the in order traversal function is not completed.
return: None
_Time Complexity: O(log(n)), Space Complexity: O(1)_
Submission
Deliverables
Be sure to upload the following deliverables in a .zip folder to Mimir by 8:00p Eastern Time on Thursday, 10/22/20.
Project3.zip
|— Project3/
|— README.md (for project feedback)
|— __init__.py (for proper Mimir testcase loading)
|— RBtree.py (contains your solution source code) |— RBnode.py (supports RBtree.py)
Grading
Tests (70)
Tests: __/70
Manual (30)
Time Complexity: __/14
set_child, replace_child, get_sibling, get_uncle, get_grandparent, min, max, search (0.5 each)
inorder, preorder, postorder, bfs, left_rotate, right_rotate (1 each)
insert, remove (2 each)
Space Complexity: __/14
set_child, replace_child, get_sibling, get_uncle, get_grandparent, min, max, search (0.5 each)
inorder, preorder, postorder, bfs, left_rotate, right_rotate (1 each)
insert, remove (2 each)
README.md is _completely_ filled out with (1) Name, (2) Feedback, (3) Time to Completion and (4) Citations: __/2
Project designed by Andrew Haas and Ian Barber