From cd2f7875dcdb01aefafbea9b488889dfe18c28a7 Mon Sep 17 00:00:00 2001 From: msteele11101 Date: Fri, 18 Sep 2020 10:35:56 -0700 Subject: [PATCH 1/3] Day 1 done somewhat --- queue/queue.py | 24 ++++-- singly_linked_list/singly_linked_list.py | 100 +++++++++++++++++++++++ stack/stack.py | 22 +++-- 3 files changed, 130 insertions(+), 16 deletions(-) diff --git a/queue/queue.py b/queue/queue.py index 0d2599ded7..cb1800376e 100644 --- a/queue/queue.py +++ b/queue/queue.py @@ -1,28 +1,34 @@ """ A queue is a data structure whose primary purpose is to store and -return elements in First In First Out order. - +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 +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! """ +import sys +sys.path.append('/Users/mstee/Data-Structures/singly_linked_list') +from singly_linked_list import LinkedList + class Queue: def __init__(self): self.size = 0 - # self.storage = ? - + self.storage = LinkedList() + def __len__(self): - pass + return self.size def enqueue(self, value): - pass + self.storage.add_to_tail(value) + self.size += 1 def dequeue(self): - pass + if self.size == 0: + return None + self.size -= 1 + return self.storage.remove_head() \ No newline at end of file diff --git a/singly_linked_list/singly_linked_list.py b/singly_linked_list/singly_linked_list.py index e69de29bb2..e035c824f4 100644 --- a/singly_linked_list/singly_linked_list.py +++ b/singly_linked_list/singly_linked_list.py @@ -0,0 +1,100 @@ +# TODO a class that represents the individual elements in our LL + +class Node: + def __init__(self, value=None, next_node=None): + self.value = value + self.next_node = next_node + + def get_value(self): + return self.value + + def get_next_node(self): + return self.next_node + + def set_next_node(self, new_next): + self.next_node = new_next + +class LinkedList: + def __init__(self): + # what attributes do we need? + self.head = None + self.tail = None + + def add_to_head(self, value): + new_node = Node(value) + if self.head is None: + # update head & tail attributes + self.head = new_node + self.tail = new_node + else: + # set next_node of my new Node to the head + new_node.set_next_node(self.head) + # update head attribute + self.head = new_node + + def add_to_tail(self, value): + # create new Node + new_node = Node(value) + # 1 LL is empty + if self.head is None: + self.head = new_node + self.tail = new_node + + # 2 LL is NOT empty + else: + self.tail.set_next_node(new_node) + + self.tail = new_node + + def remove_head(self): + # empty LinkedList + if self.head is None: + return None + # else, return value of old head + else: + ret_value = self.head.get_value() + # list with 1 element + if self.head == self.tail: + self.head = None + self.tail = None + # list with 2 elements + else: + self.head = self.head.get_next_node() + return ret_value + + + def remove_tail(self): + if self.head is None and self.tail is None: + return None + if self.head == self.tail: + value = self.head.get_value() + self.head = None + self.tail = None + return value + + else: + value = self.tail.get_value() + current_node = self.head + + while current_node.get_next_node() != self.tail: + current_node = current_node.get_next_node() + + self.tail = current_node + self.tail.set_next_node(None) + return value + + + + + + def contains(self, value): + cur_node = self.head + while cur_node is not None: + # if we find 'value' + if cur_node.get_value() == value(): + return True + return False + + def get_max(self, value): + pass + # TODO: \ No newline at end of file diff --git a/stack/stack.py b/stack/stack.py index 6e6d660ac7..6338b7ea8f 100644 --- a/stack/stack.py +++ b/stack/stack.py @@ -1,25 +1,33 @@ """ A stack is a data structure whose primary purpose is to store and -return elements in Last In First Out order. - +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 +3. What is the difference between using an array vs. a linked list when implementing a Stack? """ +import sys +sys.path.append('/Users/mstee/Data-Structures/singly_linked_list') +from singly_linked_list import LinkedList + class Stack: def __init__(self): self.size = 0 - # self.storage = ? + self.storage = LinkedList() def __len__(self): - pass + return self.size def push(self, value): - pass + self.size += 1 + self.storage.add_to_tail(value) def pop(self): - pass + if self.size == 0: + return None + + self.size -= 1 + return self.storage.remove_tail() From 3be16a4cfad602bc7a18ae7a8c936ae2c8635b4e Mon Sep 17 00:00:00 2001 From: msteele11101 Date: Fri, 18 Sep 2020 17:42:50 -0700 Subject: [PATCH 2/3] added some updates --- queue/queue.py | 21 ++--- queue/singly_linked_list.py | 98 +++++++++++++++++++++++ singly_linked_list/singly_linked_list.py | 97 ++++++++++++----------- stack/singly_linked_list.py | 99 ++++++++++++++++++++++++ stack/stack.py | 21 ++--- 5 files changed, 268 insertions(+), 68 deletions(-) create mode 100644 queue/singly_linked_list.py create mode 100644 stack/singly_linked_list.py diff --git a/queue/queue.py b/queue/queue.py index cb1800376e..d8ab212b30 100644 --- a/queue/queue.py +++ b/queue/queue.py @@ -1,34 +1,37 @@ """ A queue is a data structure whose primary purpose is to store and -return elements in First In First Out order. +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 +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! """ -import sys -sys.path.append('/Users/mstee/Data-Structures/singly_linked_list') + + 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 == 0: - return None - self.size -= 1 - return self.storage.remove_head() \ No newline at end of file + if self.size >= 1: + value = self.storage.remove_head() + self.size -= 1 + return value + return None \ No newline at end of file diff --git a/queue/singly_linked_list.py b/queue/singly_linked_list.py new file mode 100644 index 0000000000..c44c2401ff --- /dev/null +++ b/queue/singly_linked_list.py @@ -0,0 +1,98 @@ +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_head(self, value): + new_node = Node(value, self.head) + self.head = new_node + if self.head is None: + self.tail = new_node + + def add_to_tail(self, value): + + new_node = Node(value) + + if self.head is None and self.tail is None: + + self.head = new_node + self.tail = new_node + + else: + + self.tail.set_next(new_node) + self.tail = new_node + + def remove_tail(self): + + if self.head is None and self.tail is None: + + return None + + if self.head == self.tail: + + value = self.head.get_value() + + self.head = None + self.tail = None + + return value + + else: + + value = self.tail.get_value() + + current_node = self.head + + while current_node.get_next() != self.tail: + + current_node = current_node.get_next() + + self.tail = current_node + + self.tail.set_next(None) + + return value + + def remove_head(self): + + if self.head is None and self.tail is None: + + return None + + if self.head == self.tail: + + value = self.head.get_value() + + self.head = None + self.tail = None + + return value + + else: + + value = self.head.get_value() + + self.head = self.head.get_next() + + return value diff --git a/singly_linked_list/singly_linked_list.py b/singly_linked_list/singly_linked_list.py index e035c824f4..25f4e3483d 100644 --- a/singly_linked_list/singly_linked_list.py +++ b/singly_linked_list/singly_linked_list.py @@ -1,100 +1,99 @@ -# TODO a class that represents the individual elements in our LL - class Node: - def __init__(self, value=None, next_node=None): + 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_node(self): + def get_next(self): + return self.next_node - def set_next_node(self, new_next): + def set_next(self, new_next): + self.next_node = new_next + class LinkedList: def __init__(self): - # what attributes do we need? self.head = None self.tail = None def add_to_head(self, value): - new_node = Node(value) + new_node = Node(value, self.head) + self.head = new_node if self.head is None: - # update head & tail attributes - self.head = new_node self.tail = new_node - else: - # set next_node of my new Node to the head - new_node.set_next_node(self.head) - # update head attribute - self.head = new_node def add_to_tail(self, value): - # create new Node + new_node = Node(value) - # 1 LL is empty - if self.head is None: - self.head = new_node - self.tail = new_node - # 2 LL is NOT empty - else: - self.tail.set_next_node(new_node) + if self.head is None and self.tail is None: + self.head = new_node self.tail = new_node - def remove_head(self): - # empty LinkedList - if self.head is None: - return None - # else, return value of old head else: - ret_value = self.head.get_value() - # list with 1 element - if self.head == self.tail: - self.head = None - self.tail = None - # list with 2 elements - else: - self.head = self.head.get_next_node() - return ret_value + self.tail.set_next(new_node) + + self.tail = new_node def remove_tail(self): + if self.head is None and self.tail is None: + return None + if self.head == self.tail: + value = self.head.get_value() + self.head = None self.tail = None + return value else: + value = self.tail.get_value() + current_node = self.head - while current_node.get_next_node() != self.tail: - current_node = current_node.get_next_node() + while current_node.get_next() != self.tail: + + current_node = current_node.get_next() self.tail = current_node - self.tail.set_next_node(None) + + self.tail.set_next(None) + return value + def remove_head(self): + if self.head is None and self.tail is None: + return None + if self.head == self.tail: - def contains(self, value): - cur_node = self.head - while cur_node is not None: - # if we find 'value' - if cur_node.get_value() == value(): - return True - return False + value = self.head.get_value() + + self.head = None + self.tail = None + + return value - def get_max(self, value): - pass - # TODO: \ No newline at end of file + else: + + value = self.head.get_value() + + self.head = self.head.get_next() + + return value diff --git a/stack/singly_linked_list.py b/stack/singly_linked_list.py new file mode 100644 index 0000000000..25f4e3483d --- /dev/null +++ b/stack/singly_linked_list.py @@ -0,0 +1,99 @@ +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_head(self, value): + new_node = Node(value, self.head) + self.head = new_node + if self.head is None: + self.tail = new_node + + def add_to_tail(self, value): + + new_node = Node(value) + + if self.head is None and self.tail is None: + + self.head = new_node + self.tail = new_node + + else: + + self.tail.set_next(new_node) + + self.tail = new_node + + def remove_tail(self): + + if self.head is None and self.tail is None: + + return None + + if self.head == self.tail: + + value = self.head.get_value() + + self.head = None + self.tail = None + + return value + + else: + + value = self.tail.get_value() + + current_node = self.head + + while current_node.get_next() != self.tail: + + current_node = current_node.get_next() + + self.tail = current_node + + self.tail.set_next(None) + + return value + + def remove_head(self): + + if self.head is None and self.tail is None: + + return None + + if self.head == self.tail: + + value = self.head.get_value() + + self.head = None + self.tail = None + + return value + + else: + + value = self.head.get_value() + + self.head = self.head.get_next() + + return value diff --git a/stack/stack.py b/stack/stack.py index 6338b7ea8f..8a9a36b205 100644 --- a/stack/stack.py +++ b/stack/stack.py @@ -1,16 +1,16 @@ """ A stack is a data structure whose primary purpose is to store and -return elements in Last In First Out order. +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 +3. What is the difference between using an array vs. a linked list when implementing a Stack? """ -import sys -sys.path.append('/Users/mstee/Data-Structures/singly_linked_list') + + from singly_linked_list import LinkedList class Stack: @@ -22,12 +22,13 @@ def __len__(self): return self.size def push(self, value): + self.storage.add_to_head(value) self.size += 1 - self.storage.add_to_tail(value) + return self.storage def pop(self): - if self.size == 0: - return None - - self.size -= 1 - return self.storage.remove_tail() + if self.size > 0: + value = self.storage.remove_head() + self.size -= 1 + return value + return None \ No newline at end of file From 823c44cd557c3d26710c631b2fa8d9719e52ec65 Mon Sep 17 00:00:00 2001 From: msteele11101 Date: Mon, 21 Sep 2020 06:26:56 -0700 Subject: [PATCH 3/3] Day 2 Done --- doubly_linked_list/doubly_linked_list.py | 125 +++++++++++++++++++++-- 1 file changed, 116 insertions(+), 9 deletions(-) diff --git a/doubly_linked_list/doubly_linked_list.py b/doubly_linked_list/doubly_linked_list.py index 6f91b43a9b..5c42c640c2 100644 --- a/doubly_linked_list/doubly_linked_list.py +++ b/doubly_linked_list/doubly_linked_list.py @@ -7,7 +7,30 @@ def __init__(self, value, prev=None, next=None): self.prev = prev self.value = value self.next = next - + + def get_value(self): + return self.value + + def get_next(self): + if self.next: + return self.next + else: + return None + + def get_previous(self): + if self.prev: + return self.prev + else: + return None + + def delete(self): + if self.prev: + self.prev.next = self.next + if self.next: + self.next.prev = self.prev + self.value = None + self.next = None + self.prev = None """ Our doubly-linked list class. It holds references to the list's head and tail nodes. @@ -27,7 +50,15 @@ def __len__(self): the old head node's previous pointer accordingly. """ def add_to_head(self, value): - pass + root = ListNode(value) + if self.head and self.tail: + root.next = self.head + self.head.prev = root + self.head = root + else: + self.head = root + self.tail = root + self.length += 1 """ Removes the List's current head node, making the @@ -35,7 +66,22 @@ def add_to_head(self, value): Returns the value of the removed Node. """ def remove_from_head(self): - pass + if self.head: + headValue = self.head.get_value() + if self.length > 1: + newHead = self.head.get_next() + self.head.delete() + self.head = newHead + self.length -= 1 + return headValue + else: + self.head.delete() + self.head = None + self.tail = None + self.length -= 1 + return headValue + else: + return None """ Wraps the given value in a ListNode and inserts it @@ -43,7 +89,15 @@ def remove_from_head(self): the old tail node's next pointer accordingly. """ def add_to_tail(self, value): - pass + endNode = ListNode(value) + if self.head and self.tail: + endNode.prev = self.tail + self.tail.next = endNode + self.tail = endNode + else: + self.head = endNode + self.tail = endNode + self.length += 1 """ Removes the List's current tail node, making the @@ -51,32 +105,85 @@ def add_to_tail(self, value): Returns the value of the removed Node. """ def remove_from_tail(self): - pass + if self.tail: + tailValue = self.tail.get_value() + if self.length > 1: + newTail = self.tail.get_previous() + self.tail.delete() + self.tail = newTail + self.length -= 1 + return tailValue + else: + self.tail.delete() + self.tail = None + self.head = None + self.length -= 1 + return tailValue + else: + return None """ Removes the input node from its current spot in the List and inserts it as the new head node of the List. """ def move_to_front(self, node): - pass + value = node.value + if node == self.head: + return + elif node == self.tail: + self.remove_from_tail() + self.add_to_head(value) + else: + self.delete(node) + self.add_to_head(value) """ Removes the input node from its current spot in the List and inserts it as the new tail node of the List. """ def move_to_end(self, node): - pass + value = node.value + if node == self.tail: + return + elif node == self.head: + self.remove_from_head() + self.add_to_tail(value) + else: + self.delete(node) + self.add_to_tail(value) """ Deletes the input node from the List, preserving the order of the other elements of the List. """ def delete(self, node): - pass + if self.length == 0: + return + elif self.length == 1: + self.head = None + self.tail = None + node.delete() + self.length -= 1 + elif self.head == node: + self.remove_from_head() + elif self.tail == node: + self.remove_from_tail() + else: + node.delete() + self.length -= 1 """ Finds and returns the maximum value of all the nodes in the List. """ def get_max(self): - pass \ No newline at end of file + if not self.head: + return None + max_value = self.head.value + current_node = self.head + while current_node: + if current_node.value > max_value: + max_value = current_node.value + current_node = current_node.get_next() + + return max_value \ No newline at end of file