import unittest

class Empty(Exception):
    pass

class _DoublyLinkedBase(object):
    """A base class providing a doubly linked list representation."""

    class _Node:
        """Lightweight, nonpublic class for storing a doubly linked node."""
        __slots__ = '_element', '_prev', '_next'    # streamline memory

        def __init__(self, element, prev, next):    # initialize node's fields
            self._element = element                 # user's element
            self._prev = prev                       # previous node reference
            self._next = next                       # next node reference

    def __init__(self):
        """Create an empty list."""
        self._header = self._Node(None, None, None)
        self._trailer = self._Node(None, None, None)
        self._header._next = self._trailer          # trailer is after header
        self._trailer._prev = self._header          # header is before trailer
        self._size = 0

    def __len__(self):
        """Return the number of elements in the list."""
        return self._size

    def is_empty(self):
        """Return True if list is empty."""
        return self._size == 0

    def _insert_between(self, e, predecessor, successor):
        """Add element e between two existing nodes and return new node."""
        newest = self._Node(e, predecessor, successor)  # linked to neighbors
        predecessor._next = newest
        successor._prev = newest
        self._size += 1
        return newest

    def _delete_node(self, node):
        """Delete nonsentinel node from the list and return its element."""
        predecessor = node._prev
        successor = node._next
        predecessor._next = successor
        successor._prev = predecessor
        self._size -= 1
        element = node._element                         # record deleted element
        node._prev = node._next = node._element = None  # deprecate node
        return element                                  # return deleted element

class LinkedDeque(_DoublyLinkedBase):           # note the use of inheritance
    """Double-ended queue implementation based on a doubly linked list."""

    def first(self):
        """Return (but do not remove) the element at the front of the deque."""
        if self.is_empty():
            raise Empty('Deque is empty')
        return self._header._next._element      # real item just after header

    def last(self):
        """Return (but do not remvoe) the element at the back of the deque."""
        if self.is_empty():
            raise Empty('Deque is empty')
        return self._trailer._prev._element     # real item just before trailer

    def insert_first(self, e):
        """Add an element to the front of the deque."""
        self._insert_between(e, self._header, self._header._next) # after header

    def insert_last(self, e):
        """Add an element to the back of the deque."""
        self._insert_between(e, self._trailer._prev, self._trailer) # before trailer

    def delete_first(self):
        """Remove and return the element from the front of the deque.

        Raise Empty exception if the deque is empty.
        """
        if self.is_empty():
            raise Empty('Deque is empty')
        return self._delete_node(self._header._next)    # use inherited method

    def delete_last(self):
        """Remove and return the element from the back of the deque.

        Raise Empty exception if the deque is empty.
        """
        if self.is_empty():
            raise Empty('Deque is empty')
        return self._delete_node(self._trailer._prev)    # use inherited method

class PositionalList(_DoublyLinkedBase):
    """A sequential container of elements allowing positional access."""

    class Position:
        """An abstraction representing the location of a single element."""

        def __init__(self, container, node):
            """Constructor should not be invoked by user."""
            self._container = container
            self._node = node

        def element(self):
            """Return the element stored at this Position."""
            return self._node._element

        def __eq__(self, other):
            """Return True if other is a Position representing the same location."""
            return type(other) is type(self) and other._node is self._node

        def __ne__(self, other):
            """Return True if other does not represent the same location."""
            return not (self == other)      # opposite of __eq__

    def _validate(self, p):
        """Return position's node, or raise appropriate error if invalid."""
        if not isinstance(p, self.Position):
            raise TypeError('p must be proper Position type')
        if p._container is not self:
            raise ValueError('p does not belong to this container')
        if p._node._next is None:       # convention for deprecated nodes
            raise ValueError('p is no longer valid')
        return p._node

    def _make_position(self, node):
        """Return Position instance for given node (or None if sentinel)."""
        if node is self._header or node is self._trailer:
            return None                         # boundary violation
        else:
            return self.Position(self, node)    # legitimate position

    def first(self):
        """Return the first Position in the list (or None if list is empty)."""
        return self._make_position(self._header._next)

    def last(self):
        """Return the last Position in the list (or None if list is empty)."""
        return self._make_position(self._trailer._prev)

    def before(self, p):
        """Return the Position jsut before Position p (or None if p is first)."""
        node = self._validate(p)
        return self._make_position(node._prev)

    def after(self, p):
        """Return the Position jsut before Position p (or None if p is last)."""
        node = self._validate(p)
        return self._make_position(node._next)

    def __iter__(self):
        """Generate a forward iteration of the elements of the list."""
        cursor = self.first()
        while cursor is not None:
            yield cursor.element()
            cursor = self.after(cursor)

    # override inherited version to return Position, rather than Node
    def _insert_between(self, e, predecessor, successor):
        """Add element between existing nodes and return new Position."""
        node = super(PositionalList, self)._insert_between(e, predecessor, successor)
        return self._make_position(node)

    def add_first(self, e):
        """Insert element e at the front of the list and return new Position."""
        return self._insert_between(e, self._header, self._header._next)

    def add_last(self, e):
        """Insert element e at the back of the list and return new Position."""
        return self._insert_between(e, self._trailer._prev, self._trailer)

    def add_before(self, p, e):
        """Insert element e into list before Position p and return new Position."""
        original = self._validate(p)
        return self._insert_between(e, original._prev, original)

    def add_after(self, p, e):
        """Insert element e into list after Position p and return new Position."""
        original = self._validate(p)
        return self._insert_between(e, original, original._next)

    def delete(self, p):
        """Remove and return the element at Position p."""
        original = self._validate(p)
        return self._delete_node(original)  # inherited method returns element

    def replace(self, p, e):
        """Replace the element at Position p with e.

        Return the elemetn formerly a Position p.
        """
        original = self._validate(p)
        old_value = original._element       # temporarily store old element
        original._element = e               # replace with new element
        return old_value                    # return the old element value

def insertion_sort(L):
    """Sort PositionList of comparable elements into nondecreasing order."""
    if len(L) > 1:                      # otherwise, no need to sort it
        marker = L.first()
        while marker != L.last():
            pivot = L.after(marker)     # next item to place
            value = pivot.element()
            if value > marker.element():    # pivot is already sorted
                marker = pivot              # pivot becomes new marker
            else:                           # must relocate pivot
                walk = marker               # find leftmost item greater than value
                while walk != L.first() and L.before(walk).element() > value:
                    walk = L.before(walk)
                L.delete(pivot)
                L.add_before(walk, value)   # reinsert value before walk

class FavoritesList:
    """List of elements ordered from most frequently accessed to least."""

    class _Item:
        __slots__ = '_value', '_count'      # streamline memeory usage
        def __init__(self, e):
            self._value = e                 # the user's element
            self._count = 0                 # access count initially zero

    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

    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)

class FavoritesListMTF(FavoritesList):
    """List of elements ordered with move-to-front heuristic."""

    # we override _move_up to provide move-to-front semantics
    def _move_up(self, p):
        """Move accessed item at Position p to front of list."""
        if p != self._data.first():
            self._data.add_first(self._data.delete(p))      # delete/reinsert

    # we override top because list is no longer sorted
    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 reprot 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 teh element with highest count
            yield highPos.element()._value  # report element to user
            temp.delete(highPos)            # remove from temp list

class DequeTests(unittest.TestCase):

    def test_deque(self):
        dq = LinkedDeque()
        self.assertTrue(dq.is_empty())
        dq.insert_first(13)
        self.assertEqual(13, dq.first())
        self.assertEqual(13, dq.last())
        self.assertEqual(1, len(dq))

class PositionalListTests(unittest.TestCase):

    def test_positional_list(self):
        pl = PositionalList()
        self.assertTrue(pl.is_empty())
        pl.add_first(5)
        pl.add_first(3)
        pl.add_last(7)
        self.assertEqual(3, len(pl))

    def test_insertion_sort(self):
        pl = PositionalList()
        pl.add_last(15)
        pl.add_last(22)
        pl.add_last(25)
        pl.add_last(29)
        pl.add_last(36)
        pl.add_last(23)
        insertion_sort(pl)
        self.assertEqual(23, pl.after(pl.after(pl.first())).element())

class FavoritesListTests(unittest.TestCase):

    def test_favorites_list(self):
        fl = FavoritesList()
        fl.access(13)
        fl.access(17)
        fl.access(13)
        fl.access(23)
        fl.access(23)
        fl.access(23)
        self.assertEqual([23, 13, 17], list(fl.top(3)))

