Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 102 additions & 30 deletions binary_search_tree/binary_search_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
2. Implement the `in_order_print`, `bft_print`, and `dft_print` methods
on the BSTNode class.
"""
from queue import Queue
from stack import Stack

class BSTNode:
def __init__(self, value):
self.value = value
Expand All @@ -17,46 +20,115 @@ def __init__(self, value):

# Insert the given value into the tree
def insert(self, value):
pass
if value < self.value:
if self.left == None:
self.left = BSTNode(value)
else:
self.left.insert(value)
else:
if self.right == None:
self.right = BSTNode(value)
else:
self.right.insert(value)


# Return True if the tree contains the value
# False if it does not
def contains(self, target):
pass
if self.value == target:
return True
else:
if target < self.value:
if self.left == None:
return False
else:
return self.left.contains(target)
else:
if self.right == None:
return False
else:
return self.right.contains(target)

# Return the maximum value found in the tree
def get_max(self):
pass
# if self.right == None and self.left == None:
# return None

if self.right is not None:
return self.right.get_max()
else:
return self.value


# Call the function `fn` on the value of each node
def for_each(self, fn):
pass
fn(self.value)

if self.left is not None:
self.left.for_each(fn)
if self.right is not None:
self.right.for_each(fn)

# Part 2 -----------------------

# Print all the values in order from low to high
# Hint: Use a recursive, depth first traversal
# # Print all the values in order from low to high
# # Hint: Use a recursive, depth first traversal
def in_order_print(self):
pass

# Print the value of every node, starting with the given node,
# in an iterative breadth first traversal
def bft_print(self):
pass

# Print the value of every node, starting with the given node,
# in an iterative depth first traversal
def dft_print(self):
pass

# Stretch Goals -------------------------
# Note: Research may be required

# Print Pre-order recursive DFT
# base case
# if there are no more nodes
#return
if self.left == None and self.right == None:
return

#if there is a node to the left
if self.left is not None:
# call in order print on the left
self.left.in_order_print()
# print the value of the current node (self.value)
print(self.value)
#if there is a node to the right
if self.right is not None:
# call in order print on the right
self.right.in_order_print()


# # Print the value of every node, starting with the given node,
# # in an iterative breadth first traversal
def bft_print(self): #queue
#create a queue
queue = Queue()
queue.enqueue(self)

while queue:
node = queue.dequeue()
print(node.value)
if node.left is not None:
queue.enqueue(node.left)
if node.right is not None:
queue.enqueue(node.right)

# # Print the value of every node, starting with the given node,
# # in an iterative depth first traversal
def dft_print(self): # stack
stack = Stack()
stack.push(self)

while stack:
node = stack.pop()
print(node.value)
if node.left is not None:
stack.push(node.left)
if node.right is not None:
stack.push(node.right)

# # Stretch Goals -------------------------
# # Note: Research may be required

# # Print Pre-order recursive DFT
def pre_order_dft(self):
pass

# Print Post-order recursive DFT
# # Print Post-order recursive DFT
def post_order_dft(self):
pass

Expand All @@ -76,10 +148,10 @@ def post_order_dft(self):
bst.bft_print()
bst.dft_print()

print("elegant methods")
print("pre order")
bst.pre_order_dft()
print("in order")
bst.in_order_dft()
print("post order")
bst.post_order_dft()
# print("elegant methods")
# print("pre order")
# bst.pre_order_dft()
# print("in order")
# bst.in_order_dft()
# print("post order")
# bst.post_order_dft()
37 changes: 37 additions & 0 deletions binary_search_tree/queue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""
A queue is a data structure whose primary purpose is to store and
return elements in First In First Out order.

1. Implement the Queue class using an array as the underlying storage structure.
Make sure the Queue tests pass.
2. Re-implement the Queue class, this time using the linked list implementation
as the underlying storage structure.
Make sure the Queue tests pass.
3. What is the difference between using an array vs. a linked list when
implementing a Queue?

Stretch: What if you could only use instances of your Stack class to implement the Queue?
What would that look like? How many Stacks would you need? Try it!
"""
from singly_linked_list import LinkedList

