class Stack: def __init__(self): self.size = 0 # Why is our DLL a good choice to store our elements? # Modifying the order of elements is O(1) time, because they are not stored strictly in a sequence. self.storage = DoublyLinkedList() def push(self, value): self.storage.add_to_head(value) self.size += 1 # pass def pop(self): if(self.size == 0): return None old_value = self.storage.remove_from_head() self.size -= 1 return old_value # pass def len(self): return self.size # pass def Print(self): tracker = self.storage.head while tracker: print(tracker.value) tracker = tracker.next
class RingBuffer: def __init__(self, capacity): self.capacity = capacity self.storage = DoublyLinkedList() self.current = None def append(self, item): if self.storage.length == 0: self.storage.add_to_head(item) self.current = self.storage.head elif self.storage.length < self.capacity: self.storage.add_to_tail(item) self.current = self.current.next else: if self.current.next: self.current = self.current.next else: self.current = self.storage.head self.current.value = item def get(self): buffer_data = [] item = self.storage.head while item is not None: buffer_data.append(item.value) item = item.next return buffer_data
class RingBuffer: def __init__(self, capacity): self.capacity = capacity self.current = None self.storage = DoublyLinkedList() def append(self, item): # Length is none, insert 0th element, initialize pointer if len(self.storage) == 0: self.storage.add_to_head(item) self.current = self.storage.head if self.storage.length == self.capacity: if self.current is not self.storage.head: self.storage.remove_from_head() self.storage.add_to_tail(item) def get(self): # Note: This is the only [] allowed list_buffer_contents = [] # TODO: Your code here return list_buffer_contents
class LRUCache: def __init__(self, limit=10): self.limit = limit self.current = 0 self.dll = DoublyLinkedList() self.storage = {} def set(self, key, value): if key not in self.storage: self.dll.add_to_head([key, value]) self.storage[key] = self.dll.head self.current += 1 else: self.storage[key].value = [key, value] self.dll.move_to_front(self.storage[key]) if self.current > self.limit: tail_key = self.dll.tail.value[0] del self.storage[tail_key] self.dll.remove_from_tail() self.current -= 1 def get(self, key): if key in self.storage: self.dll.move_to_front(self.storage[key]) return self.storage[key].value[1] else: return None
class RingBuffer: def __init__(self, capacity): self.capacity = capacity self.current = None self.storage = DoublyLinkedList() def append(self, item): # if there's no items yet, make the one added the oldest if self.storage.length == 0: self.storage.add_to_head(item) self.current = self.storage.head # is the capacity has been reached, replace the oldest val w/ the item, # and change the oldest to the oldest.next elif self.storage.length == self.capacity: self.current.value = item if self.current.next: # self.current.next is not none self.current = self.current.next else: self.current = self.storage.head # if the capacity hasn't been reached and already a head, then add to tail else: self.storage.add_to_tail(item) def get(self): # Note: This is the only [] allowed list_buffer_contents = [] current = self.storage.head while current: list_buffer_contents.append(current.value) current = current.next return list_buffer_contents
class LRUCache: """ Our LRUCache class keeps track of the max number of nodes it can hold, the current number of nodes it is holding, a doubly- linked list that holds the key-value entries in the correct order, as well as a storage dict that provides fast access to every node stored in the cache. """ def __init__(self, limit=10): self.limit = limit self.hash = {} self.storage = DoublyLinkedList() self.size = 0 pass """ Retrieves the value associated with the given key. Also needs to move the key-value pair to the end of the order such that the pair is considered most-recently used. Returns the value associated with the key or None if the key-value pair doesn't exist in the cache. """ def get(self, key): if key in self.hash: self.storage.move_to_front(self.hash[key]) return self.storage.head.value else: return None """ Adds the given key-value pair to the cache. The newly- added pair should be considered the most-recently used entry in the cache. If the cache is already at max capacity before this entry is added, then the oldest entry in the cache needs to be removed to make room. Additionally, in the case that the key already exists in the cache, we simply want to overwrite the old value associated with the key with the newly-specified value. """ def set(self, key, value): if key in self.hash: self.storage.move_to_front(self.hash[key]) self.get(key) if self.size < self.limit: self.storage.add_to_head(ListNode(value)) self.size += 1 self.hash[key] = ListNode(value) if self.size >= self.limit: temp = { key: val for key, val in self.hash.items() if val.value != self.storage.tail.value.value } self.hash = temp del temp self.storage.remove_from_tail() self.storage.add_to_head(ListNode(value)) self.hash[key] = ListNode(value)
class Queue: def __init__(self): self.size = 0 # Why is our DLL a good choice to store our elements? # self.storage = ? self.storage = DoublyLinkedList() def enqueue(self, value): # Since were adding an item to the queue we need to add one self.size += 1 # If the storage.head is Null do something, if not -> else if self.storage.head is None: # We add the value to the head self.storage.add_to_head(value) else: # Add it to the tail self.storage.add_to_tail(value) def dequeue(self): # If the size is zero, we just return, else if self.size == 0: return else: self.size -= 1 # We need to store the value elsewhere to prevent it from being modified by +1 so we can return it later head_true_value = self.storage.head.value self.storage.remove_from_head() return head_true_value def len(self): return self.size
class Stack: def __init__(self): self.size = 0 # Why is our DLL a good choice to store our elements? self.storage = DoublyLinkedList() def push(self, value): # push means we are adding to the top/head of the DLL_Stack # we need to increment/increase size by 1 self.size += 1 # use add_to_head() to add the value in a new node # to the top/head of the DLL_Stack self.storage.add_to_head(value) def pop(self): # pop means we are subtracting/removing from the top/head of the DLL_Stack # if there is no node in storage if self.storage.head == None: # return None return None else: # we need to decrement/decrease size by 1 self.size -= 1 # use remove_from_head() to delete the last node added onto the DLL_Stack return self.storage.remove_from_head() def len(self): # return the size of the queue return self.size
class RingBuffer: def __init__(self, capacity=0): self.capacity = capacity self.current = None self.storage = DoublyLinkedList() def append(self, item): # before the list is full, keep adding item to the tail and track the most recent addition if len(self.storage) < self.capacity: self.storage.add_to_tail(item) self.current = self.storage.tail # when the list is full elif len(self.storage) == self.capacity: if self.current.next == None: self.storage.remove_from_head() self.storage.add_to_head(item) self.current = self.storage.head else: self.current.next.delete() self.current.insert_after(item) self.current = self.current.next def get(self): list_buffer_content = [] curr = self.storage.head if curr is not None: while curr.next is not None: list_buffer_content.append(curr.value) curr = curr.next list_buffer_content.append(curr.value) return list_buffer_content
class RingBuffer: def __init__(self, capacity): self.capacity = capacity self.current = None self.storage = DoublyLinkedList() def append(self, item): if self.storage.length != self.capacity: self.storage.add_to_tail(item) else: if self.current is None: self.storage.remove_from_head() self.storage.add_to_head(item) self.current = self.storage.head else: if self.current.next is not None: self.current.next.value = item self.current = self.current.next else: self.storage.head.value = item self.current = self.storage.head def get(self): # Note: This is the only [] allowed list_buffer_contents = [] curr_node = self.storage.head for _ in range(self.storage.length): list_buffer_contents.append(curr_node.value) curr_node = curr_node.next return list_buffer_contents
class Stack: def __init__(self): self.size = 0 # Why is our DLL a good choice to store our elements? # ANSWER: Push and Pop have O(1) time complexity self.storage = DoublyLinkedList() def push(self, value): if self.storage.length == 0: self.storage.add_to_head(value) else: self.storage.add_to_tail(value) self.size = self.storage.length def pop(self): if self.storage.tail is None: return None else: tail = self.storage.remove_from_tail() self.size = self.storage.length return tail def len(self): return self.size
class Stack: def __init__(self): self.size = 0 # Why is our DLL a good choice to store our elements? # self.storage = ? self.storage = DoublyLinkedList() def push(self, value): # increasing the size by 1 self.size += 1 # adding new item to the stack. self.storage.add_to_head(value) def pop(self): # if there are items if self.size > 0: # decreasing the size self.size -= 1 # calling remove from head and returning that item # when you are adding and removing from a stack it's always the top one, and the top is always the head return self.storage.remove_from_head() else: return None def len(self): return self.size
class Stack: def __init__(self): self.size = 0 # Why is our DLL a good choice to store our elements? self.storage = DoublyLinkedList() def push(self, value): self.storage.add_to_head(value) # decrease size self.size += 1 def pop(self): if self.size == 0: return None else: value = self.storage.remove_from_head() # decrease size self.size -= 1 return value def len(self): return self.storage.__len__()
class LRUCache: def __init__(self, limit=10): self.limit = limit self.size = 0 self.storage = dict() self.order = DoublyLinkedList() """ Retrieves the value associated with the given key. Also needs to move the key-value pair to the top of the order such that the pair is considered most-recently used. Returns the value associated with the key or None if the key-value pair doesn't exist in the cache. """ def get(self, key): # hanlde situation when key is not present if key in self.storage: # move item to the head node = self.storage[key] self.order.move_to_front(node) # return value associated with given key return node.value[1] else: return None pass """ Adds the given key-value pair to the cache. The newly- added pair should be considered the most-recently used entry in the cache. If the cache is already at max capacity before this entry is added, then the oldest entry in the cache needs to be removed to make room. Additionally, in the case that the key already exists in the cache, we simply want to overwrite the old value associated with the key with the newly-specified value. """ def set(self, key, value): # if the key is already in the cache, update the value if key in self.storage: node = self.storage[key] node.value = (key, value) # & move to head self.order.move_to_front(node) return # if at max if self.size == self.limit: del self.storage[self.order.tail.value[0]] # then remove oldest (the one of the tail) self.order.remove_from_tail() self.size -= 1 # add pair to cache & make it most recently used (head of dll) # 1. add key value pair to head of LL self.order.add_to_head(key, value) # 2. add to dict self.storage[key] = self.order.head # 3. increase size self.size += 1
class LRUCache: """ Our LRUCache class keeps track of the max number of nodes it can hold, the current number of nodes it is holding, a doubly- linked list that holds the key-value entries in the correct order, as well as a storage dict that provides fast access to every node stored in the cache. """ def __init__(self, limit=10): self.max_nodes = limit self.num_nodes = 0 # values in cache_list are key/value dicts self.cache_list = DLL() # storage holds key, node pairs self.storage = {} """ Retrieves the value associated with the given key. Also needs to move the key-value pair to the end of the order such that the pair is considered most-recently used. Returns the value associated with the key or None if the key-value pair doesn't exist in the cache. """ def get(self, key): if key in self.storage: node = self.storage[key] self.cache_list.move_to_front(node) return node.value[key] else: return None """ Adds the given key-value pair to the cache. The newly- added pair should be considered the most-recently used entry in the cache. If the cache is already at max capacity before this entry is added, then the oldest entry in the cache needs to be removed to make room. Additionally, in the case that the key already exists in the cache, we simply want to overwrite the old value associated with the key with the newly-specified value. """ def set(self, key, value): # if this is an existing key in the storage cache, # delete the corresponding node in the list if key in self.storage: self.cache_list.delete(self.storage[key]) self.num_nodes -= 1 self.cache_list.add_to_head({key: value}) self.storage[key] = self.cache_list.head self.num_nodes += 1 # if cache at max capacity if self.num_nodes > self.max_nodes: remove_key = list(self.cache_list.tail.value.keys())[0] del self.storage[remove_key] self.num_nodes -= 1
class Stack: def __init__(self): self.size = 0 # Why is our DLL a good choice to store our elements? self.storage = DoublyLinkedList() def push(self, value): ''' adds an item to the top of the stack ''' self.storage.add_to_head(value) self.size += 1 return self.size def pop(self): ''' removes and returns an item from the top of the stack ''' if self.storage.tail is None: return None else: self.size -= 1 return self.storage.remove_from_head() def len(self): ''' returns the number of items in the stack ''' return self.size
class Stack: def __init__(self): self.size = 0 # Why is our DLL a good choice to store our elements? self.storage = DoublyLinkedList() def push(self, value): self.storage.add_to_head(value) #increment the size of the stack self.size += 1 def pop(self): #if the stack is not empty if self.len() > 0: value = self.storage.remove_from_head() #decrement the stack size self.size -= 1 #return's the value of item_to_remove after the item is popped or removed return value #if the stack is not empty else: print("The stack is totally empty.") def len(self): #returns the size of the stack return self.size
class RingBuffer: def __init__(self, capacity): self.storage = DoublyLinkedList() self.capacity = capacity self.current_node = None def append(self, item): # normal insert if len(self.storage) < self.capacity: self.storage.add_to_tail(item) self.current_node = self.storage.tail else: if self.current_node == self.storage.tail: self.storage.remove_from_head() self.storage.add_to_head(item) self.current_node = self.storage.head else: self.storage.insert_after(self.current_node, item) self.current_node = self.current_node.next self.storage.delete(self.current_node.next) def get(self): # Note: This is the only [] allowed list_buffer_contents = [] # TODO: Your code here node = self.storage.head while node: list_buffer_contents.append(node.value) node = node.next return list_buffer_contents
class Queue: def __init__(self): self.size = 0 # Why is our DLL a good choice to store our elements? # A DLL can be traversed in both forward and backward direction and we # can quickly insert a new node before a given node. self.storage = DoublyLinkedList() def enqueue(self, value): self.size += 1 self.storage.add_to_head(value) return self.len() def dequeue(self): if self.size > 0: self.size -= 1 return self.storage.remove_from_tail() elif self.size <= 0: return None def len(self): return self.size
class Queue: def __init__(self): self.size = 0 # Why is our DLL a good choice to store our elements? # self.storage = ? self.storage = DoublyLinkedList() def __str__(self): node = self.storage.head while node and node.next: print(node.value) node = node.next def enqueue(self, value): self.storage.add_to_head(value) self.size += 1 def dequeue(self): if self.size == 0: return else: self.size -= 1 return self.storage.remove_from_tail() def len(self): return self.size
class Stack: def __init__(self): self.size = 0 # Why is our DLL a good choice to store our elements? # it has the needed essentials of a list that has a beggining and end self.storage = DoublyLinkedList() def __str__(self): if self.storage.head is None and self.storage.tail is None: return "empty" curr_node = self.storage.head output = "" output += f'({curr_node.value})' while curr_node.next is not None: curr_node = curr_node.next output += f' <-> ({curr_node.value})' return output def push(self, value): # add to head self.storage.add_to_head(value) # increase count by 1 self.size += 1 def pop(self): # if the stack has at least one item, remove it if self.size > 0: # decrease count by one self.size -= 1 return self.storage.remove_from_head() def len(self): return self.size
class RingBuffer: def __init__(self, capacity): self.capacity = capacity self.current = None self.storage = DoublyLinkedList() def append(self, item): if self.storage.length < self.capacity: self.storage.add_to_head(item) self.current = self.storage.head else: if self.current is self.storage.head: self.storage.delete(self.storage.tail) self.storage.add_to_tail(item) self.current = self.storage.tail else: to_delete = self.current.prev self.storage.delete(to_delete) self.storage.insert_before(self.current, item) self.current = self.current.prev def get(self): # Note: This is the only [] allowed list_buffer_contents = [] i = self.storage.tail while i is not None: list_buffer_contents.append(i.value) i = i.prev return list_buffer_contents
class LRUCache: """ Our LRUCache class keeps track of the max number of nodes it can hold, the current number of nodes it is holding, a doubly- linked list that holds the key-value entries in the correct order, as well as a storage dict that provides fast access to every node stored in the cache. """ def __init__(self, limit=10): self.limit = limit self.size = 0 self.cache = {} self.storage = DoublyLinkedList() """ Retrieves the value associated with the given key. Also needs to move the key-value pair to the end of the order such that the pair is considered most-recently used. Returns the value associated with the key or None if the key-value pair doesn't exist in the cache. """ def get(self, key): if key in self.cache: i = self.cache[key] self.storage.move_to_front(i) return i.value[1] else: return None """ Adds the given key-value pair to the cache. The newly- added pair should be considered the most-recently used entry in the cache. If the cache is already at max capacity before this entry is added, then the oldest entry in the cache needs to be removed to make room. Additionally, in the case that the key already exists in the cache, we simply want to overwrite the old value associated with the key with the newly-specified value. """ #adds key-value pair to cache #assign it to the tail of the cache #if cache is maxxed out delete head #else if the key-value is already in the cache. assign it to the tail def set(self, key, value): if key in self.cache: i = self.cache[key] i.value =(key,value) return self.storage.move_to_front(i) if self.size == self.limit: del self.cache[self.storage.tail.value[0]] self.storage.remove_from_tail() self.size -= 1 self.storage.add_to_head((key,value)) self.cache[key] = self.storage.head self.size += 1
class Queue: def __init__(self, value=None): self.size = 0 self.storage = DoublyLinkedList(value) # Why is our DLL a good choice to store our elements? # self.storage = ? def enqueue(self, value): # pass self.size += 1 self.storage.add_to_head(value) """Adds to the back of the Queue""" def dequeue(self): value = self.storage.remove_from_tail() if not value == None: print('this is the value ', value) self.size -= 1 return value else: # print('this is the value when none ',value) return value def len(self): # pass return self.size """takes the length of the queue"""
class RingBuffer: def __init__(self, capacity): self.capacity = capacity self.current = None self.size = 0 self.storage = DoublyLinkedList() def append(self, item): if self.size == self.capacity: # remove last item from dll self.storage.remove_from_tail() self.size -= 1 # add new item to dll.head self.storage.add_to_head(item) # increment size self.size += 1 def get(self): # Note: This is the only [] allowed list_buffer_contents = [] self.current = self.storage.tail while self.current: list_buffer_contents.append(self.current.value) self.current = self.current.prev return list_buffer_contents
class RingBuffer: def __init__(self, capacity): self.capacity = capacity self.current = None self.storage = DoublyLinkedList() def append(self, item): if self.storage.length < self.capacity: self.storage.add_to_tail(item) elif self.storage.length == self.capacity: if self.current == None: self.storage.remove_from_head() self.storage.add_to_head(item) self.current = self.storage.head else: if self.current.next: self.current.insert_after(item) self.current = self.current.next self.current.next.delete() else: self.storage.remove_from_head() self.storage.add_to_head(item) self.current = self.storage.head def get(self): # Note: This is the only [] allowed list_buffer_contents = [] # TODO: Your code here node = self.storage.head while node: list_buffer_contents.append(node.value) node = node.next return list_buffer_contents
class TextBuffer: def __init__(self, init=None): self.contents = DoublyLinkedList() if init != None: for char in init: self.contents.add_to_tail(char) def __len__(self): return len(self.contents) def __str__(self): s = "" current = self.contents.head while current: s += current.value current = current.next return s def append(self, char): self.contents.add_to_tail(char) def prepend(self, char): self.contents.add_to_head(char) def delete_front(self): self.contents.remove_from_head() def delete_back(self): self.contents.remove_from_tail() def join(self, buffer): buffer.contents.head.prev = self.contents.tail self.contents.tail.next = buffer.contents.head self.contents.tail = buffer.contents.tail
class LRUCache: """ Our LRUCache class keeps track of the max number of nodes it can hold, the current number of nodes it is holding, a doubly- linked list that holds the key-value entries in the correct order, as well as a storage dict that provides fast access to every node stored in the cache. """ def __init__(self, limit=10): self.limit = limit # Adding a limit to the cache self.held = 0 # starting held count too 0 self.linked_list = DoublyLinkedList() # setting Cashed storage self.hashing_table = dict() """ Retrieves the value associated with the given key. Also needs to move the key-value pair to the end of the order such that the pair is considered most-recently used. Returns the value associated with the key or None if the key-value pair doesn't exist in the cache. """ def get(self, key): # If there is the input key in the hashing_table if key in self.hashing_table: # Then move the DoublyLinkedList.tail to the front self.linked_list.move_to_front(self.linked_list.tail) # and return the Key return self.hashing_table[key] # if not ignore else: return None """ Adds the given key-value pair to the cache. The newly- added pair should be considered the most-recently used entry in the cache. If the cache is already at max capacity before this entry is added, then the oldest entry in the cache needs to be removed to make room. Additionally, in the case that the key already exists in the cache, we simply want to overwrite the old value associated with the key with the newly-specified value. """ def set(self, key, value): # If the key allredy in hashing_table then if key in self.hashing_table: # set the key value to input value self.hashing_table[key] = value return # stop est here # if there are more items held than the limit if self.held >= self.limit: # then del oldest cached value del self.hashing_table[self.linked_list.tail.value] self.linked_list.remove_from_tail() # Now lets add the key to the linked list self.linked_list.add_to_head(key) # set the key value to input value self.hashing_table[key] = value self.held += 1 # add +1 to held for tracking the limit
class RingBuffer: def __init__(self, capacity): self.capacity = capacity self.current = None self.storage = DoublyLinkedList() def append(self, item): if not self.current: # If self.current is None, the list isn't full yet self.storage.add_to_tail(item) if self.storage.length == self.capacity: # If this puts the list at capacity, set self.current # to the head. (self.current is basically the node # that will get replaced if a new value is appended.) self.current = self.storage.head else: if self.current is self.storage.head: # Replace the head self.current = self.storage.head.next self.storage.remove_from_head() self.storage.add_to_head(item) elif self.current is self.storage.tail: # Replace the tail self.current = self.storage.head self.storage.remove_from_tail() self.storage.add_to_tail(item) else: # Log self.current's next and prev, then delete it. current_next = self.current.next current_prev = self.current.prev self.storage.delete(self.current) # Set the new self.current self.current = current_next # Keep track of the tail, since we'll be adding the # new value as the tail temporarily. tail = self.storage.tail self.storage.add_to_tail(item) # Set the new node's next and prev to be the same as # the old self.current. new_node = self.storage.tail new_node.next = current_next new_node.prev = current_prev # Also fix the directions for the nodes that surround the new node current_next.prev = new_node current_prev.next = new_node # Finally, set the tail back to being the proper tail, # and make sure it has no "next" node. self.storage.tail = tail self.storage.tail.next = None def get(self): # Note: This is the only [] allowed list_buffer_contents = [] # TODO: Your code here node = self.storage.head while node: list_buffer_contents.append(node.value) node = node.next return list_buffer_contents
class Stack: def __init__(self): self.size = 0 # Why is our DLL a good choice to store our elements? # ANSWER: Because the only position we need to access is the first one # (or the last one--the point is, only one position need be accessible.) self.storage = DoublyLinkedList() def push(self, value): # Push and pop from the head. self.size += 1 self.storage.add_to_head(value) def pop(self): # Push and pop from the head. if self.size == 0: # Return None when attempting to pop from an empty stack return None else: self.size -= 1 return self.storage.remove_from_head() def len(self): # Just return the size return self.size