class FavoritesListMTFTests(unittest.TestCase):

    def test_favorites_list_mft(self):
        fl = FavoritesList()
        fl.access(13)
        fl.access(17)
        fl.access(13)
        fl.access(23)
        fl.access(23)
        fl.access(23)
        self.assertEqual([23, 13, 17], list(fl.top(3)))
        
if __name__ == '__main__':
    unittest.main()

import unittest

class Empty(Exception):
    pass

class _DoublyLinkedBase(object):
    """A base class providing a doubly linked list representation."""

    class _Node:
        """Lightweight, nonpublic class for storing a doubly linked node."""
        __slots__ = '_element', '_prev', '_next'    # streamline memory

        def __init__(self, element, prev, next):    # initialize node's fields
            self._element = element                 # user's element
            self._prev = prev                       # previous node reference
            self._next = next                       # next node reference

    def __init__(self):
        """Create an empty list."""
        self._header = self._Node(None, None, None)
        self._trailer = self._Node(None, None, None)
        self._header._next = self._trailer          # trailer is after header
        self._trailer._prev = self._header          # header is before trailer
        self._size = 0

    def __len__(self):
        """Return the number of elements in the list."""
        return self._size

    def is_empty(self):
        """Return True if list is empty."""
        return self._size == 0

    def _insert_between(self, e, predecessor, successor):
        """Add element e between two existing nodes and return new node."""
        newest = self._Node(e, predecessor, successor)  # linked to neighbors
        predecessor._next = newest
        successor._prev = newest
        self._size += 1
        return newest

    def _delete_node(self, node):
        """Delete nonsentinel node from the list and return its element."""
        predecessor = node._prev
        successor = node._next
        predecessor._next = successor
        successor._prev = predecessor
        self._size -= 1
        element = node._element                         # record deleted element
        node._prev = node._next = node._element = None  # deprecate node
        return element                                  # return deleted element

class LinkedDeque(_DoublyLinkedBase):           # note the use of inheritance
    """Double-ended queue implementation based on a doubly linked list."""

    def first(self):
        """Return (but do not remove) the element at the front of the deque."""
        if self.is_empty():
            raise Empty('Deque is empty')
        return self._header._next._element      # real item just after header

    def last(self):
        """Return (but do not remvoe) the element at the back of the deque."""
        if self.is_empty():
            raise Empty('Deque is empty')
        return self._trailer._prev._element     # real item just before trailer

    def insert_first(self, e):
        """Add an element to the front of the deque."""
        self._insert_between(e, self._header, self._header._next) # after header

    def insert_last(self, e):
        """Add an element to the back of the deque."""
        self._insert_between(e, self._trailer._prev, self._trailer) # before trailer

    def delete_first(self):
        """Remove and return the element from the front of the deque.

        Raise Empty exception if the deque is empty.
        """
        if self.is_empty():
            raise Empty('Deque is empty')
        return self._delete_node(self._header._next)    # use inherited method

    def delete_last(self):
        """Remove and return the element from the back of the deque.

        Raise Empty exception if the deque is empty.
        """
        if self.is_empty():
            raise Empty('Deque is empty')
        return self._delete_node(self._trailer._prev)    # use inherited method

class PositionalList(_DoublyLinkedBase):
    """A sequential container of elements allowing positional access."""

    class Position:
        """An abstraction representing the location of a single element."""

        def __init__(self, container, node):
            """Constructor should not be invoked by user."""
            self._container = container
            self._node = node

        def element(self):
            """Return the element stored at this Position."""
            return self._node._element

        def __eq__(self, other):
            """Return True if other is a Position representing the same location."""
            return type(other) is type(self) and other._node is self._node

        def __ne__(self, other):
            """Return True if other does not represent the same location."""
            return not (self == other)      # opposite of __eq__

    def _validate(self, p):
        """Return position's node, or raise appropriate error if invalid."""
        if not isinstance(p, self.Position):
            raise TypeError('p must be proper Position type')
        if p._container is not self:
            raise ValueError('p does not belong to this container')
        if p._node._next is None:       # convention for deprecated nodes
            raise ValueError('p is no longer valid')
        return p._node

    def _make_position(self, node):
        """Return Position instance for given node (or None if sentinel)."""
        if node is self._header or node is self._trailer:
            return None                         # boundary violation
        else:
            return self.Position(self, node)    # legitimate position

    def first(self):
        """Return the first Position in the list (or None if list is empty)."""
        return self._make_position(self._header._next)

    def last(self):
        """Return the last Position in the list (or None if list is empty)."""
        return self._make_position(self._trailer._prev)

    def before(self, p):
        """Return the Position jsut before Position p (or None if p is first)."""
        node = self._validate(p)
        return self._make_position(node._prev)

    def after(self, p):
        """Return the Position jsut before Position p (or None if p is last)."""
        node = self._validate(p)
        return self._make_position(node._next)

    def __iter__(self):
        """Generate a forward iteration of the elements of the list."""
        cursor = self.first()
        while cursor is not None:
            yield cursor.element()
            cursor = self.after(cursor)

    # override inherited version to return Position, rather than Node
    def _insert_between(self, e, predecessor, successor):
        """Add element between existing nodes and return new Position."""
        node = super(PositionalList, self)._insert_between(e, predecessor, successor)
        return self._make_position(node)

    def add_first(self, e):
        """Insert element e at the front of the list and return new Position."""
        return self._insert_between(e, self._header, self._header._next)

    def add_last(self, e):
        """Insert element e at the back of the list and return new Position."""
        return self._insert_between(e, self._trailer._prev, self._trailer)

    def add_before(self, p, e):
        """Insert element e into list before Position p and return new Position."""
        original = self._validate(p)
        return self._insert_between(e, original._prev, original)

    def add_after(self, p, e):
        """Insert element e into list after Position p and return new Position."""
        original = self._validate(p)
        return self._insert_between(e, original, original._next)

    def delete(self, p):
        """Remove and return the element at Position p."""
        original = self._validate(p)
        return self._delete_node(original)  # inherited method returns element

    def replace(self, p, e):
        """Replace the element at Position p with e.

        Return the elemetn formerly a Position p.
        """
        original = self._validate(p)
        old_value = original._element       # temporarily store old element
        original._element = e               # replace with new element
        return old_value                    # return the old element value

def insertion_sort(L):
    """Sort PositionList of comparable elements into nondecreasing order."""
    if len(L) > 1:                      # otherwise, no need to sort it
        marker = L.first()
        while marker != L.last():
            pivot = L.after(marker)     # next item to place
            value = pivot.element()
            if value > marker.element():    # pivot is already sorted
                marker = pivot              # pivot becomes new marker
            else:                           # must relocate pivot
                walk = marker               # find leftmost item greater than value
                while walk != L.first() and L.before(walk).element() > value:
                    walk = L.before(walk)
                L.delete(pivot)
                L.add_before(walk, value)   # reinsert value before walk

class FavoritesList:
    """List of elements ordered from most frequently accessed to least."""

    class _Item:
        __slots__ = '_value', '_count'      # streamline memeory usage
        def __init__(self, e):
            self._value = e                 # the user's element
            self._count = 0                 # access count initially zero

    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

    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)

class FavoritesListMTF(FavoritesList):
    """List of elements ordered with move-to-front heuristic."""

    # we override _move_up to provide move-to-front semantics
    def _move_up(self, p):
        """Move accessed item at Position p to front of list."""
        if p != self._data.first():
            self._data.add_first(self._data.delete(p))      # delete/reinsert

    # we override top because list is no longer sorted
    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 reprot 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 teh element with highest count
            yield highPos.element()._value  # report element to user
            temp.delete(highPos)            # remove from temp list

class DequeTests(unittest.TestCase):

    def test_deque(self):
        dq = LinkedDeque()
        self.assertTrue(dq.is_empty())
        dq.insert_first(13)
        self.assertEqual(13, dq.first())
        self.assertEqual(13, dq.last())
        self.assertEqual(1, len(dq))

