Example #1
0
class FavoritesList:
    class _Item:
        __slots__ = '_value', '_count'

        def __init__(self, v):
            self._value = v
            self._count = 0

    def _find_position(self, e):
        """ Search for element e and return its Position """
        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():
            walk = self._data.before(p)
            cnt = p.element()._count
            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))

    """ ==================================Public Methods==================================== """

    def __init__(self):
        self._data = PositionalList()

    def __len__(self):
        return len(self._data)

    def is_empty(self):
        return self._data.is_empty()

    def access(self, e):
        """ Access element e, thereby increasing 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):
        if not 1 <= k <= len(self):
            raise ValueError("Illegal value for k")
        walk = self._data.first()
        for _ in range(k):
            item = walk.element()._value
            yield item
            walk = self._data.after(walk)
class UnsortedPriorityQueue(PriorityQueueBase):
    """A min-oriented priority queue implemented with an unsorted list"""
    def __init__(self):
        self._data = PositionalList()

    def _find_min(self):
        """Return Position of item with minimum key"""
        if self._data.is_empty():  # empty queue
            raise ValueError("Empty Priority Queue")
        small = self._data.first()
        walk = self._data.after(small)
        while walk != None:
            # find a item with smaller key or higher priority
            if small.element() > walk.element():
                small = walk
            walk = self._data.after(walk)
        return small

    def __len__(self):
        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"""
        item = self._find_min().element()
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key"""
        p = self._find_min()  # find the position
        item = self._data.delete(
            p)  # delete the position and return the element
        return item._key, item._value