class FavoritesList: class _Item: __slots__ = '_value', '_count' def __init__(self, e): self._value = e self._count = 0 def __init__(self): self._data = PositionalList() def __len__(self): return len(self._data) def is_empty(self): return len(self._data) == 0 def access(self, e): p = self._find_position(e) if p is None: p = self._data.add_last(self._Item(e)) p.element()._count += 1 self._move_up(p) def remove(self, e): p = self._find_position(e) if p is not None: self._data.delete(p) def top(self, k=1): if not 1 <= k <= len(self): raise ValueError('Illegal value for k') walk = self._data.first() for j in range(k): item = walk.element() yield item._value walk = self._data.after(walk) def _find_position(self, e): walk = self._data.first() while walk is not None and walk.element()._value != e: walk = self._data.after(walk) return walk def _move_up(self, p): if p == self._data.first(): return cnt = p.element()._count walk = self._data.before(p) if cnt <= walk.element()._count: return while (walk != self._data.first() and cnt > self._data.before(walk).element()._count): walk = self._data.before(walk) self._data.add_before(walk, self._data.delete(p))
def top(self, k): if not 1 <= k <= len(self): raise ValueError('Illegal value for k') temp = PositionalList() for item in self._data: temp.add_last(item) for j in range(k): highPos = temp.first() walk = temp.after(highPos) while walk is not None: if walk.element()._count > highPos.element()._count: highPos = walk yield highPos.element()._value temp.delete(highPos)
class SortedPriorityQueue(PriorityQueueBase): def __init__(self): self._data = PositionalList() def __len__(self): return len(self._data) def add(self, key, value): newest = self._Item(key, value) walk = self._data.last() while walk is not None and newest < walk.element(): walk = self._data.before(walk) if walk is None: self._data.add_first(newest) else: self._data.add_after(walk, newest) def min(self): if self.is_empty(): raise Empty('Priority queue is empty') p = self._data.first() item = p.element() return (item._key, item._value) def remove_min(self): if self.is_empty(): raise Empty('Priority queue is empty') item = self._data.delete(self._data.first()) return (item._key, item._value)
class SortedPriorityQueue(PriorityQueueBase): """ A priority queue class storing elements sorted according to priority """ def __init__(self): self._data = PositionalList() def __len__(self): return len(self._data) def min(self): if self.is_empty(): raise EmptyException('Priority queue is empty.') p = self._data.first() return (p.element()._key, p.element()._value) def remove_min(self): if self.is_empty(): raise EmptyException('Priority queue is empty.') p = self._data.first() item = self._data.delete(p) return (item._key, item._value) def add(self, k, v): newest = self._Item(k, v) walk = self._data.last() while walk is not None and newest < walk.element(): walk = self._data.before(walk) if walk is None: self._data.add_first(newest) else: self._data.add_after(walk, newest)
class SortedPriorityQueue(PriorityQueueBase): # base class defines _Item """ A min-oriented priority queue implemented with a sorted list. """ def __init__(self): """ Create a new empty Priority Queue. """ self._data = PositionalList() def __len__(self): """ Return the num of items in the priority queue. """ return len(self._data) def add(self, key, value): """ Add a key-value pair. """ newest = self._Item(key, value) # make new item instance walk = self._data.last() # walk backward looking for smaller key while walk is not None and newest < walk.element(): walk = self._data.before(walk) if walk is None: self._data.add_first(newest) # new key is smallest else: self._data.add_after(walk, newest) # newest goes after walk def min(self): """ Return but do not remove (k,v) tuple with min key """ if self.is_empty(): raise Exception('Priority queue is empty.') p = self._data.first() item = p.element() return (item._key, item._value) def remove_min(self): """ Remove and return (k,v) tuple with min key. """ if self.is_empty(): raise Exception('Priority queue is empty.') item = self._data.delete(self._data.first()) return (item._key, item._value)
class UnsortedPriorityQueue(PriorityQueueBase): def _find_min(self): if self.is_empty(): raise Empty('Priority queue is empty') small = self._data.first() walk = self._data.after(small) while walk is not None: if walk.element() < small.element(): small = walk walk = self._data.after(walk) return small def __init__(self): self._data = PositionalList() def __len__(self): return len(self._data) def add(self, key, value): self._data.add_last(self._Item(key, value)) def min(self): p = self._find_min() item = p.element() return(item._key, item._value) def remove_min(self): p = self._find_min() item = self._data.delete(p) return (item._key, item._value)
class UnsortedPriorityQueue(PriorityQueueBase): def __init__(self): self._data = PositionalList() def __len__(self): return len(self._data) def _find_min(self): if self.is_empty(): raise Empty('Priority queue is empty.') min = self._data.first() walk = self._data.after(min) while walk is not None: if walk.element() < min.element(): min = walk walk = self._data.after(min) return min def add(self, key, value): self._data.add_last(self._Item(key, value)) def min(self): p = self._find_min() item = p.element() return item._key, item._value def remove_min(self): p = self._find_min() item = self._data.delete(p) return item._key, item._value
class UnsortedPriorityQueue(PriorityQueueBase): """ A priority queue class storing elements in arbitrary order """ def __init__(self): self._data = PositionalList() def __len__(self): return len(self._data) def _find_min(self): if self.is_empty(): raise EmptyException("Priority Queue is empty.") curr_min = self._data.first() walk = self._data.after(curr_min) while walk is not None: if walk.element() < curr_min.element(): curr_min = walk walk = self._data.after(walk) return curr_min def min(self): p = self._find_min() return (p.element()._key, p.element()._value) def remove_min(self): p = self._find_min() item = self._data.delete(p) return (item._key, item._value) def add(self, k, v): self._data.add_last(self._Item(k, v))
class UnsortedPriorityQueue(PriorityQueueBase): """ a min-oriented priority queue implemented with an unsorted list """ def __init__(self): """ Create a new empty Priority Queue """ self._data = PositionalList() def _find_min(self): # nonpublic utility """ Return Position of item with min key """ if self.is_empty(): # method inherited from base class raise Exception('Priority queue is empty') small = self._data.first() walk = self._data.after(small) def __len__(self): """ Return the number of items in the priority queue. """ return len(self._data) def add(self, key, value): """ add a key-value pair. """ self._data.add_last(self._Item(key, value)) def min(self): """ Return but do not remove (k,v) tuple with min key. """ p = self._find_min() item = p.element() return (item._key, item._value) def remove_min(self): """ Remove and return (k,v) tuple with min key. """ p = self._find_min() item = self._data.delete(p) return (item._key, item._value)
class SortedPriorityQueue(PriorityQueueBase): def __init__(self): self._data = PositionalList() def __len__(self): return len(self._data) def add(self, key, value): new = self._Item(key, value) walk = self._data.last() while walk is not None and new < walk.element(): walk = self._data.before(walk) if walk is None: self._data.add_first(new) else: self._data.add_before(walk, new) def min(self): if self.is_empty(): raise Empty('Priority queue is empty.') p = self._data.first() item = p.element() return item._key, item._value def remove_min(self): if self.is_empty(): raise Empty('Priority queue is empty.') item = self._data.delete(self._data.first()) return item._key, item._value
class sortedPriorityQueue(PriorityQueueBase): # base class defines _Item """A min-oriented priority queue implemented with an unsorted list.""" #----------------------------- nonpublic behavior ----------------------------- #------------------------------ public behaviors ------------------------------ def __init__(self): """Create a new empty Priority Queue.""" self._data = PositionalList() def __len__(self): """Return the number of items in the priority queue.""" return len(self._data) def add(self, key, value): """Add a key-value pair.""" newest = self._Item(key, value) walk = self._data.last() while walk is not None and newest < walk.element(): walk = self._data.before(walk) if walk is None: self._data.add_first(newest) else: self._data.add_after(walk, newest) def min(self): """Return but do not remove (k,v) tuple with minimum key. Raise Empty exception if empty. """ if self.is_empty(): raise Exception("Priority queue is empty") p = self._data.first() item = p.element() return (item._key, item._value) def remove_min(self): """Remove and return (k,v) tuple with minimum key. Raise Empty exception if empty. """ if self.is_empty(): raise Exception("Priority Queue is empty.") item = self._data.delete(self._data.first()) return (item._key) def __iter__(self): """Generate iteration of the map's keys.""" for item in self._data: yield item # yield the KEY def insertionSort(self, A): for i in A: self.add(i, i) for i in range(len(A)): A[i] = self.remove_min()
class UnsortedPriorityQueue(PriorityQueue): """ An implementstion of a PriorityQueue Store items in an unsorted list Requires searching the entire list when accessing items """ def __init__(self): """ Creates an empty PriorityQueue """ self._data = PositionalList() def __len__(self): """ returns: the number of items in the PriorityQueue """ return len(self._data) def add(self, key, value): """ Adds a key-value pair to the PriorityQueue """ self._data.add_last(self._Item(key, value)) def _find_min(self): """ Non-public utility method returns: the item with the minimum key """ if self.is_empty(): raise Empty('Priority Queue is empty') minimum = self._data.first() walk = self._data.after(minimum) while walk is not None: if walk.element() < minimum.element( ): # __lt__ is implemented by the PriorityQueue class minimum = walk walk = self._data.after(walk) return minimum def min(self): """ returns: the (k,v) tuple with the minimum key, without removing it """ p = self._find_min() item = p.element() return (item._key, item._value) def remove_min(self): """ removes the minimum (k,v) tuple from the priority queue returns: the (k,v) tuple """ p = self._find_min() item = self._data.delete(p) # PositionalList removes and returns item return (item._key, item._value)
def top(self, k): """Generate sequence of top k elements in terms of access count.""" if not 1 <= k <= len(self): raise ValueError('Illegal value for k') # we begin by making a copy of the original list temp = PositionalList() for item in self._data: # positional lists support iteration temp.add_last(item) # we repeatedly find, report, and remove element with largest count for j in range(k): # find and report next highest from temp highPos = temp.first() walk = temp.after(highPos) while walk is not None: if walk.element()._count > highPos.element()._count: highPos = walk walk = temp.after(walk) # we have found the element with highest count yield highPos.element()._value # report element to user temp.delete(highPos) # remove from temp list
class PositionalQueue(object): """ A queue implementation based on positional list. With enqueue returning a position instance and support for a new method, delete(p), that removes the element associated with position p from the queue. """ def __init__(self): self._data = PositionalList() def __len__(self): """ Length method.""" return len(self._data) def is_empty(self): """ check if the queue is empty or not.""" return len(self._data) == 0 def first(self): """ get the first element of the queue.""" if self._data.is_empty(): raise Empty('The queue is empty') return self._data.first().element() def enqueue(self, e): """ add an element to the end of the queue. :return: the Position of the element just be enqueued. """ return self._data.add_last(e) def dequeue(self): """ remove the first element of the queue.""" self._data.delete(self._data.first()) def delete(self, p): """ Delete the element associated with position p.""" self._data.delete(p) def __repr__(self): return str(self._data)
class UnsortedPriorityQueue(PriorityQueueBase): # base class defines _Item """A min-oriented priority queue implemented with an unsorted list.""" #----------------------------- nonpublic behavior ----------------------------- def _find_min(self): """Return Position of item with minimum key.""" if self.is_empty(): # is_empty inherited from base class raise Exception('Priority queue is empty') small = self._data.first() walk = self._data.after(small) while walk is not None: if walk.element() < small.element(): small = walk walk = self._data.after(walk) return small #------------------------------ public behaviors ------------------------------ def __init__(self): """Create a new empty Priority Queue.""" self._data = PositionalList() def __len__(self): """Return the number of items in the priority queue.""" return len(self._data) def add(self, key, value): """Add a key-value pair.""" self._data.add_last(self._Item(key, value)) def min(self): """Return but do not remove (k,v) tuple with minimum key. Raise Empty exception if empty. """ p = self._find_min() item = p.element() return (item._key, item._value) def remove_min(self): """Remove and return (k,v) tuple with minimum key. Raise Empty exception if empty. """ p = self._find_min() item = self._data.delete(p) return (item._key, item._value) def __iter__(self): """Generate iteration of the map's keys.""" for item in self._data: yield item # yield the KEY
class SortedPriorityQueue(PriorityQueue): """ Implementation of a PriorityQueue using a sorted PositionalList Adds items to the list in order """ def __init__(self): """ Creates an empty PriorityQueue """ self._data = PositionalList() def __len__(self): """ returns: the number of items in the PriorityQueue """ return len(self._data) def add(self, key, value): """ Adds a key-value pair to the PriorityQueue """ new_item = self._Item(key, value) walk = self._data.last() while walk is not None and new_item < walk.element(): walk = self._data.before(walk) if walk is not None: self._data.add_after(walk, new_item) else: self._data.add_first(new_item) def min(self): """ returns: the (k,v) tuple with the minimum key, without removing it """ if self.is_empty(): raise Empty('Priority Queue is empty') p = self._data.first() item = p.element() return (item._key, item._value) def remove_min(self): """ removes the minimum (k,v) tuple from the priority queue returns: the (k,v) tuple """ if self.is_empty(): raise Empty('Priority Queue is empty') p = self._data.first() item = self._data.delete(p) return (item._key, item._value)
def top(self, k): """Generate sequence of top k elements in terms of access count.""" if not 0 <= k <= len(self): raise ValueError("Illegal value for k") # we begin my making copy of original list, as we will modify the temprary list temp = PositionalList() for item in self._data: # positional list supports iteration temp.add_last(item) # we repeatedly find, report, and remove elements with largest count from temp list for j in range(k): # find and report next highest from temp highPos = temp.first() walk = temp.after(highPos) while walk != None: if walk.element()._count > highPos.element()._count: highPos = walk walk = temp.after(walk) # we have found element with the highest count yield highPos.element()._value # report element to user temp.delete( highPos) # remove from temp to get next most accessed element
class UnsortedPriorityQueue(PriorityQueueBase): # base class defines _Item """A min-oriented priority queue implemented with an unsorted list.""" #----------------------------- nonpublic behavior ----------------------------- def _find_min(self): """Return Position of item with minimum key.""" if self.is_empty(): # is_empty inherited from base class raise Empty('Priority queue is empty') small = self._data.first() walk = self._data.after(small) while walk is not None: if walk.element() < small.element(): small = walk walk = self._data.after(walk) return small #------------------------------ public behaviors ------------------------------ def __init__(self): """Create a new empty Priority Queue.""" self._data = PositionalList() def __len__(self): """Return the number of items in the priority queue.""" return len(self._data) def add(self, key, value): """Add a key-value pair.""" self._data.add_last(self._Item(key, value)) def min(self): """Return but do not remove (k,v) tuple with minimum key. Raise Empty exception if empty. """ p = self._find_min() item = p.element() return (item._key, item._value) def remove_min(self): """Remove and return (k,v) tuple with minimum key. Raise Empty exception if empty. """ p = self._find_min() item = self._data.delete(p) return (item._key, item._value)
class SortedPriorityQueue(PriorityQueueBase): # base class defines _Item """A min-oriented priority queue implemented with a sorted list.""" # ------------------------------ public behaviors ------------------------------ def __init__(self): """Create a new empty Priority Queue.""" self._data = PositionalList() def __len__(self): """Return the number of items in the priority queue.""" return len(self._data) def add(self, key, value): """Add a key-value pair.""" newest = self._Item(key, value) walk = self._data.last() # walk backward look for smaller while walk and newest < walk.element(): walk = self._data.before(walk) if not walk: self._data.add_first(newest) else: self._data.add_after(walk, newest) def min(self): """Return but do not remove (k,v) tuple with minimum key. Raise Empty exception if empty. """ if self.is_empty(): raise Empty('Priority Queue is empty') first = self._data.first() item = first.element() return (item._key, item._value) def remove_min(self): """Remove and return (k,v) tuple with minimum key. Raise Empty exception if empty. """ min = self._data.first() item = self._data.delete(min) return (item._key, item._value)
class SortedPriorityQueue(PriorityQueueBase): # base class defines _Item """A min-oriented priority queue implemented with a sorted list.""" #------------------------------ public behaviors ------------------------------ def __init__(self): """Create a new empty Priority Queue.""" self._data = PositionalList() def __len__(self): """Return the number of items in the priority queue.""" return len(self._data) def add(self, key, value): """Add a key-value pair.""" newest = self._Item(key, value) # make new item instance walk = self._data.last() # walk backward looking for smaller key while walk is not None and newest < walk.element(): walk = self._data.before(walk) if walk is None: self._data.add_first(newest) # new key is smallest else: self._data.add_after(walk, newest) # newest goes after walk def min(self): """Return but do not remove (k,v) tuple with minimum key. Raise Empty exception if empty. """ if self.is_empty(): raise Empty('Priority queue is empty.') p = self._data.first() item = p.element() return (item._key, item._value) def remove_min(self): """Remove and return (k,v) tuple with minimum key. Raise Empty exception if empty. """ if self.is_empty(): raise Empty('Priority queue is empty.') item = self._data.delete(self._data.first()) return (item._key, item._value)
class SortedPriorityQueue(PriorityQueueBase): def __init__(self): #empty priority queue self._data = PositionalList() def __len__(self): #number of items in priority queue return len(self._data) def add(self, key, value): #add key-value pair #._Item defined by base class newest = self._Item(key, value) walk = self._data.last() #look for smaller key while walk is not None and newest < walk.element(): walk = self._data.before(walk) if walk is None: self._data.add_first(newest) else: self._data.add_after(walk, newest) def min(self): #returns but does not remove the tuple with min key if self.is_empty(): raise Empty('Priority queue is empty.') p = self._data.first() item = p.element() return (item._key, item._value) def remove_min(self): #removes and returns the tuple with minimum key if self.is_empty(): raise Empty('Priority queue is empty') item = self._data.delete(self._data.first()) return (item._key) def __iter__(self): #iteration of the map's keys for item in self._data: yield item
class SortedListPQ(PriorityQueueBase): # base class defines _Item """A min-oriented priority queue implemented with an unsorted list.""" def __init__(self): """Create a new empty Priority Queue.""" self._data = PositionalList() def __len__(self): """Return the number of items in the priority queue.""" return len(self._data) def add(self, key, value): """Add a key-value pair.""" newest = self._Item(key, value) walk = self._data.last() while walk is not None and newest < walk.element(): walk = self._data.before(walk) if walk is None: self._data.add_first(newest) else: self._data.add_after(walk, newest) def min(self): """Return but do not remove (k,v) tuple with minimum key. Raise Empty exception if empty. """ if self.is_empty(): raise Empty("Priority queue is empty") p = self._data.first() item = p.element() return item._key, item._value def remove_min(self): """Remove and return (k,v) tuple with minimum key. Raise Empty exception if empty. """ if self.is_empty(): raise Empty("Priority queue is empty") item = self._data.delete(self._data.first()) return (item._key, item._value)
class FavouritesList: # positional list stores item intances class _Item: __slots__ = "_value", "_count" def __init__(self, e): self._value = e self._count = 0 # return position of item with value e (items should have unique values) def _find_position(self, e): p = self._data.first() while p is not None and p.element()._value != e: p = self._data.after(p) return p # move position of newly inserted item up to the appropriate place def _move_up(self, p): if p == self._data.first(): return it = self._data.before(p) if it.element()._count >= p.element()._count: return while self._data.before(it) != None and self._data.before( it).element()._count < p.element()._count: it = self._data.before(it) item = self._data.delete(p) self._data.add_before(it, item) # if p == self._data.first(): # return # # b = self._data.before(p) # c = p._element()._count # # while b.element()._count < c and self._data.before(b) != None: # b = self._data.before(b) # # e = self.data.delete(p) # # if b.element()._count < c: # self._data.add_before(b, e) # else: # self._data.add_after(b, e) def __init__(self): self._data = PositionalList() def __len__(self): return len(self._data) def is_empty(self): return len(self._data) == 0 def access(self, e): p = self._find_position(e) if p is None: p = self._data.add_last(self._Item(e)) p.element()._count += 1 self._move_up(p) def remove(self, e): p = self._find_position(e) if p is not None: self._data.delete(p) def top(self, k): if k < 1 or k > len(self._data): raise ValueError("Invalid value for k.") p = self._data.first() for i in range(k): yield p.element()._value p = self._data.after(p)
class FavoritesList: """List of elements ordered from most frequently accessed to least.""" # ------------------- nested _Item class -------------------------------- class _Item: __slots__ = '_value', '_count' # make the object lighter-weight in memory def __init__(self, e): self._value = e # the user's element self._count = 0 # access count initially zero # -------------------- nonpublic utilities -------------------------------- def _find_position(self, e): """Search for element e and return its Position (or None if not found). Returns: walk (Position): Position object. """ walk = self._data.first() # a Position object while walk is not None and walk.element()._value != e: walk = self._data.after(walk) return walk def _move_up(self, p): """Move item at Position p earlier in the list based on access count.""" if p != self._data.first(): # If it's not first, consider moving it... cnt = p.element()._count walk = self._data.before(p) if cnt > walk.element()._count: # must shift p forward (it's more # frequently accessed) while (walk != self._data.first() and # Walk leftward til reach front of list... cnt > self._data.before(walk).element()._count ): #...or an element that sorts # to a higher position than the element that's being sorted walk = self._data.before(walk) # Walk one step left self._data.add_before(walk, self._data.delete(p)) # delete/reinsert # ------------------------- public methods ------------------------------- def __init__(self): """Create empty list of favorites.""" self._data = PositionalList() # will be list of _Item instances def __len__(self): """Return number of entries on favorites list.""" return len(self._data) def is_empty(self): """Return True if list is empty.""" return len(self._data) == 0 # Presumably, this can't (or shouldn't) just use _DLB's # inherited-inherited is_empty method because that entire class # is meant to be nonpublic. def access(self, e): """ Access element e, thereby increasing its access count. e (object): The actual stored item--the _value attribute of the _Item object. Not the _Item object itself (that's not to be accessed from outside the class) and not the Position object. Need not be the identical object in memory; e.g. separate string or int object with same value will be accessed successfully. """ p = self._find_position(e) # try to locate existing element if p is None: p = self._data.add_last(self._Item(e)) # if new, place at end p.element()._count += 1 # always increment count self._move_up(p) # Move element forward if needed def remove(self, e): """Remove element e from the list of favorites.""" p = self._find_position(e) # try to locate existing element if p is not None: self._data.delete(p) # delete, if found def top(self, k): """Generate sequence of top k elements in terms of access count. Yields an iterator that can be used in a for loop; doesn't return anything. Args: k (int): Number of elements to include in the list. Must be a positive nonzero integer no greater than the length of the list. Returns: None """ if not 1 <= k <= len(self): raise ValueError('Illegal value for k') walk = self._data.first() for j in range(k): item = walk.element() # element of list is _Item yield item._value # report user's element walk = self._data.after(walk)
class FavoritesList: """A list of elements ordered from most frequently accessed to least.""" # ----- Class to store an element's value and access frequency. ----- # class _Item: """Object to store elements' value and access counts.""" __slots__ = "_value", "_count" def __init__(self, e): self._value = e # Element. self._count = 0 # To store access count. # ----- Non-Public Utilities ----- # def _find_position(self, e): """Search for element 'e' and return its position, or None if not found.""" walk = self._data.first() # Start at header of underlying linked list. while (walk is not None) and (walk.element()._value != e): walk = self._data.after(walk) return walk def _move_up(self, p): """Move item at position 'p' *earlier* in the list, based on access counts.""" if p != self._data.first(): count = p.element()._count() walk = self._data.before(p) if count > walk.element( )._count: # Need to shift element forward/up the positional list. # You're not at the head of the LL & Current count is larger than next count. while (walk != self._data.first()) and ( count > self._data.before(walk).element()._count): walk = self._data.before( walk ) # Continue backward traversal through linked list. self._data.add_before(walk, self._data.delete( p)) # Insert element at correct position in list. # ----- Public Methods ----- # def __init__(self): """Create an empty list of favorites.""" self._data = PositionalList( ) # Will be a list of _Item instances (from nested class above) def __len__(self): """Return number of elements in favorites list.""" return len(self._data) def is_empty(self): """Return True if favorites list is empty.""" # return self._data.is_empty() return len(self._data) == 0 def access(self, e): """Access element 'e', and increase its frequency count.""" elem_pos = self._find_position(e) # Must add element if doesn't currently exist in the favorites list. if elem_pos is None: elem_pos = self._data.add_last(self._Item(e)) ## Don't need because we are not returning anything. # elem_node = self._data._validate(elem_pos) # elem = elem_node._element elem_pos.element()._count += 1 self._move_up(elem_pos) def remove(self, e): """Remove element 'e' from favorites list.""" p = self._find_position(e) if p is not None: self._data.delete(p) def top(self, k): """Generate a sequence (create a generator for) of the top 'k' elements, with respect to access counts.""" if not 1 <= k <= len(self): raise ValueError("'k' value outside of range.") ## Don't need because we are not returning a list, only making a generator. # top = list() walk = self._data.first() for i in range(k): item = walk.element() elem = item._value # top.append(elem) yield elem walk = self._data.after(walk)
class FavoritesList: """List of elements ordered from most frequently accessed to least.""" # ------------------------------ nested _Item class ------------------------------ class _Item: __slots__ = '_value', '_count' # streamline memory usage def __init__(self, e): self._value = e # the user's element self._count = 0 # access count initially zero # ------------------------------- nonpublic utilities ------------------------------- def _find_position(self, e): """Search for element e and return its Position (or None if not found).""" walk = self._data.first() while walk is not None and walk.element()._value != e: walk = self._data.after(walk) return walk def _move_up(self, p): """Move item at Position p earlier in the list based on access count.""" if p != self._data.first(): # consider moving... cnt = p.element()._count walk = self._data.before(p) if cnt > walk.element()._count: # must shift forward while (walk != self._data.first() and cnt > self._data.before(walk).element()._count): walk = self._data.before(walk) self._data.add_before(walk, self._data.delete(p)) # delete/reinsert # ------------------------------- public methods ------------------------------- def __init__(self): """Create an empty list of favorites.""" self._data = PositionalList() # will be list of _Item instances def __len__(self): """Return number of entries on favorites list.""" return len(self._data) def is_empty(self): """Return True if list is empty.""" return len(self._data) == 0 def access(self, e): """Access element e, thereby increasing its access count.""" p = self._find_position(e) # try to locate existing element if p is None: p = self._data.add_last(self._Item(e)) # if new, place at end p.element()._count += 1 # always increment count self._move_up(p) # consider moving forward def remove(self, e): """Remove element e from the list of favorites.""" p = self._find_position(e) # try to locate existing element if p is not None: self._data.delete(p) # delete, if found def top(self, k): """Generate sequence of top k elements in terms of access count.""" if not 1 <= k <= len(self): raise ValueError('Illegal value for k') walk = self._data.first() for j in range(k): item = walk.element() # element of list is _Item yield item._value # report user's element walk = self._data.after(walk) def __repr__(self): """Create string representation of the favorites list.""" return ', '.join('({0}:{1})'.format(i._value, i._count) for i in self._data)
class FavouritesList: """ An abstract data type storing a sequence of elements in order of their access count i.e. the most popular/most accessed elements occur first. Uses a doubly linked list as underlying storage """ class _Item: """ a composite object containing an element of the favourites list as well as its access count """ def __init__(self, e): self._value = e self._count = 0 def _find_position(self, e): """ find the position in the list where e is stored or return None """ walk = self._data.first() while walk is not None and walk.element()._value != e: walk = self._data.after(walk) return walk def _move_up(self, p): """ consider moving element at position p further ahead in the sequence to preserve the invariant i.e. elements of the sequence must be stored in non-increasing order. """ if p != self._data.first(): cnt = p.element()._count walk = self._data.before(p) if cnt > walk.element()._count: while walk != self._data.first() and cnt > self._data.before( walk).element()._count: walk = self._data.before(walk) self._data.add_before(walk, self._data.delete(p)) def __init__(self): self._data = PositionalList() def __len__(self): return len(self._data) def is_empty(self): return len(self) == 0 def access(self, e): """ access element e and increase its access count. """ p = self._find_position(e) if p is None: p = self._data.add_last(self._Item(e)) p.element()._count += 1 self._move_up(p) def remove(self, e): p = self._find_position(e) if p is not None: self._data.delete(p) def top(self, k): """ return an iteration of the top k most accessed elements of the list """ if not 1 <= k <= len(self): raise ValueError("Invalid value of k.") walk = self._data.first() for i in range(k): yield walk.element()._value walk = self._data.after(walk)
class FavoritesList: """List of elements ordered from most frequently accessed to least.""" # ------------------------------ nested _Item class ----------------------- class _Item: __slots__ = "_value", "_count" # streamline memory usage def __init__(self, e): self._value = e # the user's element self._count = 0 # access count initially zero # ------------------------------- nonpublic utilities --------------------- def _find_position(self, e): """Search for element e and return its Position (or None if not found).""" walk = self._data.first() while walk is not None and walk.element()._value != e: walk = self._data.after(walk) return walk def _move_up(self, p): """Move item at Position p earlier in the list based on access count.""" if p != self._data.first(): # consider moving... cnt = p.element()._count walk = self._data.before(p) if cnt > walk.element()._count: # must shift forward while walk != self._data.first() and cnt > self._data.before(walk).element()._count: walk = self._data.before(walk) self._data.add_before(walk, self._data.delete(p)) # delete/reinsert # ------------------------------- public methods -------------------------- def __init__(self): """Create an empty list of favorites.""" self._data = PositionalList() # will be list of _Item instances def __len__(self): """Return number of entries on favorites list.""" return len(self._data) def is_empty(self): """Return True if list is empty.""" return len(self._data) == 0 def access(self, e): """Access element e, thereby increasing its access count.""" p = self._find_position(e) # try to locate existing element if p is None: p = self._data.add_last(self._Item(e)) # if new, place at end p.element()._count += 1 # always increment count self._move_up(p) # consider moving forward def remove(self, e): """Remove element e from the list of favorites.""" p = self._find_position(e) # try to locate existing element if p is not None: self._data.delete(p) # delete, if found def top(self, k): """Generate sequence of top k elements in terms of access count.""" if not 1 <= k <= len(self): raise ValueError("Illegal value for k") walk = self._data.first() for j in range(k): item = walk.element() # element of list is _Item yield item._value # report user's element walk = self._data.after(walk) def __repr__(self): """Create string representation of the favorites list.""" return ", ".join("({0}:{1})".format(i._value, i._count) for i in self._data)