class PositionalListTests(unittest.TestCase):

    def test_positional_list(self):
        pl = PositionalList()
        self.assertTrue(pl.is_empty())
        pl.add_first(5)
        pl.add_first(3)
        pl.add_last(7)
        self.assertEqual(3, len(pl))

    def test_insertion_sort(self):
        pl = PositionalList()
        pl.add_last(15)
        pl.add_last(22)
        pl.add_last(25)
        pl.add_last(29)
        pl.add_last(36)
        pl.add_last(23)
        insertion_sort(pl)
        self.assertEqual(23, pl.after(pl.after(pl.first())).element())

class FavoritesListTests(unittest.TestCase):

    def test_favorites_list(self):
        fl = FavoritesList()
        fl.access(13)
        fl.access(17)
        fl.access(13)
        fl.access(23)
        fl.access(23)
        fl.access(23)
        self.assertEqual([23, 13, 17], list(fl.top(3)))

class FavoritesListMTFTests(unittest.TestCase):

    def test_favorites_list_mft(self):
        fl = FavoritesList()
        fl.access(13)
        fl.access(17)
        fl.access(13)
        fl.access(23)
        fl.access(23)
        fl.access(23)
        self.assertEqual([23, 13, 17], list(fl.top(3)))
        
if __name__ == '__main__':
    unittest.main()

A base class providing a doubly linked list representation. Lightweight, nonpublic class for storing a doubly linked node. # streamline memory # initialize node's fields # user's element # previous node reference # next node reference Create an empty list. # trailer is after header # header is before trailer Return the number of elements in the list. Return True if list is empty. Add element e between two existing nodes and return new node. # linked to neighbors Delete nonsentinel node from the list and return its element. # record deleted element # deprecate node # return deleted element # note the use of inheritance Double-ended queue implementation based on a doubly linked list. Return (but do not remove) the element at the front of the deque. # real item just after header Return (but do not remvoe) the element at the back of the deque. # real item just before trailer Add an element to the front of the deque. # after header Add an element to the back of the deque. # before trailer Remove and return the element from the front of the deque.          Raise Empty exception if the deque is empty. # use inherited method Remove and return the element from the back of the deque.          Raise Empty exception if the deque is empty. # use inherited method A sequential container of elements allowing positional access. An abstraction representing the location of a single element. Constructor should not be invoked by user. Return the element stored at this Position. Return True if other is a Position representing the same location. Return True if other does not represent the same location. # opposite of __eq__ Return position's node, or raise appropriate error if invalid. # convention for deprecated nodes Return Position instance for given node (or None if sentinel). # boundary violation # legitimate position Return the first Position in the list (or None if list is empty). Return the last Position in the list (or None if list is empty). Return the Position jsut before Position p (or None if p is first). Return the Position jsut before Position p (or None if p is last). Generate a forward iteration of the elements of the list. # override inherited version to return Position, rather than Node Add element between existing nodes and return new Position. Insert element e at the front of the list and return new Position. Insert element e at the back of the list and return new Position. Insert element e into list before Position p and return new Position. Insert element e into list after Position p and return new Position. Remove and return the element at Position p. # inherited method returns element Replace the element at Position p with e.          Return the elemetn formerly a Position p. # temporarily store old element # replace with new element # return the old element value Sort PositionList of comparable elements into nondecreasing order. # otherwise, no need to sort it # next item to place # pivot is already sorted # pivot becomes new marker # must relocate pivot # find leftmost item greater than value # reinsert value before walk List of elements ordered from most frequently accessed to least. # streamline memeory usage # the user's element # access count initially zero Search for element e and return its Position (or None if not found). Move item at Position p earlier in the list based on access count. # consider moving... # must shift forward # delete/reinsert Create an empty list of favorites. # will be list of _Item instances Return number of entries on favorites list. Return True if list is empty. Access element e, thereby increasing its access count. # try to locate existing element # if new, place at end # always increment count # consider moving forward Remove element e from the list of favorites. # try to locate existing element # delete, if found Generate sequence of top k elements in terms of access count. # element of list is _Item # report user's element List of elements ordered with move-to-front heuristic. # we override _move_up to provide move-to-front semantics Move accessed item at Position p to front of list. # delete/reinsert # we override top because list is no longer sorted Generate sequence of top k elements in terms of access count. # we begin by making a copy of the original list # positional lists support iteration # we repeatedly find, report, and remove element with largest count # find and reprot next highest from temp # we have found teh element with highest count # report element to user # remove from temp list