Update test cases and sample code for 2026.05.27 homework

This commit is contained in:
2026-06-11 11:45:17 -04:00
parent e2dcba1600
commit 0fd98a46ca
4 changed files with 78 additions and 13 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.idea

View File

@@ -60,8 +60,12 @@ def rotate_left(node: Node) -> Node:
new_right_child = node.right.left new_right_child = node.right.left
node.right = new_right_child node.right = new_right_child
node.parent = new_parent if new_right_child is not None:
new_right_child.parent = node
new_parent.left = node new_parent.left = node
node.parent = new_parent
new_parent.parent = original_parent
if original_parent is not None: if original_parent is not None:
if original_parent.left == node: if original_parent.left == node:
@@ -81,8 +85,12 @@ def rotate_right(node: Node) -> Node:
new_left_child = node.left.right new_left_child = node.left.right
node.left = new_left_child node.left = new_left_child
node.parent = new_parent if new_left_child is not None:
new_left_child.parent = node
new_parent.right = node new_parent.right = node
node.parent = new_parent
new_parent.parent = original_parent
if original_parent is not None: if original_parent is not None:
if original_parent.left == node: if original_parent.left == node:
@@ -115,48 +123,86 @@ def trees_equal(a: Node | None, b: Node | None) -> bool:
if __name__ == "__main__": if __name__ == "__main__":
# note that matching is done by value for simplicity here
def test_rotate_right_example(): def test_rotate_right_example():
# The worksheet example: right rotate on 10. # The worksheet example: right rotate on 10.
root = Node( root = Node(
10, 10,
left=Node(5, left=Node(3, left=Node(2)), right=Node(7)), left=Node(
right=Node(15), 5,
left=Node(3, left=Node(2, parent=Node(3)), parent=Node(5)),
right=Node(7, parent=Node(5)),
parent=Node(10),
),
right=Node(15, parent=Node(10)),
) )
expected = Node( expected = Node(
5, 5,
left=Node(3, left=Node(2)), left=Node(3, left=Node(2, parent=Node(3)), parent=Node(5)),
right=Node(10, left=Node(7), right=Node(15)), right=Node(
10,
left=Node(7, parent=Node(10)),
right=Node(15, parent=Node(10)),
parent=Node(5),
),
) )
return rotate_right(root), expected return rotate_right(root), expected
def test_rotate_left_example(): def test_rotate_left_example():
# The worksheet example: left rotate on 16. # The worksheet example: left rotate on 16.
root = Node(16, right=Node(33, left=Node(22), right=Node(55))) root = Node(
expected = Node(33, left=Node(16, right=Node(22)), right=Node(55)) 16,
right=Node(
33,
left=Node(22, parent=Node(33)),
right=Node(55, parent=Node(33)),
parent=Node(16),
),
)
expected = Node(
33,
left=Node(16, right=Node(22, parent=Node(16)), parent=Node(33)),
right=Node(55, parent=Node(33)),
)
return rotate_left(root), expected return rotate_left(root), expected
def test_rotate_right_two_nodes(): def test_rotate_right_two_nodes():
# Smallest case: a root with only a left child. # Smallest case: a root with only a left child.
return rotate_right(Node(2, left=Node(1))), Node(1, right=Node(2)) return rotate_right(Node(2, left=Node(1, parent=Node(2)))), Node(1, right=Node(2, parent=Node(1)))
def test_rotate_left_two_nodes(): def test_rotate_left_two_nodes():
# Smallest case: a root with only a right child. # Smallest case: a root with only a right child.
return rotate_left(Node(1, right=Node(2))), Node(2, left=Node(1)) return rotate_left(Node(1, right=Node(2, parent=Node(1)))), Node(2, left=Node(1, parent=Node(2)))
def test_round_trip(): def test_round_trip():
# A left rotate undone by a right rotate restores the original tree. # A left rotate undone by a right rotate restores the original tree.
original = Node(1, left=Node(0), right=Node(3, left=Node(2), right=Node(4))) original = Node(1, left=Node(0, parent=Node(1)),
expected = Node(1, left=Node(0), right=Node(3, left=Node(2), right=Node(4))) right=Node(3, left=Node(2, parent=Node(3)), right=Node(4, parent=Node(3)), parent=Node(1)))
expected = Node(1, left=Node(0, parent=Node(1)),
right=Node(3, left=Node(2, parent=Node(3)), right=Node(4, parent=Node(3)), parent=Node(1)))
return rotate_right(rotate_left(original)), expected return rotate_right(rotate_left(original)), expected
def test_rotate_with_parent(): def test_rotate_with_parent():
# run it on 33 instead of the root # run it on 33 instead of the root
root = Node(16, right=Node(33, left=Node(22), right=Node(55))) root = Node(16, right=Node(33, left=Node(22), right=Node(55)))
root.right.parent = root
root.right.left.parent = root.right
root.right.right.parent = root.right
original = root.right original = root.right
expected = Node(55, left=Node(33, left=Node(22))) expected = Node(
55,
left=Node(33, left=Node(22, parent=Node(33)), parent=Node(55)),
parent=Node(16),
)
return rotate_left(original), expected # pyright: ignore[reportArgumentType] return rotate_left(original), expected # pyright: ignore[reportArgumentType]
tests = [ tests = [
("rotate_right on worksheet example (10)", test_rotate_right_example), ("rotate_right on worksheet example (10)", test_rotate_right_example),
("rotate_left on worksheet example (16)", test_rotate_left_example), ("rotate_left on worksheet example (16)", test_rotate_left_example),

View File

@@ -0,0 +1,16 @@
## Outline
- Review homework and do some tree exercises
- Introduce tree balancing
- Introduce red-black trees
- Basic properties
- Root property: the root is black
- External property: every nil child pointer is considered a black node
- Internal property: children and parents of a red node are black
- Depth property: all nodes have the same black depth
- Insertion and balancing algorithms
- Assignment: implement red-black tree balancing
## Resources
- [Red-black tree - Wikipedia](https://en.wikipedia.org/wiki/Redblack_tree)