Data Structures
Stacks, Queues, and Trees
Read about stacks and queues in Python here:
In essence, we want to use arrays for stacks as popping off the end of the array is O(1)
, while we want to use deque
from collections
to implement a queue as it has fast popping off the front and end
import timeit
from collections import deque
= 100000
num_elements
= list(range(num_elements))
test_list = deque(range(num_elements))
test_deque
def pop_front_list():
while test_list:
0)
test_list.pop(
def pop_front_deque():
while test_deque:
test_deque.popleft()
def pop_back_list():
while test_list:
test_list.pop()
def pop_back_deque():
while test_deque:
test_deque.pop()
# timing
= timeit.timeit(pop_front_list, number=1)
time_pop_front_list = timeit.timeit(pop_front_deque, number=1)
time_pop_front_deque = timeit.timeit(pop_back_list, number=1)
time_pop_back_list = timeit.timeit(pop_back_deque, number=1)
time_pop_back_deque
print(f"Time to pop all elements from the front of the list: {time_pop_front_list:.5f} seconds")
print(f"Time to pop all elements from the front of the deque: {time_pop_front_deque:.5f} seconds")
print(f"Time to pop all elements from the back of the list: {time_pop_back_list:.5f} seconds")
print(f"Time to pop all elements from the back of the deque: {time_pop_back_deque:.5f} seconds")
>>> print(f"Time to pop all elements from the front of the list: {time_pop_front_list:.5f} seconds")
Time to pop all elements from the front of the list: 0.93451 seconds
>>> print(f"Time to pop all elements from the front of the deque: {time_pop_front_deque:.5f} seconds")
Time to pop all elements from the front of the deque: 0.00246 seconds
>>> print(f"Time to pop all elements from the back of the list: {time_pop_back_list:.5f} seconds")
Time to pop all elements from the back of the list: 0.00000 seconds
>>> print(f"Time to pop all elements from the back of the deque: {time_pop_back_deque:.5f} seconds")
Time to pop all elements from the back of the deque: 0.00000 seconds
Trees are explained here:
The core of it is that a tree is implemented as a class Node
that has self.data
and self.children = []
.
class Node:
def __init__(self, data):
self.data = data
self.children = []
def add_child(self, child):
self.children.append(child)
def __repr__(self, level=0):
"""
the __repr__ method is overwritten so that when
one just prints out a tree, it's nicely formatted.
"""
= "\t"*level + repr(self.data) + "\n"
ret for child in self.children:
+= child.__repr__(level+1)
ret return ret
# Create the root node
= Node('Root')
root
# Create child nodes
= Node('Child1')
child1 = Node('Child2')
child2 = Node('Child3')
child3
# Add children to the root
root.add_child(child1)
root.add_child(child2)
# Create and add children for child1
= Node('Child1_1')
child1_1 = Node('Child1_2')
child1_2
child1.add_child(child1_1)
child1.add_child(child1_2)
# Create and add a child for child2
= Node('Child2_1')
child2_1
child2.add_child(child2_1)
# Add a single child to child3 (who is not yet connected to the tree)
= Node('Child3_1')
child3_1
child3.add_child(child3_1)
# Now let's add child3 to the root to complete the tree
root.add_child(child3)
# Print the structure of the tree
print(root)
'Root'
'Child1'
'Child1_1'
'Child1_2'
'Child2'
'Child2_1'
'Child3'
'Child3_1'
Read about red-black trees here:
And AVL trees here: