diff --git a/README.md b/README.md index e8a86807c0..e968e698f6 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Topics: * Doubly Linked Lists * Binary Search Trees * Heaps - +/comment Stretch Goals: * Generic Heaps * AVL Trees diff --git a/binary_search_tree/binary_search_tree.py b/binary_search_tree/binary_search_tree.py index 1032c6b97d..df079c0f39 100644 --- a/binary_search_tree/binary_search_tree.py +++ b/binary_search_tree/binary_search_tree.py @@ -1,17 +1,68 @@ class BinarySearchTree: - def __init__(self, value): - self.value = value - self.left = None - self.right = None + def __init__(self, value): + self.value = value + self.left = None + self.right = None - def insert(self, value): - pass + def insert(self, value): + if value < self.value: + if not self.left: + self.left = BinarySearchTree(value) + else: + self.left.insert(value) + else: + if not self.right: + self.right = BinarySearchTree(value) + else: + self.right.insert(value) - def contains(self, target): - pass + def contains(self, target): + current_node = self - def get_max(self): - pass + while current_node is not None: + if target == current_node.value: + return True + elif current_node.left is None and current_node.right is None: + break + elif target < current_node.value: + current_node = current_node.left + print(current_node) + current_node.contains(target) + elif target > current_node.value: + current_node = current_node.right + print(current_node) + current_node.contains(target) + return False - def for_each(self, cb): - pass \ No newline at end of file + def get_max(self): + + max_value = self.value + current_node = self + while current_node: + if current_node.left is None and current_node.right is None: + break + elif current_node.right.value > max_value: + max_value = current_node.right.value + current_node = current_node.right + return current_node.get_max() + else: + current_node = current_node.right + return current_node.get_max() + + return max_value + + def for_each(self, cb): + + current_node = self + left_node = self.left + right_node = self.right + cb(self.value) + if left_node is None and right_node is None: + return + elif left_node and right_node: + left_node.for_each(cb) + right_node.for_each(cb) + elif left_node is not None and right_node is None: + left_node.for_each(cb) + elif right_node is not None and left_node is None: + right_node.for_each(cb) diff --git a/doubly_linked_list/doubly_linked_list.py b/doubly_linked_list/doubly_linked_list.py index 597c076eb3..7df958b8c8 100644 --- a/doubly_linked_list/doubly_linked_list.py +++ b/doubly_linked_list/doubly_linked_list.py @@ -1,68 +1,154 @@ -"""Each ListNode holds a reference to its previous node -as well as its next node in the List.""" class ListNode: - def __init__(self, value, prev=None, next=None): - self.value = value - self.prev = prev - self.next = next + def __init__(self, value, prev=None, next=None): + self.value = value + self.prev = prev + self.next = next - """Wrap the given value in a ListNode and insert it + """Wrap the given value in a ListNode and insert it after this node. Note that this node could already have a next node it is point to.""" - def insert_after(self, value): - current_next = self.next - self.next = ListNode(value, self, current_next) - if current_next: - current_next.prev = self.next - """Wrap the given value in a ListNode and insert it + def get_value(self): + return self.value + + def insert_after(self, value): + current_next = self.next + self.next = ListNode(value, self, current_next) + if current_next: + current_next.prev = self.next + + """Wrap the given value in a ListNode and insert it before this node. Note that this node could already have a previous node it is point to.""" - def insert_before(self, value): - current_prev = self.prev - self.prev = ListNode(value, current_prev, self) - if current_prev: - current_prev.next = self.prev - """Rearranges this ListNode's previous and next pointers + def insert_before(self, value): + current_prev = self.prev + self.prev = ListNode(value, current_prev, self) + if current_prev: + current_prev.next = self.prev + + """Rearranges this ListNode's previous and next pointers accordingly, effectively deleting this ListNode.""" - def delete(self): - if self.prev: - self.prev.next = self.next - if self.next: - self.next.prev = self.prev + + def delete(self): + if self.prev: + self.prev.next = self.next + if self.next: + self.next.prev = self.prev + """Our doubly-linked list class. It holds references to the list's head and tail nodes.""" + + class DoublyLinkedList: - def __init__(self, node=None): - self.head = node - self.tail = node - self.length = 1 if node is not None else 0 + def __init__(self, node=None): + self.head = node + self.tail = node + self.length = 1 if node is not None else 0 + + def __len__(self): + return self.length + + def add_to_head(self, value): + new_node = ListNode(value) + if not self.head and not self.tail: + self.head = new_node + self.tail = new_node + self.length += 1 + else: + self.head.insert_before(value) + self.head = self.head.prev + self.length += 1 + + def remove_from_head(self): + if self.head == self.tail: + deleted_value = self.head.value + self.head = None + self.tail = None + self.length -= 1 + return deleted_value + else: + deleted_value = self.head.value + self.head = self.head.next + self.head.prev = None + self.length -= 1 + return deleted_value + + def add_to_tail(self, value): + new_node = ListNode(value) + + if not self.head and not self.tail: + self.head = new_node + self.tail = new_node + self.length += 1 + else: + self.tail.insert_after(value) + self.tail = self.tail.next + self.tail.next = None + self.length += 1 + + def remove_from_tail(self): + if self.head == self.tail: + deleted_value = self.tail.value + self.head = None + self.tail = None + self.length -= 1 + return deleted_value + else: + deleted_value = self.tail.value + self.tail = self.tail.prev + self.tail = None + self.length -= 1 + return deleted_value + + def move_to_front(self, node): + self.add_to_head(node.value) + node.delete() + self.length -= 1 + + def move_to_end(self, node): + if node.value == self.head: + self.add_to_tail(node.value) + self.remove_from_head() + + else: + self.add_to_tail(node.value) + self.remove_from_head() - def __len__(self): - return self.length + def delete(self, node): + if node.prev is None: + self.remove_from_head() + elif node.next is None: + self.remove_from_tail() + else: + self.delete(node) + self.length -= 1 - def add_to_head(self, value): - pass + def get_max(self): + max_value = self.head.value + if self.length == 1 and self.head == self.tail: + return self.head.value + elif self.length > 1: + current_node = self.head + while current_node is not None: + if current_node.next is None: + break + elif current_node.next.value > max_value: + max_value = current_node.next.value + current_node = current_node.next + else: + return 0 - def remove_from_head(self): - pass + return max_value - def add_to_tail(self, value): - pass - def remove_from_tail(self): - pass +dblList = DoublyLinkedList() - def move_to_front(self, node): - pass +dblList.add_to_head(2) +dblList.add_to_head(55) +dblList.add_to_head(60) +dblList.add_to_tail(30) - def move_to_end(self, node): - pass - def delete(self, node): - pass - - def get_max(self): - pass +print(dblList.get_max()) diff --git a/heap/max_heap.py b/heap/max_heap.py index df4baba780..890c46b54c 100644 --- a/heap/max_heap.py +++ b/heap/max_heap.py @@ -1,21 +1,27 @@ class Heap: - def __init__(self): - self.storage = [] + def __init__(self): + self.storage = [] - def insert(self, value): - pass + def insert(self, value): + pass - def delete(self): - pass + def delete(self): + pass - def get_max(self): - pass + def get_max(self): + pass - def get_size(self): - pass + def get_size(self): + pass - def _bubble_up(self, index): - pass + def _bubble_up(self, index): + while index > 0: + parent = (index-1) // 2 + if self.storage[index] > self.storage[parent]: + self.storage[index], self.storage[parent] = self.storage[parent], self.storage[index] + index = parent + else: + break - def _sift_down(self, index): - pass + def _sift_down(self, index): + pass diff --git a/queue/linked_list.py b/queue/linked_list.py new file mode 100644 index 0000000000..1c0498a859 --- /dev/null +++ b/queue/linked_list.py @@ -0,0 +1,59 @@ +class Node: + def __init__(self, value, next_node=None): + self.value = value + self.next_node = next_node + + def get_value(self): + return self.value + + def get_next(self): + return self.next_node + + def set_next(self, new_next): + self.next_node = new_next + + +class LinkedList: + def __init__(self): + self.head = None + self.tail = None + + def add_to_tail(self, value): + new_node = Node(value) + + if not self.head and not self.tail: + self.head = new_node + self.tail = new_node + else: + self.tail.set_next(new_node) + self.tail = new_node + + def remove_head(self): + + if not self.head and not self.tail: + return None + + if self.head == self.tail: + old_head = self.head + self.head = None + self.tail = None + + return old_head.get_value() + else: + old_head = self.head + self.head = self.head.get_next() + return old_head.get_value() + + def contain(self, value): + if not self.head and not self.tail: + return None + + current = self.head + + while current: + if current.get_value() == value: + return True + + current = current.get_next() + + return False diff --git a/queue/queue.py b/queue/queue.py index 3bdcfe92b7..8406319646 100644 --- a/queue/queue.py +++ b/queue/queue.py @@ -1,15 +1,33 @@ +from linked_list import LinkedList + + class Queue: - def __init__(self): - self.size = 0 - # what data structure should we - # use to store queue elements? - self.storage = - - def enqueue(self, item): - pass - - def dequeue(self): - pass - - def len(self): - pass + def __init__(self): + self.size = 0 + # what data structure should we + # use to store queue elements? + self.storage = LinkedList() + + def enqueue(self, item): + self.storage.add_to_tail(item) + return self.storage.tail.get_value() + + def dequeue(self): + return f"{self.storage.head.get_value()} was removed" + return self.storage.remove_head() + + def len(self): + self.size = 0 + if not self.storage.head and not self.storage.tail: + return 0 + + if self.storage.head == self.storage.tail: + return 1 + + current_value = self.storage.head + + while current_value: + self.size += 1 + current_value = current_value.get_next() + + return self.size