class Queue:
def __init__(self):
self.size = 0
self.storage = LinkedList()

def __len__(self):
return self.size

def enqueue(self, value):
self.storage.add_to_tail(value)
self.size += 1
return self.storage

def dequeue(self):
if self.size >= 1:
value = self.storage.remove_head()
self.size -= 1
return value
return None

115 changes: 115 additions & 0 deletions binary_search_tree/singly_linked_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
class Node:
def __init__(self, value, next_node = None):
# value that the node is holding
self.value = value
# ref to the next node in the chain
self.next_node = next_node


def get_value(self):
"""
Method to get the value of a node
"""
return self.value

def get_next(self):
"""
Method to get the node's "next_node"
"""
return self.next_node

def set_next(self, new_next):
"""
Method to update the node's "next_node" to the new_next
"""
self.next_node = new_next

class LinkedList:
def __init__(self):
self.head = None
self.tail = None
self.length = 0

def add_to_tail(self, value):
# wrap the value in a new Node
new_node = Node(value)
# check if the linked list is empty
if self.head is None and self.tail is None:
# set the head and tail to the new node
self.head = new_node
self.tail = new_node
# otherwise the list must have at least one item in there
else:
# update the last node's "next_node" to the new node
self.tail.set_next(new_node) # (last node in chain).next_node = new_node
# update the "self.tail" to point to the new node that we just added
self.tail = new_node

def add_to_head(self, value):
new_node = Node(value, self.head)
self.head = new_node
if self.length == 0:
self.tail = new_node
self.length += 1

def remove_tail(self):
"""
remove the last node in the chain and return its value
"""
# check for empty list
if self.head is None and self.tail is None:
# return None
return None
# check if there is only one node
if self.head == self.tail:
# store the value of the node that we are going to remove
value = self.tail.get_value()
# remove the node
# set head and the tail to None
self.head = None
self.tail = None
# return the stored value
return value
# otherwise
else:
# store the value of the node that we are going to remove
value = self.tail.get_value()
# we need to set the "self.tail" to the second to last node
# we can only do this by traversing the whole list from beginning to end

# starting from the head
current_node = self.head

# keep iterating until the node after "current_node" is the tail
while current_node.get_next() != self.tail:
# keep looping
current_node = current_node.get_next()

# at the end of the iteration set "self.tail" to the current_node
self.tail = current_node
# set the new tail's "next_node" to None
self.tail.set_next(None)
# return Value
return value

def remove_head(self):
# check for empty list
if self.head is None and self.tail is None:
# return None
return None
if self.head == self.tail:
# store the value of the node that we are going to remove
value = self.head.get_value()
# remove the node
# set head and the tail to None
self.head = None
self.tail = None
# return the stored value
return value
else:
# store the old head's value
value = self.head.get_value()
# set self.head to old head's next
self.head = self.head.get_next()
# return the value
return value
33 changes: 33 additions & 0 deletions binary_search_tree/stack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""
A stack is a data structure whose primary purpose is to store and
return elements in Last In First Out order.

1. Implement the Stack class using an array as the underlying storage structure.
Make sure the Stack tests pass.
2. Re-implement the Stack class, this time using the linked list implementation
as the underlying storage structure.
Make sure the Stack tests pass.
3. What is the difference between using an array vs. a linked list when
implementing a Stack?
"""
from singly_linked_list import LinkedList

class Stack:
def __init__(self):
self.size = 0
self.storage = LinkedList()

def __len__(self):
return self.size

def push(self, value):
self.storage.add_to_head(value)
self.size += 1
return self.storage

def pop(self):
if self.size > 0:
value = self.storage.remove_head()
self.size -= 1
return value
return None
Loading