Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
A
algo-bsc
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Package registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Vuillemot Romain
algo-bsc
Commits
164b7d6c
Commit
164b7d6c
authored
Oct 24, 2023
by
Romain Vuillemot
Browse files
Options
Downloads
Patches
Plain Diff
solution from class
parent
eda423c8
No related branches found
No related tags found
No related merge requests found
Changes
3
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
lectures/10-trees slides.pdf
+0
-0
0 additions, 0 deletions
lectures/10-trees slides.pdf
notebooks/08-binary-trees.ipynb
+1
-8
1 addition, 8 deletions
notebooks/08-binary-trees.ipynb
notebooks/10-trees.ipynb
+832
-0
832 additions, 0 deletions
notebooks/10-trees.ipynb
with
833 additions
and
8 deletions
lectures/10-trees slides.pdf
+
0
−
0
View file @
164b7d6c
No preview for this file type
This diff is collapsed.
Click to expand it.
notebooks/08-binary-trees.ipynb
+
1
−
8
View file @
164b7d6c
...
...
@@ -1004,7 +1004,7 @@
},
{
"cell_type": "code",
"execution_count": 2
77
,
"execution_count": 2
96
,
"id": "3a064bfb",
"metadata": {},
"outputs": [],
...
...
@@ -1013,25 +1013,18 @@
"from IPython.display import display\n",
"\n",
"def draw_binary_tree(tree_dict):\n",
" # Create a new graph\n",
" dot = Digraph(format='png')\n",
" \n",
" # Recursive function to add nodes and edges\n",
" def add_nodes_and_edges(node, parent_name=None):\n",
" if isinstance(node, dict):\n",
" for key, value in node.items():\n",
" # Add the node\n",
" dot.node(key, key)\n",
" # Add the edge to the parent (if it exists)\n",
" if parent_name:\n",
" dot.edge(parent_name, key)\n",
" # Recursively call the function for the children\n",
" add_nodes_and_edges(value, key)\n",
"\n",
" # Call the function to build the tree\n",
" add_nodes_and_edges(tree_dict)\n",
" \n",
" # Display the graph in the notebook\n",
" display(dot)"
]
},
...
...
%% Cell type:markdown id:09fc003e tags:
# UE5 Fundamentals of Algorithms
## Lecture 8: Binary trees
### Ecole Centrale de Lyon, Bachelor of Science in Data Science for Responsible Business
#### Romain Vuillemot
<center><img
src=
"figures/Logo_ECL.png"
style=
"width:300px"
></center>
%% Cell type:markdown id:74743087 tags:
---
%% Cell type:markdown id:f3ebe7d2 tags:
## Outline
-
Definitions
-
Data structures
-
Basic operations
-
Properties
%% Cell type:markdown id:a4973a08 tags:
## Definitions
> Tree is a hierarchical data structure with nodes connected by edges
-
A non-linear data structures (multiple ways to traverse it)
-
Nodes are connected by only one path (a series of edges) so trees have no cycle
-
Edges are also called links, they can be traversed in both ways (no orientation)
We focus on _binary trees._
> Trees that have at most two children
-
Children can be ordered left child and the right child
%% Cell type:markdown id:28bb09dc tags:
## Binary trees representation
Trees are most commonly represented as a node-lin diagram, with the root at the top and the leaves (nodes without children) at the bottom).
%% Cell type:code id:51f0cf57 tags:
```
python
draw_binary_tree
(
binary_tree
)
```
%% Output
%% Cell type:markdown id:55e54f01 tags:
## Binary trees data structures
Binary trees can be stored in multiple ways
-
The first element is the value of the node.
-
The second element is the left subtree.
-
The third element is the right subtree.
Here are examples:
-
Adjacency list
`T = {'A': ['B', 'C']}`
-
Arrays
`["A", "B"]`
-
Class / Object-oriented programming
`Class Node()`
Other are possible: using linked list, modules, etc.
Adjacency lists are the most common ways and can be achieved in multiple fashions.
%% Cell type:markdown id:30faa950 tags:
## Binary trees data structures (dictionnaries and lists)
_Binary trees using dictionnaries where nodes are keys and edges are Lists._
%% Cell type:code id:d495c8a5 tags:
```
python
T
=
{
'
A
'
:
[
'
B
'
,
'
C
'
],
'
B
'
:
[
'
D
'
,
'
E
'
],
'
C
'
:
[],
'
D
'
:
[],
'
E
'
:
[]
}
```
%% Cell type:markdown id:b2b2c183 tags:
## Using OOP
%% Cell type:code id:5df1c518 tags:
```
python
class
Node
:
def
__init__
(
self
,
value
):
self
.
value
=
value
self
.
left
=
None
self
.
right
=
None
def
get_value
(
self
):
return
self
.
value
def
set_value
(
self
,
v
=
None
):
self
.
value
=
v
```
%% Cell type:code id:abc855b1 tags:
```
python
root
=
Node
(
4
)
root
.
left
=
Node
(
2
)
root
.
right
=
Node
(
5
)
root
.
left
.
left
=
Node
(
1
)
root
.
left
.
right
=
Node
(
3
)
```
%% Cell type:markdown id:8b8ec2a0 tags:
## Definitions on binary trees
`Nodes`
- a tree is composed of nodes that contain a
`value`
and
`children`
.
`Edges`
- are the connections between nodes; nodes may contain a value.
`Root`
- the topmost node in a tree; there can only be one root.
`Parent and child`
- each node has a single parent and up to two children.
`Leaf`
- no node below that node.
`Depth`
- the number of edges on the path from the root to that node.
`Height`
- maximum depth in a tree.
%% Cell type:markdown id:b0bb3608 tags:
# Basic operations
%% Cell type:markdown id:8726ff36 tags:
### Get the root of a tree
_Return the topmost node in a tree (there can only be one root)._
%% Cell type:code id:1fbb1c2f tags:
```
python
def
get_root
(
T
):
if
(
len
(
T
.
keys
())
>
0
):
return
list
(
T
.
keys
())[
0
]
else
:
return
-
1
```
%% Cell type:code id:6b4492dc tags:
```
python
get_root
(
T
)
```
%% Output
'A'
%% Cell type:code id:ea01e802 tags:
```
python
assert
get_root
({})
==
-
1
assert
get_root
({
"
A
"
:
[]})
==
"
A
"
assert
isinstance
(
get_root
({
"
A
"
:
[]}),
str
)
# to make sure there is only 1 root (eg not a list)
```
%% Cell type:markdown id:3ffffeda tags:
### Get the list of nodes
_Return all the nodes in the tree (as a list of nodes names)._
%% Cell type:code id:3af082b7 tags:
```
python
def
get_nodes
(
T
):
return
list
(
T
.
keys
())
```
%% Cell type:code id:ede5b5f4 tags:
```
python
get_nodes
(
T
)
```
%% Output
['A', 'B', 'C', 'D', 'E']
%% Cell type:code id:2d3305d5 tags:
```
python
assert
get_nodes
(
T
)
==
[
'
A
'
,
'
B
'
,
'
C
'
,
'
D
'
,
'
E
'
]
assert
get_nodes
({})
==
[]
```
%% Cell type:markdown id:db9c925d tags:
### Get the list of edges
_Return all the edges as a list of pairs as `Tuple`._
%% Cell type:code id:b50fe9c2 tags:
```
python
def
get_edges
(
graph
):
edges
=
[]
for
node
,
neighbors
in
graph
.
items
():
for
neighbor
in
neighbors
:
edges
.
append
((
node
,
neighbor
))
return
edges
```
%% Cell type:code id:8958bd83 tags:
```
python
get_edges
(
T
)
```
%% Output
[('A', 'B'), ('A', 'C'), ('B', 'D'), ('B', 'E')]
%% Cell type:code id:30dd31d3 tags:
```
python
assert
get_edges
(
T
)
==
[(
'
A
'
,
'
B
'
),
(
'
A
'
,
'
C
'
),
(
'
B
'
,
'
D
'
),
(
'
B
'
,
'
E
'
)]
assert
get_edges
({})
==
[]
```
%% Cell type:markdown id:95accba5 tags:
### Get the parent of a node
_Return the parent node of a given node (and -1 if the root)._
%% Cell type:code id:37fbe31b tags:
```
python
def
get_parent
(
graph
,
node_to_find
):
for
parent
,
neighbors
in
graph
.
items
():
if
node_to_find
in
neighbors
:
return
parent
return
None
```
%% Cell type:code id:78e88d23 tags:
```
python
assert
get_parent
(
T
,
'
D
'
)
==
'
B
'
assert
get_parent
(
T
,
'
A
'
)
is
None
assert
get_parent
({},
''
)
is
None
```
%% Cell type:markdown id:3fb6f347 tags:
### Check if the node is the root
_Return True if the root not, else
`None`
.
%% Cell type:code id:164e4ef7 tags:
```
python
def
is_root
(
T
,
node
):
return
find_parent
(
T
,
node
)
is
None
```
%% Cell type:code id:5c053617 tags:
```
python
assert
is_root
(
T
,
'
A
'
)
==
True
```
%% Cell type:markdown id:bba64730 tags:
### Get the children of a node
_Given a node, return all its children as a `List`._
%% Cell type:code id:ac145c20 tags:
```
python
def
find_children
(
graph
,
parent_node
):
children
=
graph
.
get
(
parent_node
,
[])
return
children
```
%% Cell type:code id:9444a66f tags:
```
python
assert
find_children
(
T
,
'
A
'
)
==
[
'
B
'
,
'
C
'
]
assert
find_children
(
T
,
'
B
'
)
==
[
'
D
'
,
'
E
'
]
assert
find_children
(
T
,
'
C
'
)
==
[]
```
%% Cell type:markdown id:6f600f3d tags:
### Check if the node is a leaf
_Return `True` if the node has no children._
%% Cell type:code id:77f5f17c tags:
```
python
def
is_leaf
(
T
,
node
):
return
len
(
find_children
(
T
,
node
))
==
0
```
%% Cell type:code id:5f5078d6 tags:
```
python
assert
is_leaf
(
T
,
'
C
'
)
assert
not
is_leaf
(
T
,
'
A
'
)
```
%% Cell type:markdown id:a41e666e tags:
### Add/Delete a node
_Given a tree as input._
-
Add a node to given a current partent
-
Remove a given node
%% Cell type:code id:c9312a43 tags:
```
python
def
add_node
(
graph
,
parent
,
new_node
):
if
parent
in
graph
:
graph
[
parent
].
append
(
new_node
)
else
:
graph
[
parent
]
=
[
new_node
]
def
delete_node
(
graph
,
node_to_delete
):
for
parent
,
children
in
graph
.
items
():
if
node_to_delete
in
children
:
children
.
remove
(
node_to_delete
)
if
not
children
:
del
graph
[
parent
]
```
%% Cell type:code id:38181a0f tags:
```
python
U
=
{
"
A
"
:
[]}
add_node
(
U
,
"
A
"
,
'
F
'
)
U
```
%% Cell type:markdown id:4885c320 tags:
### Height of a tree
_Calculate the longest path from the root to leaves. Tip: use a recursive approach_
-
if the node is a leaf, return 1
-
for a current node, the height is the max height of its children + 1
%% Cell type:code id:ee2973b7 tags:
```
python
T
```
%% Output
{'A': ['B', 'C'], 'B': ['D', 'E'], 'C': [], 'D': [], 'E': []}
%% Cell type:code id:b7ef1fab tags:
```
python
v
```
%% Cell type:code id:6ef9af29 tags:
```
python
def
height
(
T
,
node
):
if
node
not
in
T
:
return
0
# leaf
children
=
T
[
node
]
if
not
children
:
return
1
# leaf
list_heights
=
[]
for
child
in
children
:
list_heights
.
append
(
height
(
T
,
child
))
return
1
+
max
(
list_heights
)
```
%% Cell type:code id:44a54ec8 tags:
```
python
assert
height
(
T
,
'
A
'
)
==
3
assert
height
(
T
,
'
B
'
)
==
2
assert
height
(
T
,
'
C
'
)
==
1
```
%% Cell type:markdown id:e35608be tags:
## Height of a binary tree
<img
src=
"figures/hauteur-arbre.png"
style=
"width: 400px"
>
$n = 2^{(h+1)} - 1$
$n + 1 = 2^{(h+1)}$
$log(n + 1) = log(2^{(h+1)})$
$log(n + 1) = (h+1) log(2)$
$log(n + 1) / log(2) = h + 1$
so $h = log(n + 1) / log(2) - 1$
$h$ is equivalent to $log(n)$
%% Cell type:markdown id:94f34cf8 tags:
## Binary trees (using Arrays)
<img
src=
"figures/arbre-tableau.png"
style=
"width: 400px"
>
In a complete or balanced binary tree:
-
if the index of a node is equal to $i$, then the position indicating its left child is at $2i$,
-
and the position indicating its right child is at $2i + 1$.
%% Cell type:markdown id:8afab007 tags:
## Visualize a tree
%% Cell type:code id:610ad3bb 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
```
%% Output
<graphviz.graphs.Digraph at 0x104c32b30>
%% Cell type:markdown id:01880f1d tags:
## Visualize a tree
%% Cell type:code id:3a064bfb tags:
```
python
from
graphviz
import
Digraph
from
IPython.display
import
display
def
draw_binary_tree
(
tree_dict
):
# Create a new graph
dot
=
Digraph
(
format
=
'
png
'
)
# Recursive function to add nodes and edges
def
add_nodes_and_edges
(
node
,
parent_name
=
None
):
if
isinstance
(
node
,
dict
):
for
key
,
value
in
node
.
items
():
# Add the node
dot
.
node
(
key
,
key
)
# Add the edge to the parent (if it exists)
if
parent_name
:
dot
.
edge
(
parent_name
,
key
)
# Recursively call the function for the children
add_nodes_and_edges
(
value
,
key
)
# Call the function to build the tree
add_nodes_and_edges
(
tree_dict
)
# Display the graph in the notebook
display
(
dot
)
```
%% Cell type:code id:cb7726ee tags:
```
python
```
...
...
This diff is collapsed.
Click to expand it.
notebooks/10-trees.ipynb
0 → 100644
+
832
−
0
View file @
164b7d6c
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment