Ejemplo n.º 1
0
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
Ejemplo n.º 4
0
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
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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
Ejemplo n.º 11
0
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
Ejemplo n.º 12
0
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
Ejemplo n.º 13
0
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__()
Ejemplo n.º 14
0
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
Ejemplo n.º 15
0
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
Ejemplo n.º 16
0
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
Ejemplo n.º 17
0
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
Ejemplo n.º 19
0
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
Ejemplo n.º 20
0
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
Ejemplo n.º 21
0
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
Ejemplo n.º 22
0
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
Ejemplo n.º 23
0
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
Ejemplo n.º 24
0
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"""
Ejemplo n.º 25
0
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
Ejemplo n.º 27
0
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
Ejemplo n.º 28
0
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
Ejemplo n.º 30
0
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