Skip to content
Snippets Groups Projects
Commit fc9b329e authored by Romain Vuillemot's avatar Romain Vuillemot
Browse files

lab 7

parent afb43d01
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id:12eb2af6 tags:
NAME:
%% Cell type:markdown id:8985c402-e154-4eab-aea3-750a88318acb tags:
# UE5 Fundamentals of Algorithms
# Lab 7: Binary trees
**IMPORTANT:** make sure the graphviz library (to visualize graphs) runs in your notebooks, this can be achieved by running the following cells (if graphviz is not install run the `!pip install graphviz` command in a cell). If graphviz ultimatelly does not, then you may skip the cell with the `visualize_oop` functions.
%% Cell type:code id:1f8b2afd-8315-41fa-b5d7-7f9566332151 tags:
``` python
from graphviz import Digraph
from IPython.display import display
class Node:
def __init__(self, value, l = None, r = None):
self.value = value
self.left = l
self.right = r
def visualize_oop(root):
def build(node, dot=None):
if dot is None:
dot = Digraph(format='png')
if node is not None:
dot.node(str(node.value))
if node.left is not None:
dot.edge(str(node.value), str(node.left.value))
build(node.left, dot)
if node.right is not None:
dot.edge(str(node.value), str(node.right.value))
build(node.right, dot)
return dot
return build(root)
visualize_oop(Node(3, Node(2)))
```
%% Cell type:markdown id:7c7461c1-fe15-405b-a2c9-709e6f9c3743 tags:
---
%% Cell type:markdown id:a2428808-27d5-4d42-84b8-01632b1271dd tags:
## Exercise 1: Manipulate binary trees data structure
Here is an example of tree (using the graphviz library as data structure). Look at the result.
%% Cell type:code id:83b91119-09f7-4cba-a87b-19fc4a793e91 tags:
``` python
from graphviz import Digraph
dot = Digraph()
dot.node_attr['shape'] = 'circle'
dot.node('0', label='0') # Root
dot.node('1')
dot.node('2')
dot.node('3')
dot.node('4')
dot.node('5')
dot.edge('0', '1')
dot.edge('1', '4')
dot.edge('1', '5')
dot.edge('0', '2', color='red')
dot.edge('2', '3', color='red')
dot # Render the graph
```
%% Cell type:markdown id:1fca57f5-4b3c-4ad8-a4c0-9d1de647abf9 tags:
Use a `Dict` data structure to store the nodes and edges of the above tree.
%% Cell type:code id:fa1bce0f-7b06-4d20-8a1b-990bcd03bda9 tags:
``` python
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:cb16382b-e00d-498a-bab2-0b251f93d147 tags:
Use a `Tuple` data structure to store the nodes and edges of the above tree.
%% Cell type:code id:a4cbc1d4-5adc-4cda-9c2a-24101bd1bed9 tags:
``` python
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:483af12c-f194-4377-a0f4-56f860b6d865 tags:
Use a `List` data structure to store the nodes and edges of the above tree.
%% Cell type:code id:54f96c40-40f1-4838-9861-3f08bd828503 tags:
``` python
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:5554f67b-ba9d-4143-8082-382fd43caf0b tags:
Write code to compare the various data structure and show they store the same information.
%% Cell type:code id:b2144bf6-00d9-40c6-973e-734fad8aa949 tags:
``` python
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:e6f07240-86c1-46f7-97f1-4764328b2221 tags:
``` python
Write a function that converts a binary tree stored as a `Dict` in to a `List`.
```
%% Cell type:code id:d7976e73-44e0-4c9c-8383-3acb6f4ed284 tags:
``` python
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:cdec902d-c43c-4be2-bafe-78baac70c7ee tags:
``` python
dict_to_list(T_dict)
```
%% Cell type:code id:133cca89-39f7-43c5-8d9f-c0e7c9a89427 tags:
``` python
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:a06bc87a-dd09-4513-8d73-3f949374f158 tags:
``` python
list_to_dict(dict_to_list_of_lists(T_dict))
```
%% Cell type:markdown id:57c4ed49-f64b-4dc9-80e6-2c80269ebe90 tags:
Provide examples of conversions showing they do not lose any information.
%% Cell type:code id:16d722bc-625e-4750-96a4-f58aaab467b1 tags:
``` python
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:fb0e9336-603c-49c4-9617-9ccecdbf7156 tags:
## Exercise 2: Binary search tree (BST)
We assume we have a binary search tree (BST). Its main property is that for every node, the value of the left children is less than the value of the right children.
%% Cell type:code id:02513514-0e1b-4c0d-a5fd-ac6b571231b7 tags:
``` python
class Node:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def __str__(self):
return str(self.value)
```
%% Cell type:markdown id:055d2cea-4e45-402d-baf8-e50939c94132 tags:
Write an `insert` function inserts a value in a tree so it preserves the BST property (in an iterative way).
%% Cell type:code id:6492983d-054c-4488-b8ff-57b3878f5b7e tags:
``` python
def insert_ite(root, value):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:7c2a2f74-a8b8-4cd6-a881-9181efdb7a64 tags:
``` python
a = Node(2)
insert_ite(a, 3)
insert_ite(a, 4)
insert_ite(a, 1)
```
%% Cell type:code id:10b6d8de-fb38-41e3-92b9-957f04a6f1e4 tags:
``` python
visualize_oop(a)
```
%% Cell type:markdown id:0cb5f4e8-348d-4ab0-bdd3-1fe61a6ca687 tags:
Now in a recursive way.
%% Cell type:code id:3826d528-370f-4e29-8217-20a71947b39a tags:
``` python
def insert_rec(root, value):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:dba5b7d0-1bb6-4b46-b123-5be447b8e10c tags:
``` python
a = Node(2)
insert(a, 3)
insert(a, 4)
insert(a, 1)
```
%% Cell type:markdown id:d40d2486-c901-428a-b2e3-0004ae707376 tags:
Compare the results.
%% Cell type:code id:069fb592-4178-405b-8d8b-546bc908dc1e tags:
``` python
visualize_oop(a)
```
%% Cell type:markdown id:1608511b-df49-43fd-a946-606cf6bb57a4 tags:
Now write a function that search for a given `value` is in the BST.
%% Cell type:code id:bb343233-16f8-4441-8e18-9407611d8d10 tags:
``` python
def search(root, value):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:05aaa6a3-a57c-47b3-849f-722ee0546ab0 tags:
``` python
assert search(a, 3)
assert not search(a, 5)
```
%% Cell type:markdown id:07ca3602-96fd-43d7-b7ac-54f92124a11d tags:
## Exercise 3: Calculate properties of binary trees
%% Cell type:code id:2e65ec3d-8e90-4e25-befb-d779713fa3f2 tags:
``` python
class Node:
def __init__(self, value, l = None, r = None):
self.value = value
self.left = l
self.right = r
```
%% Cell type:markdown id:3bd05d7e-7e0c-4042-9aac-616960849de9 tags:
Calculate the height of a binary tree in a recursive way:
%% Cell type:code id:c323b9af-98f6-45d6-9ee2-cffde39a2a16 tags:
``` python
def height_rec(node):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:9527fa59-87cf-4216-a7dc-ad0aa3330d4c tags:
``` python
assert height_rec(Node(2)) == 0
assert height_rec(Node(2, Node(3))) == 1
assert height_rec(Node(2, Node(3, Node(4)))) == 2
```
%% Cell type:markdown id:7b46712d-472b-4997-90b4-acda29a17fb9 tags:
In an interative way:
%% Cell type:code id:6cd2bdcf-d4ad-4103-88ed-ced3fb45f4e8 tags:
``` python
def height_ite(root):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:dac217fa-c9db-46ca-91a3-a834c3d0aa38 tags:
``` python
assert height_ite(Node(2)) == 0
assert height_ite(Node(2, Node(3))) == 1
assert height_ite(Node(2, Node(3, Node(4)))) == 2
```
%% Cell type:markdown id:dea3b5d5-dc00-4569-9343-1735263939e6 tags:
A binary tree is considered balanced if the height of the left and right subtrees of any node differ by no more than 1. You may use the previously created `height` function.
%% Cell type:code id:d15492f9-0f52-4f1c-b782-fced561764d0 tags:
``` python
def is_balanced_rec(root):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:0d7542de-86a9-4e38-ba51-87f55d6f7909 tags:
``` python
assert is_balanced_rec(Node(2))
assert not is_balanced_rec(Node(2, Node(3, Node(4))))
```
%% Cell type:markdown id:6c613015-7ab9-48a9-9c58-a9ee0fcb8c7c tags:
## Exercise 4: Implement a (complete) binary tree using a list
%% Cell type:markdown id:0c98803c-4d6d-4c8a-b496-bcc49fa48232 tags:
We will now implement a **complete binary tree**. This binary tree will be implemented using an array (since it is a **complete** tree where all levels are filled, except possibly the last). The binary tree has nodes with an index \(i\), with a left child and a right child. The array and the tree are connected as follows:
- The root is at position $i = 0$ (this value will be returned by the function `get_root`).
- The parent is at position $\lfloor (i - 1)/ 2 \rfloor$ (function `get_parent`).
- The left child is at position $2 \times i + 1$ (function `get_left_child`).
- The right child is at position $2 \times i + 2$ (function `get_right_child`).
```
1
/ \
2 5
/ \ /
3 4 6
The corresponding list:
[1, 2, 5, 3, 4, 6]
```
%% Cell type:code id:2d989ada-2637-4610-ad82-e450bdb21909 tags:
``` python
class BinaryTree():
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:e9098c68-368f-4716-9208-819bfa7cfe10 tags:
``` python
# Test empty tree
tree_empty = BinaryTree()
assert tree_empty.size() == 0
assert tree_empty.get_root() == None
assert tree_empty.get_parent()[0] == None
assert tree_empty.get_left_child(0)[0] == None
assert tree_empty.get_right_child(0)[0] == None
```
%% Cell type:code id:c7d0d23b-b039-4015-b650-fbb700d359a8 tags:
``` python
L = [1, 2, 5, 3, 4, 6]
tree_values = BinaryTree(L)
assert tree_values.size() == len(L) # 6
assert tree_values.get_root() == L[0] # 3
assert tree_values.get_left_child(0)[0] == L[2*0+1] # 2
assert tree_values.get_right_child(0)[0] == L[2*0+2] # 5
assert tree_values.get_parent(1)[0] == L[0] # 5
```
%% Cell type:markdown id:957d18d6-3c3a-463f-8726-bad3b27a367b tags:
**BONUS Questions**
- Implement the other methods we have seen previously (get height, find values etc.)
- Compare with other data structures (`Dict`, `Tuple`, ..)
%% Cell type:code id:56066835-ae94-4faa-8c78-6a3831476cf7 tags:
``` python
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment