Пример #1
0
 def __init__(self):
     '''
     (WackyQueue) -> NoneType
     REQ: oddlist and evenlist must be link list
     '''
     self._oddlist = WackyNode(None, None)  # dummy node
     self._evenlist = WackyNode(None, None)  # dummy node
Пример #2
0
 def __init__(self):
     '''(WackyQueue) -> NoneType
     constructs an empty queue
     '''
     # Representation invariant:
     self._head1 = WackyNode(None, None)
     self._head2 = WackyNode(None, None)
Пример #3
0
 def insert(self, obj, pri):
     '''(WackyQueue, obj, int) -> NoneType
     insert an object to queue, whose priority = pri and item = obj
     '''
     # create a new node with obj and pri given
     new_node = WackyNode(obj, pri)
     # set 3 pointers that point to 2 head nodes and the 1st node
     prev = self._head1
     curr = self._head2
     next = self._head1.get_next()
     # find the right place for insertion by comparing the priority of
     # the current object and the objects that are already in the queue
     while (next is not None) and (next.get_priority() >= pri):
         # move to the next node
         now = next
         next = curr.get_next()
         prev = curr
         curr = now
     # when find the right place
     # insert the new node after the prev node
     prev.set_next(new_node)
     # if the curr node has a _next node
     if (curr.get_next() is not None):
         # set this node to be the _next of the new node
         new_node.set_next(curr.get_next())
     # set next node to be the _next of the curr node
     curr.set_next(next)
Пример #4
0
 def __init__(self):
     '''(WackyQueue) -> NoneType
     This is the init method in <WackyQueue> for initializing variables
     '''
     # create odd and even linked list both with a dummy WackyNode
     self._oddlist = WackyNode(None, 0)
     self._evenlist = WackyNode(None, 0)
Пример #5
0
    def insert(self, obj, pri, node=None, curr=None, next=None):
        if not node:  # for changepriority (in case you check for same node)
            node = WackyNode(obj, pri)
        if not curr:  # for changepriority (avoid starting from head)
            curr, next = self._oddlist, self._evenlist

        while curr.get_next() and curr.get_next().get_priority() >= pri:
            next, curr = curr.get_next(), next

        node.set_next(next.get_next())
        next.set_next(curr.get_next())
        curr.set_next(node)
Пример #6
0
    def __init__(self):
        '''(WackyQueue) -> NoneType
        constructs an empty queue
        '''
        # Representation invariant:
        # WackyQueue consists of two linked lists
        # _head1 is a dummy head of the linked list of odd nodes
        # _head2 is a dummy head of the linked list of even nodes
        # _head1.get_next() is the first node in the list of odd nodes
        # _head1.get_next() is the first node in the WackyQueue
        # _head2.get_next() is the first node in the list of even nodes
        # _head2.get_next() is the second node in the WackyQueue

        self._head1 = WackyNode(None, None)
        self._head2 = WackyNode(None, None)
Пример #7
0
 def __init__(self):
     '''(WackyQueue) -> None
     This method instanciates a WackyQueue
     '''
     # Representation Invariant
     # _size is how many objects the Queue contains
     # _head is the head of the one of the WackyQueues
     # _head2 is the second head of the WackyWueues
     # The hgher the number, the greater its priority
     # Which ever head holds 0 as its priority is the head of the odd
     # list
     # if self._head.get_priority is 0, it is the head of the odd list
     # if self._head2.get_priority is 0, it is the head of the odd list
     # END OF REPRESENTATION INVARIANT
     # Now cretaed the WackyHeads holding no information and
     # pointing to nothing
     # Make self._head's priotiry 0 by defualt to be the head of the odd
     # list, you will see why later.
     self._head = WackyNode(None, 0)
     self._head2 = WackyNode(None, 1)
Пример #8
0
    def __init__(self):
        ''' (WackyQueue) -> None
        Returns None and initializes all the instance variables needed for the
        class
        '''
        # Representation Invariant:
        # > what are the instances used and what data structure is used for
        # them?
        # _even_list is a linked list
        # _odd_list is a linked list
        # > what are the things inside of this data structure?
        # items inside _even_list and _odd_list are stored as WackyNodes
        # > what is the arrangement of these items, if they follow a specific
        #   pattern
        # _even_list stores all the objects that are inserted in even insertion
        # numbers (0, 2, 4...)
        # _odd_list stores all the objects that are inserted in odd insertion
        # numbers (1, 3, 5...)

        # initialize the lists with a nodes aka head
        self._odd_list = WackyNode(None, None)
        self._even_list = WackyNode(None, None)
Пример #9
0
    def insert(self, item, pri):
        '''(WackyQueue, obj, int) -> NoneType
        Insert a WackyNode with <item> object
        and <pri> as its priority into WackyQueue
        '''
        def insert_process(insert_node, before, after, gap, connect):
            '''(WackyNode, WackyNode, WackyNode, WackyNode,
            WackyNode) -> NoneType
            A helper function for the process when inserting a WackyNode
            in the WackyQueue, it organizes the WackyQueue in correct order
            after inserting
            '''
            # connect the insert WackyNode in correct order
            before.set_next(insert_node)
            insert_node.set_next(after)
            gap.set_next(connect)

        # create a WackyNode to insert
        new_node = WackyNode(item, pri)
        # initialize variables for looping by heapler function
        curr, oprev, ocurr, eprev, ecurr = set_variables(
            self._oddlist, self._evenlist)
        # create a flag. When flag is True, current and odd current are
        # at the same position, vise versa
        flag = True
        # loop through two linked list to find the insert position
        while curr and curr.get_priority() >= pri:
            # check if current and odd current are at the same position
            if flag:
                # Do the looping process by helper function
                curr, oprev, ocurr = loop_process(curr, oprev, ocurr,
                                                  curr.get_next(), ecurr)
            # else current and even current are at the same position
            else:
                # Do the looping process by helper function
                curr, eprev, ecurr = loop_process(curr, eprev, ecurr,
                                                  curr.get_next(), ocurr)
            # switch the state of flag
            flag = not flag
        # if current and odd current are at the same position after the loop
        if flag:
            # insert the new WackyNode in correct order by helper function
            insert_process(new_node, oprev, ecurr, eprev, ocurr)
        # else current and even current are at same position after the loop
        else:
            # insert the new WackyNode in correct order by helper function
            insert_process(new_node, eprev, ocurr, oprev, ecurr)
Пример #10
0
 def insert(self, obj, pri):
     '''(WackyQueue, object, int) -> NoneType
     Insert object obj with priority pri into the wacky queue
     '''
     # create a new Wacky Node
     Newnode = WackyNode(obj, pri)
     # case 1: it is the first inserted Node in the list, the list is empty
     if (self._Oddhead is None):
         self._Oddhead = Newnode
     else:
         # use help funtion to find the position whose
         # priority is less than pri
         cur, pre, double_pre, Oddcur, Evencur, is_end, is_odd =\
             self._find_pri_pos(pri)
         # use help function to insert the Newnode in the position
         self._insert_pos(Newnode, cur, pre, double_pre, Oddcur, Evencur,
                          is_end, is_odd)
Пример #11
0
 def changepriority(self, obj, pri):
     '''(WackyQueue, object, int) -> NoneType
     Change the priority of the first copy of object obj to pri.
     The wacky queue is unchanged if obj is not in it or already has
     priority pri.
     If the priority of obj is changed, then the insertion time of
     obj is taken to be the time of the changepriority operation.
     '''
     # find the first Node whose item is the object in this list
     # find whether there exist the same priority in the list
     # find the position whose pri is less than pri
     cur, pre, double_pre, is_same, cur_pri, pre_pri, double_pre_pri,\
         pri_Even, pri_Odd, pri_is_end, pri_is_odd\
         = self._first_obj_same_priority(obj, pri)
     # change the priority when obj is in it and do not have same pri
     if (is_same is False and cur is not None):
         # if the pri is less than the first object's pri and
         # large than or euql to the next node's pri
         # just change the priority for the first node
         if (cur == pre_pri or cur == cur_pri):
             cur.set_priority(pri)
         # it is the first oddlist node and the second last node in the list
         elif (cur.get_next() is None and self._Oddhead == cur
               and pri_is_end is True):
             cur.set_priority(pri)
             self._Evenhead = cur
             self._Oddhead = cur_pri
         # the first node is the second last node in list
         # and will be in the last
         elif (cur.get_next() is None and pre.get_next() is not None
               and pri < cur_pri.get_priority()):
             cur.set_priority(pri)
             double_pre.set_next(cur_pri)
             pre.set_next(cur)
         # the first node will switch the position with the node before it
         elif (pre == cur_pri and double_pre is not None
               and double_pre_pri is not None):
             cur.set_priority(pri)
             temp = cur.get_next()
             cur.set_next(cur_pri.get_next())
             double_pre_pri.set_next(cur)
             double_pre.set_next(cur_pri)
             cur_pri.set_next(temp)
         # the pri is less than first object and large than
         # the next node of next node of this object's pri
         elif (cur == double_pre_pri):
             cur.set_priority(pri)
             cur.set_next(pre_pri.get_next())
             pre_pri.set_next(cur_pri)
             # case 1: the first object is the first node in the odd list
             if (pre is None and double_pre is None):
                 self._Evenhead = cur
                 self._Oddhead = pre_pri
             # case 2: the first object is the first node in even list
             elif (double_pre is None and pre is not None):
                 pre.set_next(cur)
                 self._Evenhead = pre_pri
             # case 3: the general case
             else:
                 pre.set_next(cur)
                 double_pre.set_next(pre_pri)
         else:
             # remove this object from the list
             # case 1: the first object is the first node in odd list
             if (double_pre is None and pre is None):
                 # point the Oddhead to the Evenhead
                 # point the Evenhead to second node in the odd list
                 self._Oddhead = self._Evenhead
                 self._Evenhead = cur.get_next()
             # case 2: the first object is the first node in even list
             elif (double_pre is None and pre is not None):
                 # point Evenhead to the next node of pre
                 # point the pre node to next node of cur
                 self._Evenhead = pre.get_next()
                 pre.set_next(cur.get_next())
             # case 3: the general case
             else:
                 # remove the Node with first obj in the list
                 # set the next node of cur node to be
                 # the next node of pre node
                 # set the next node pf pre node to be the next
                 # node of double pre node
                 double_pre.set_next(pre.get_next())
                 pre.set_next(cur.get_next())
             # insert the Node to the sepcific position
             # create a new Wacky Node
             Newnode = WackyNode(obj, pri)
             # case 1: the list is empty
             if (self._Oddhead is None):
                 self._Oddhead = Newnode
             else:
                 self._insert_pos(Newnode, cur_pri, pre_pri, double_pre_pri,
                                  pri_Odd, pri_Even, pri_is_end, pri_is_odd)
        # Initialize the heads pointing to the 2 linked lists - odd and even
        self._odd_head = None
        self._even_head = None

""" ANNOTATION 2: Method should be less than 73 lines """
    def insert(self, item, priority):
""" END ANNOTATION 2 """
        ''' (WackyQueue, obj, int) -> NoneType
""" ANNOTATION 1: How do the priorities work? """
        Insert an item with a priority into the Wacky Queue.
        Duplicates are allowed - wacky queue may contain same copies of obj
        with same or different priorities.
""" END ANNOTATION 1 """
        '''
        # Create a new node that will be inserted into the wacky queue
        new_node = WackyNode(item, priority)

        # If the WackyQueue is empty, add the new node to the first position of
        # WackyQueue (first position of odd linked list)
        if self._odd_head is None:
            self._odd_head = new_node
        # If the WackyQueue contains only one node and if the new node has a
        # priority greater than the first node,
        elif ((self._even_head is None) and (new_node.get_priority() >
                                             self._odd_head.get_priority())):
            # Switch the first node to the second node's position and insert
            # new node to first node's position
            self._even_head = self._odd_head
            self._odd_head = new_node
        # If the WackyQueue contains only one node and if the priority of new
        # node is lesser than that of first node,
Пример #13
0
class WackyQueue():
    '''Class of WackyQueue'''
    def __init__(self):
        '''(WackyQueue) -> NoneType
        This is the init method in <WackyQueue> for initializing variables
        '''
        # create odd and even linked list both with a dummy WackyNode
        self._oddlist = WackyNode(None, 0)
        self._evenlist = WackyNode(None, 0)

    def insert(self, item, pri):
        '''(WackyQueue, obj, int) -> NoneType
        Insert a WackyNode with <item> object
        and <pri> as its priority into WackyQueue
        '''
        def insert_process(insert_node, before, after, gap, connect):
            '''(WackyNode, WackyNode, WackyNode, WackyNode,
            WackyNode) -> NoneType
            A helper function for the process when inserting a WackyNode
            in the WackyQueue, it organizes the WackyQueue in correct order
            after inserting
            '''
            # connect the insert WackyNode in correct order
            before.set_next(insert_node)
            insert_node.set_next(after)
            gap.set_next(connect)

        # create a WackyNode to insert
        new_node = WackyNode(item, pri)
        # initialize variables for looping by heapler function
        curr, oprev, ocurr, eprev, ecurr = set_variables(
            self._oddlist, self._evenlist)
        # create a flag. When flag is True, current and odd current are
        # at the same position, vise versa
        flag = True
        # loop through two linked list to find the insert position
        while curr and curr.get_priority() >= pri:
            # check if current and odd current are at the same position
            if flag:
                # Do the looping process by helper function
                curr, oprev, ocurr = loop_process(curr, oprev, ocurr,
                                                  curr.get_next(), ecurr)
            # else current and even current are at the same position
            else:
                # Do the looping process by helper function
                curr, eprev, ecurr = loop_process(curr, eprev, ecurr,
                                                  curr.get_next(), ocurr)
            # switch the state of flag
            flag = not flag
        # if current and odd current are at the same position after the loop
        if flag:
            # insert the new WackyNode in correct order by helper function
            insert_process(new_node, oprev, ecurr, eprev, ocurr)
        # else current and even current are at same position after the loop
        else:
            # insert the new WackyNode in correct order by helper function
            insert_process(new_node, eprev, ocurr, oprev, ecurr)

    def extracthigh(self):
        '''(WackyQueue) -> obj
        Remove and return the first item in the wacky queue
        REQ: WackyQueue is not empty
        '''
        # get the first WackyNode in odd linked list
        first = self._oddlist.get_next()
        # rearrange odd and even linked list to correct order after extracting
        self._oddlist.set_next(self._evenlist.get_next())
        self._evenlist.set_next(first.get_next())
        # return the first item
        return first.get_item()

    def isempty(self):
        '''(WackyQueue) -> bool
        Return Ture if WackyQueue is empty
        '''
        # return the result if oddlist is empty without dummy
        return self._oddlist.get_next() is None

    def changepriority(self, item, pri):
        '''(WackyQueue, obj, int) -> NoneType
        Change the priority of the first copy of object <item> to priority
        <pri>, the wacky queue is unchange if object is not in WackyQueue or
        already has priority <pri>
        '''
        def delete_process(prev1, curr1, prev2, curr2):
            '''(WackyNode, WackyNode, WackyNode, WackyNode) -> NoneType
            A helper function for the delete process when changing
            a WackyNode's priority in the WackyQueue, it organizes the
            WackyQueue in correct order after deleting the WackyNode
            '''
            # connect the rest of WackyNodes in correct order
            prev1.set_next(curr1)
            prev2.set_next(curr2.get_next())

        # initialize variables for looping by heapler function
        curr, oprev, ocurr, eprev, ecurr = set_variables(
            self._oddlist, self._evenlist)
        # loop through two linked list to find the first copy of object
        while curr and curr.get_item() != item:
            # check if current and odd current are at the same position
            if curr == ocurr:
                # Do the looping process by helper function
                curr, oprev, ocurr = loop_process(curr, oprev, ocurr,
                                                  curr.get_next(), ecurr)
            # else current and even current are at the same position
            else:
                # Do the looping process by helper function
                curr, eprev, ecurr = loop_process(curr, eprev, ecurr,
                                                  curr.get_next(), ocurr)
        # if the object exist and it doesn't have the same priority as we want
        if curr and curr.get_priority() != pri:
            # if current and odd current are at the same position after loop
            if curr == ocurr:
                # delete the WackyNode with the object and connect the rest
                # of WackyNodes in correct order by helper function
                delete_process(oprev, ecurr, eprev, ocurr)
            # else current and even current are at the same position after loop
            else:
                # delete the WackyNode with the object and connect the rest
                # of WackyNodes in correct order by helper function
                delete_process(eprev, ocurr, oprev, ecurr)
            # insert the object back with new priority
            self.insert(item, pri)

    def negateall(self):
        '''(WackyQueue) -> NoneType
        Negate the priority of every object in the wacky queue
        '''
        def negate_process(curr, prev):
            '''(WackyNode, WackyNode) -> WackyNode
            A helper function for the process of negating the priority of
            every object in the WackyQueue, it negates the <curr> WackyNode's
            priority and switch the order with <prev> WackyNode
            Return the WackyNode in next position of <curr> WackyNode
            '''
            # save the next WackyNode of current Node for future use
            temp = curr.get_next()
            # negate the current WackyNode's priority
            curr.set_priority(-curr.get_priority())
            # reverse the order with its previous WackyNode
            curr.set_next(prev)
            return temp

        def decide_head(odd_head, even_head):
            '''(WackyNode, WackyNode) -> NoneType
            A helper function for choosing heads for odd and even list after
            negating in WackyQueue
            '''
            # set the head of the odd and even list after dummy
            self._oddlist.set_next(odd_head)
            self._evenlist.set_next(even_head)

        # initialize current and previous position in odd list
        oprev = None
        ocurr = self._oddlist.get_next()
        # initialize current and previous position in even list
        eprev = None
        ecurr = self._evenlist.get_next()
        # initialize a position alternating at odd and even current
        curr = ocurr
        # create a flag. When flag is True, current and odd current are
        # at the same position, vise versa
        flag = True
        # loop through two linked list to find the insert position
        while curr:
            # check if current and odd current are at the same position
            if flag:
                # Do the negating process on current by helper function
                temp = negate_process(curr, oprev)
                # Do the looping process by helper function
                curr, oprev, ocurr = loop_process(curr, oprev, ocurr, temp,
                                                  ecurr)
            # else current and even current are at the same position
            else:
                # Do the negating process on current by helper function
                temp = negate_process(curr, eprev)
                # Do the looping process by helper function
                curr, eprev, ecurr = loop_process(curr, eprev, ecurr, temp,
                                                  ocurr)
            # switch the state of flag
            flag = not flag
        # if current and odd current are at the same position after loop
        # which means total amount of WackyNodes are even
        if flag:
            # choose the head for odd and even list by helper function
            # switching two linked list with each other
            decide_head(eprev, oprev)
        # else current and even current are at the same position after loop
        # which means total amount of WackyNodes are odd
        else:
            # choose the head for odd and even list by helper function
            decide_head(oprev, eprev)

    def getoddlist(self):
        '''(WackyQueue) -> NoneType
        Return a pointer to a linked list of WackyNodes in odd position
        in the WackyQueue
        If there is no first object, then an empty list is returned
        '''
        # return the pointer to linked list of WackyNodes in odd position
        return self._oddlist.get_next()

    def getevenlist(self):
        '''(WackyQueue) -> NoneType
        Return a pointer to a linked list of WackyNodes in even position
        in the WackyQueue
        If there is no second object, then an empty list is returned
        '''
        # return the pointer to linked list of WackyNodes in even position
        return self._evenlist.get_next()
Пример #14
0
    def insert(self, item, priority):
        ''' (WackyQueue, obj, int) -> None
        Returns None and inserts the object <item> at the given <priority>
        User can have duplicate objects at the same or at different priorities
        '''
        # in all scenarios we have to make a new node. Making a new wacky node
        # that points to none. We then have to assign new pointers to it and
        # make it part of the linked list family
        new_node = WackyNode(item, priority)
        # here comes the hard part! The part where pictures came in handy
        # thanks Nick for the drawing tip! Also, pri = priority in short :)
        # initialize curr to the head of the odd list
        curr = self._odd_list.get_next()
        after = self._even_list.get_next()
        # if curr is none, that is the odd list is empty
        if (curr is None):
            # then make the odd list point to the new node
            self._odd_list.set_next(new_node)
        # else if after in None, that is the even list is empty
        elif (after is None):
            # then add the new node to the even list
            self._even_list.set_next(new_node)
        # have a while loop that loops through the entire queue and looks
        # if the pri fits any of these case
        while (curr is not None) and (after is not None):
            # four cases:
            # 1- the general case, curr > insert > after
            if (curr.get_priority() > priority) and \
               (priority > after.get_priority()):
                # then curr and after don't get changed
                curr = curr  # this is causing the infinite loop
                after = after
                # the insert pointer algorithm: tho this will be repeated many
                # times in this function, only one of them will be executed
                # because of the elif structure
                # make curr point to the new node
                curr.set_next(new_node)
                # make after point to curr.next
                after.set_next(curr.get_next())
                # make new node point to after.next
                new_node.set_next(after.get_next())

            # 2- edge case: insert > curr
            elif (priority > curr.get_priority()):
                # then set after to be curr
                after = curr
                # and curr to be None
                curr = None
                # here our insert pointer algorithm will not work, because
                # None.any_method() will raise an exception
                # so here's the modified version of it:
                # since we're inserting at the head of the list, it will always
                # be inserted at the head of the odd list
                # make the head of the odd list point to the new node
                self._odd_list.set_next(new_node)
                # make head of the even point to the first node of odd
                self._even_list.set_next(after)
                # make the new node point to the first node of even
                new_node.set_next(after.get_next())

            # 3- multiple entries of the same pri
            elif (priority == curr.get_priority()):
                # this is super messy, but let's do it! find a priority that
                # is less than the one we have
                while not (after.get_priority() <
                           priority):  # crashes whn\en after becomes None
                    # set curr = after and after to the next node after curr
                    curr, after = after, curr.get_next()

            # 4- edge case: curr = None
            elif (curr is None):
                # then insert the new node at the end
                curr.set_next(new_node)
            # if they fit none of these cases, get new currs and afters
            else:
                curr, after = after, curr.get_next()
Пример #15
0
 def insert(self, obj, pri):
     '''(WackyQueue, object, int) -> None
     This method puts an object in the Wacky Queue depending on its
     priority
     '''
     # Create the new node
     new_node = WackyNode(obj, pri)
     # First you want to find the spot where the new node will go. 'in-head'
     # means the operation is currently in self._head and is loking for
     # where to insert the item
     # We also want to start comparing items from the top of the list
     if self._head.get_priority() is 0:
         current_check = 'in-head'
         current_node = self._head.get_next()
     elif self._head2.get_priority() is 0:
         current_check = 'in-head2'
         current_node = self._head2.get_next()
     # Next you want to make sure that the current node is not None
     if current_node is not None:
         current_pri = current_node.get_priority()
     # You want to keep track of what node was visited last in each list
     last_head_node = self._head
     last_head2_node = self._head2
     # Loop through BOTH lists, by alternating until you find the spot
     while (current_node is not None) and (pri <= current_pri):
         # create a condition that does alternate checking
         if current_check == 'in-head':
             # Keep track of both current and LAST Nodes
             last_head_node = current_node
             current_node = last_head2_node.get_next()
             # Next you want to make sure that the current node is not None
             if current_node is not None:
                 current_pri = current_node.get_priority()
             # Now to alternate make the current check to point to head2
             current_check = 'in-head2'
         elif current_check == 'in-head2':
             # Keep track of both current and LAST Nodes
             last_head2_node = current_node
             current_node = last_head_node.get_next()
             if current_node is not None:
                 current_pri = current_node.get_priority()
             # Now to alternate make the current check to point to head2
             current_check = 'in-head'
     # When the spot is found, depending on the obj of the head, that is
     # where you inserting it
     # Do not forget to push all the other items down the list
     # If the current_check is 'in-head', then you want to PUT the new node
     # in head
     if current_check == 'in-head':
         # Get the next node of the last node you visited in head2
         # Make the new node point to that
         new_node.set_next(last_head2_node.get_next())
         # Make the last node you visited in head2 point to the current node
         last_head2_node.set_next(current_node)
         # Make the last node you visited in head point to the new node
         last_head_node.set_next(new_node)
     # If the current_check is 'in-head2', then you want to PUT the new node
     # in head2
     elif current_check == 'in-head2':
         # Then get the next node of the last node you visited in head
         # Point the new node to the next node of the last node you visited
         # in head
         new_node.set_next(last_head_node.get_next())
         # Now point the last node you visited in head and point it to the
         # current node
         last_head_node.set_next(current_node)
         # Also, get the last node you visited before the current node,
         # then point that node to the new node.
         last_head2_node.set_next(new_node)
Пример #16
0
 def insert(self, obj, pri):
     '''
     (WackyQueue, obj, int) -> NoneType
     This function takes in an object with a priority
     and insert it into the proper position of the two link list
     REQ: the pri must be an integer
     '''
     # set the new node
     new_node = WackyNode(obj, pri)
     # set the basic pointers for the odd list
     prev = None
     curr = self._oddlist.get_next()
     # set the basic pointer for the even list
     prev_even = None
     curr_even = self._evenlist.get_next()
     # loop through every obj to find a place to insert
     while curr and curr_even and curr.get_priority() >= pri and\
           curr_even.get_priority() >= pri:
         # move forward the pointer on the odd list
         prev = curr
         curr = curr.get_next()
         # move forward the pointer on the even list
         prev_even = curr_even
         curr_even = curr_even.get_next()
     if not curr:
         if self._oddlist._next is None:
             self._oddlist.set_next(new_node)
         else:
             # if curr is none, then the new node is smaller than
             # both prev and prev_even
             prev.set_next(new_node)
     elif not curr_even:
         # if curr is not none but curr_even is none
         # there are two occations:
         if self._evenlist._next is None:
             if pri <= self._oddlist.get_next().get_priority():
                 self._evenlist.set_next(new_node)
             else:
                 self._evenlist.set_next(self._oddlist.get_next())
                 self._oddlist.set_next(new_node)
         else:
             if pri <= curr.get_priority():
                 # if pri is less than odd curr value
                 # then it is inserted into the even list at last
                 prev_even.set_next(new_node)
             else:
                 # if pri is bigger than curr value
                 # of course less or equal to prev_even value
                 # then the new node is inserted after the prev
                 prev.set_next(new_node)
                 prev_even.set_next(curr)
     elif pri > curr_even.get_priority() and pri <= curr.get_priority():
         # if pri is between the value of curr and curr_even
         # then the new node is inserted after the prev_even
         # link the new node with the curr position in even list
         if prev_even is None:
             self._evenlist.set_next(new_node)
         else:
             prev_even.set_next(new_node)
         # link the new node with the next object in odd list
         new_node.set_next(curr.get_next())
         # link the curr position in odd list
         # with the next object in even list
         curr.set_next(curr_even)
     elif pri > curr.get_priority():
         # if pri's value is bigger than curr's value
         # of course less or equal to prev_even value
         # link prev in odd list with new node
         if prev is None:
             self._oddlist.set_next(new_node)
         else:
             prev.set_next(new_node)
         # link the new node with the curr obj in even list
         new_node.set_next(curr_even)
         # link the prev position in even list with curr position in odd
         if prev_even is None:
             self._evenlist.set_next(curr)
         else:
             prev_even.set_next(curr)
Пример #17
0
class WackyQueue():
    '''This class represents a WackyQueue
    A WackyQUeue is queue that operates with WackyNodes
    It stores its data in two linked lists. Every odd object
    is in a list. And the other holds every even object
    '''
    def __init__(self):
        '''(WackyQueue) -> None
        This method instanciates a WackyQueue
        '''
        # Representation Invariant
        # _size is how many objects the Queue contains
        # _head is the head of the one of the WackyQueues
        # _head2 is the second head of the WackyWueues
        # The hgher the number, the greater its priority
        # Which ever head holds 0 as its priority is the head of the odd
        # list
        # if self._head.get_priority is 0, it is the head of the odd list
        # if self._head2.get_priority is 0, it is the head of the odd list
        # END OF REPRESENTATION INVARIANT
        # Now cretaed the WackyHeads holding no information and
        # pointing to nothing
        # Make self._head's priotiry 0 by defualt to be the head of the odd
        # list, you will see why later.
        self._head = WackyNode(None, 0)
        self._head2 = WackyNode(None, 1)

    def insert(self, obj, pri):
        '''(WackyQueue, object, int) -> None
        This method puts an object in the Wacky Queue depending on its
        priority
        '''
        # Create the new node
        new_node = WackyNode(obj, pri)
        # First you want to find the spot where the new node will go. 'in-head'
        # means the operation is currently in self._head and is loking for
        # where to insert the item
        # We also want to start comparing items from the top of the list
        if self._head.get_priority() is 0:
            current_check = 'in-head'
            current_node = self._head.get_next()
        elif self._head2.get_priority() is 0:
            current_check = 'in-head2'
            current_node = self._head2.get_next()
        # Next you want to make sure that the current node is not None
        if current_node is not None:
            current_pri = current_node.get_priority()
        # You want to keep track of what node was visited last in each list
        last_head_node = self._head
        last_head2_node = self._head2
        # Loop through BOTH lists, by alternating until you find the spot
        while (current_node is not None) and (pri <= current_pri):
            # create a condition that does alternate checking
            if current_check == 'in-head':
                # Keep track of both current and LAST Nodes
                last_head_node = current_node
                current_node = last_head2_node.get_next()
                # Next you want to make sure that the current node is not None
                if current_node is not None:
                    current_pri = current_node.get_priority()
                # Now to alternate make the current check to point to head2
                current_check = 'in-head2'
            elif current_check == 'in-head2':
                # Keep track of both current and LAST Nodes
                last_head2_node = current_node
                current_node = last_head_node.get_next()
                if current_node is not None:
                    current_pri = current_node.get_priority()
                # Now to alternate make the current check to point to head2
                current_check = 'in-head'
        # When the spot is found, depending on the obj of the head, that is
        # where you inserting it
        # Do not forget to push all the other items down the list
        # If the current_check is 'in-head', then you want to PUT the new node
        # in head
        if current_check == 'in-head':
            # Get the next node of the last node you visited in head2
            # Make the new node point to that
            new_node.set_next(last_head2_node.get_next())
            # Make the last node you visited in head2 point to the current node
            last_head2_node.set_next(current_node)
            # Make the last node you visited in head point to the new node
            last_head_node.set_next(new_node)
        # If the current_check is 'in-head2', then you want to PUT the new node
        # in head2
        elif current_check == 'in-head2':
            # Then get the next node of the last node you visited in head
            # Point the new node to the next node of the last node you visited
            # in head
            new_node.set_next(last_head_node.get_next())
            # Now point the last node you visited in head and point it to the
            # current node
            last_head_node.set_next(current_node)
            # Also, get the last node you visited before the current node,
            # then point that node to the new node.
            last_head2_node.set_next(new_node)

    def extracthigh(self):
        '''(WackyQueue) -> object
        This method removes and returns the first item in the WackyQueue.
        The object with the largest priority and inputed first amognst its
        equal priority is removed first
        REQ: The Queue is not empty
        '''
        # You want to extract from the top of the head that has the highest
        # priority in the queue
        if self._head.get_priority() is 0:
            top_item = self._head.get_next()
            new_top_item = top_item.get_next()
            # Now make head point to the new top item
            self._head.set_next(new_top_item)
            # Remember to change the priority of the head, because the new top
            # item is now in the other head
            self._head.set_priority(1)
            self._head2.set_priority(0)
        elif self._head2.get_priority() is 0:
            top_item = self._head2.get_next()
            new_top_item = top_item.get_next()
            # Now make head2 point to the new top item
            self._head2.set_next(new_top_item)
            # Now remember to change the priority of both heads
            self._head.set_priority(0)
            self._head2.set_priority(1)
        return top_item.get_item()

    def is_empty(self):
        '''(WackyQueue) -> bool
        This method returns True if the WackyQueue is empty and False if it is
        not
        '''
        # This part is simple, just get the next item to the dummy node
        # and check if it is None or a Node
        check_odd = self._head.get_next()
        check_even = self._head2.get_next()
        return check_odd is check_even is None

    def changepriority(self, obj, pri):
        '''(WackyQueue) -> None
        This method finds the first object of this priority and changes it to
        the priority that is given. Nothing is done if the object is not found
        '''
        # Now you want to find the first apperance of that object
        # start with the top of the list
        if self._head.get_priority() is 0:
            current_check = 'in-head'
            current_node = self._head.get_next()
        elif self._head2.get_priority() is 0:
            current_check = 'in-head2'
            current_node = self._head2.get_next()
        current_item = current_node.get_item()
        last_head_node = self._head
        last_head2_node = self._head2
        # Now you want to loop until you have found the object you are looking
        # for
        while (current_item is not obj) and (current_node is not None):
            # Again just like in insert, you want to start with the top of the
            # Queue
            if current_check == 'in-head':
                last_head_node = current_node
                current_node = last_head2_node.get_next()
                if current_node is not None:
                    current_item = current_node.get_item()
                current_check = 'in-head2'
            elif current_check == 'in-head2':
                last_head2_node = current_node
                current_node = last_head_node.get_next()
                if current_node is not None:
                    current_item = current_node.get_item()
                current_check = 'in-head'
        # Check if the current node is None first
        if ((current_node is not None) and
           (current_node.get_priority is not pri)):
            # After you have found the node that contains the object you need
            # to re-arrange the list
            if current_check == 'in-head':
                # So first if you left off at head, that is where you are
                # removing the node from
                # Get the previous head item you visited and point it to the
                # next item of the last head2 item you visited
                last_head_node.set_next(last_head2_node.get_next())
                # Now get the previous head2 item you visited and point it to
                # the next node of the current node
                last_head2_node.set_next(current_node.get_next())
                self.insert(obj, pri)
            # If you left off at head2, this is where you are removing the
            # item from
            elif current_check == 'in-head2':
                # get the previos head2 node and point it to the next item of
                # the previous head node you visited
                last_head2_node.set_next(last_head_node.get_next())
                # Then get the previous head node you visited to point it the
                # next item of the current node
                last_head_node.set_next(current_node.get_next())
                # Now you need to put back the new node into the list
                # use the insert method
                self.insert(obj, pri)

    def negate_all(self):
        '''(WackyQueue) -> None
        This method reveres the entry time of all the objects
        '''
        # Since your methods should be independent of the items in the list
        # when retrieving them, You want to 'just' flip both the odd and even
        # lists, luckily you have a helper function for this
        self._head = flip(self._head)
        self._head2 = flip(self._head2)
        # Now to get to the purpose of the function you have to negate all
        # the priorities in the Queue
        current_node = self._head.get_next()
        while current_node is not None:
            pri = current_node.get_priority()
            pri = pri * -1
            current_node.set_priority(pri)
            if current_node is not None:
                current_node = current_node.get_next()
        # Repeat the same steps for head2
        current_node = self._head2.get_next()
        while current_node is not None:
            pri = current_node.get_priority()
            pri = pri * -1
            current_node.set_priority(pri)
            if current_node is not None:
                current_node = current_node.get_next()
        # For the final step, since you do not remember what the last object
        # in the queue is. You need to check for the highest
        if (self._head.get_next() and self._head2.get_next() is not None):
            head_top_pri = self._head.get_next().get_priority()
            head2_top_pri = self._head2.get_next().get_priority()
            # Now you need see if you need a new top Node
            if head_top_pri > head2_top_pri:
                self._head.set_priority(0)
                self._head2.set_priority(1)
            elif head2_top_pri > head_top_pri:
                self._head2.set_priority(0)
                self._head.set_priority(1)

    def getoddlist(self):
        '''(WackyQueue) -> WackyNode
        This function returns a node that points to all the odd items in the
        queue
        '''
        # You know the first item on the list is the list is the one that has
        # priority 0
        if self._head.get_priority() is 0:
            odd_list = self._head.get_next()
        elif self._head2.get_priority() is 0:
            odd_list = self._head2.get_next()
        return odd_list

    def getevenlist(self):
        '''(WackyQueue) -> WackyNode
        This function returns a node that points to all the even items in the
        list
        '''
        # You know that which ever head whose priority is 1 has all the even
        # items
        if self._head.get_priority() is 1:
            even_list = self._head.get_next()
        elif self._head2.get_priority() is 1:
            even_list = self._head2.get_next()
        return even_list

    def __str__(self):
        '''(WackyQueue) -> str
        This method prints the contents of the WackyQueue
        '''
        current_node = self._head.get_next()
        current_node2 = self._head2.get_next()
        head_str = ''
        head2_str = ''
        top_head_str = ''
        top_head2_str = ''
        while current_node is not None:
            current_obj = current_node.get_item()
            head_str = head_str + str(current_obj) + ', '
            current_node = current_node.get_next()
        while current_node2 is not None:
            current_obj2 = current_node2.get_item()
            head2_str = head2_str + str(current_obj2) + ', '
            current_node2 = current_node2.get_next()
        # Check which head has the higher priority
        if self._head.get_priority() is 0:
            top_head_str = 'ODD-LIST -> '
            top_head2_str = 'EVEN-LIST -> '
        elif self._head2.get_priority() is 0:
            top_head2_str = 'ODD-LIST -> '
            top_head_str = 'EVEN-LIST -> '
Пример #18
0
class WackyQueue:
    ''' a sequence of objects that have integer priority i.e. the more
    positive the object, the higher the priority, and the more negative
    the object the lesser the priority '''
    def __init__(self):
        ''' (WackyQueue) -> None
        Returns None and initializes all the instance variables needed for the
        class
        '''
        # Representation Invariant:
        # > what are the instances used and what data structure is used for
        # them?
        # _even_list is a linked list
        # _odd_list is a linked list
        # > what are the things inside of this data structure?
        # items inside _even_list and _odd_list are stored as WackyNodes
        # > what is the arrangement of these items, if they follow a specific
        #   pattern
        # _even_list stores all the objects that are inserted in even insertion
        # numbers (0, 2, 4...)
        # _odd_list stores all the objects that are inserted in odd insertion
        # numbers (1, 3, 5...)

        # initialize the lists with a nodes aka head
        self._odd_list = WackyNode(None, None)
        self._even_list = WackyNode(None, None)

    def loop_even(self):
        ''' (WackyQueue) -> int
        Returns the size of the even linked list
        '''
        # initialize a counter
        size = 0
        # initialize the current node as head
        curr = self._even_list.get_next()
        # loop through the list till you're at the end of the list
        # how do you know that end? The current will point to None. You want to
        # stop as soon as current points to none
        while curr is not None:
            # in the loop, increase the counter by 1 and get the next element
            # set curr equal to that next element
            size += 1
            curr = curr.get_next()
        # return the counter (because the counter will be the size of the list)
        return size

    def loop_odd(self):
        ''' (WackyQueue) -> int
        Returns the size of the odd linked list
        '''
        # initialize a counter
        size = 0
        # initialize the current node as head
        curr = self._even_list.get_next()
        # loop through the list till you're at the end of the list
        # how do you know that end? The current will point to None. You want to
        # stop as soon as current points to none
        while curr is not None:
            # in the loop, increase the counter by 1 and get the next element
            # set curr equal to that next element
            size += 1
            curr = curr.get_next()
        # return the counter (because the counter will be the size of the list)
        return size

    def find_by_pri(self, priority):
        ''' (WackyQueue, int) -> WackyNode, WackyNode, WackyNode
        Returns a wacky node that points to the node with priority
        <priority> we are looking for, the node previous to it, and the node
        after it. (previous, current, after). If <priority> is not found,
        then previous will point to the last node of the list and
        current and after will point to None.
        REQ: <item> with <priority> has to be in the wacky queue
        REQ: wacky queue can not be empty
        '''
        # we want to alternate between our lists. Therefore, we need 3 pointers
        # one that points to the current node, one that points to the node
        # previous to it, and one that points to the previous of previous
        # (2 away from the current node). Why do we need so many pointers?
        # we want to keep track of the previous nodes. Since we're alternating
        # between lists, we want the third pointer to be pointing to the
        # previous list we checked, so that we can go back to that one again.

        # initialize all my pointers. curr will be head of the odd list, since
        # we start inserting from the odd list. prev and second_last will be
        # None
        second_last = None
        prev = None
        curr = self._odd_list
        # we need something to alternate lists. From Piazza, we can do this:
        # x, y = y, x. Setting our lists to variables
        curr_list, next_list = self._odd_list, self._even_list
        # while we are not at the end of the list and we haven't found the
        # priority yet
        while (curr is not None) and (curr.get_priority() is not priority):
            # change the lists (to alternate the lists)
            curr_list, next_list = next_list, curr_list
            # make second last point to where previous is pointing
            second_last = prev
            # then make the previous point to where current is pointing
            prev = curr
            # then make the current point to the next node in this list, which
            # is the one from the even list
            curr = curr_list.get_next()
        # two things will get you out of the loop: if the pri is found or if
        # curr is None which means that we've hit the end of our list
        # if curr is None, then everything else will be None too
        if curr is None:
            after = None
        else:
            after = curr_list.get_next()
        # return the nodes
        return prev, curr, after

    def find_by_item(self, item):
        ''' (WackyQueue, obj) -> WackyNode, WackyNode, WackyNode
        Returns a pointer to the node that contains the object <item>. If
        <item> is not in the list, None will be returned
        REQ: WackyQueue should have the item in it already
        '''
        # the algorithm is similar to find by pri, but instead of looking for
        # the pri, we are looking for the item
        # we will again need 3 pointers, for the same reasons as above (should
        # I just copy past my algorithm here, lol?) here:

        # initialize all my pointers. curr will be head of the odd list, since
        # we start inserting from the odd list. prev and second_last will be
        # None
        second_last = None
        prev = None
        curr = self._odd_list
        # we need something to alternate lists. From Piazza, we can do this:
        # x, y = y, x. Setting our lists to variables
        curr_list, next_list = self._odd_list, self._even_list
        # while we are not at the end of the list and we haven't found the
        # priority yet
        while (curr is not None) and (curr.get_item() is not item):
            # change the lists (to alternate the lists)
            curr_list, next_list = next_list, curr_list
            # make second last point to where previous is pointing
            second_last = prev
            # then make the previous point to where current is pointing
            prev = curr
            # then make the current point to the next node in this list, which
            # is the one from the even list
            curr = curr_list.get_next()
        # two things will get you out of the loop: if the item is found or if
        # curr is None which means that we've hit the end of our list
        # if curr is None, then everything else will be None too
        if curr is None:
            after = None
        else:
            after = curr_list.get_next()
        # return the nodes
        return prev, curr, after

    def reverse_list(self, linked_list):
        ''' (WackyQueue, WackyQueue) -> WackyNode
        Returns None and reverses the <linked_list> s.t. the head is the new
        tail and the tail is new head
        REQ: linked_list can not be empty
        '''
        # the algorithm is simple. initialize 3 pointers: before, current and
        # after where before is pointing to the node before current (i.e. None)
        # current is pointing to the the node whose pointer are being changed
        # and after is the pointer after the current node
        before = None
        curr = linked_list
        after = linked_list.get_next()
        # while we are not at the end of the list i.e. current is not None
        while (curr is not None):
            # set the pointer of the current node equal to previous
            curr.set_next(before)
            # make the previous pointer point to where current is pointing
            before = curr
            # make current point to where after is pointing
            curr = after
            # make after point to the next node to current
            after = curr.get_next()

    def negator(self, linked_list):
        ''' (WackyQueue, WackyQueue) -> None
        Negates the priorities of the <linked_list>
        REQ: linked_list is not empty
        '''
        # this one is fairly simple:
        # set curr to the head of the list
        curr = linked_list
        # loop through the list till you reach the end aka none
        while (curr is not None):
            # get each elements priority
            pri = curr.get_priority()
            # and negate it
            pri = -pri
            # then set the elements priority as it should be
            curr.set_priority(pri)
            # get the next element
            curr = curr.get_next()

    def insert(self, item, priority):
        ''' (WackyQueue, obj, int) -> None
        Returns None and inserts the object <item> at the given <priority>
        User can have duplicate objects at the same or at different priorities
        '''
        # in all scenarios we have to make a new node. Making a new wacky node
        # that points to none. We then have to assign new pointers to it and
        # make it part of the linked list family
        new_node = WackyNode(item, priority)
        # here comes the hard part! The part where pictures came in handy
        # thanks Nick for the drawing tip! Also, pri = priority in short :)
        # initialize curr to the head of the odd list
        curr = self._odd_list.get_next()
        after = self._even_list.get_next()
        # if curr is none, that is the odd list is empty
        if (curr is None):
            # then make the odd list point to the new node
            self._odd_list.set_next(new_node)
        # else if after in None, that is the even list is empty
        elif (after is None):
            # then add the new node to the even list
            self._even_list.set_next(new_node)
        # have a while loop that loops through the entire queue and looks
        # if the pri fits any of these case
        while (curr is not None) and (after is not None):
            # four cases:
            # 1- the general case, curr > insert > after
            if (curr.get_priority() > priority) and \
               (priority > after.get_priority()):
                # then curr and after don't get changed
                curr = curr  # this is causing the infinite loop
                after = after
                # the insert pointer algorithm: tho this will be repeated many
                # times in this function, only one of them will be executed
                # because of the elif structure
                # make curr point to the new node
                curr.set_next(new_node)
                # make after point to curr.next
                after.set_next(curr.get_next())
                # make new node point to after.next
                new_node.set_next(after.get_next())

            # 2- edge case: insert > curr
            elif (priority > curr.get_priority()):
                # then set after to be curr
                after = curr
                # and curr to be None
                curr = None
                # here our insert pointer algorithm will not work, because
                # None.any_method() will raise an exception
                # so here's the modified version of it:
                # since we're inserting at the head of the list, it will always
                # be inserted at the head of the odd list
                # make the head of the odd list point to the new node
                self._odd_list.set_next(new_node)
                # make head of the even point to the first node of odd
                self._even_list.set_next(after)
                # make the new node point to the first node of even
                new_node.set_next(after.get_next())

            # 3- multiple entries of the same pri
            elif (priority == curr.get_priority()):
                # this is super messy, but let's do it! find a priority that
                # is less than the one we have
                while not (after.get_priority() <
                           priority):  # crashes whn\en after becomes None
                    # set curr = after and after to the next node after curr
                    curr, after = after, curr.get_next()

            # 4- edge case: curr = None
            elif (curr is None):
                # then insert the new node at the end
                curr.set_next(new_node)
            # if they fit none of these cases, get new currs and afters
            else:
                curr, after = after, curr.get_next()

    def extracthigh(self):
        ''' (WackyQueue) -> obj
        Removes and returns the first object in the wacky queue
        REQ: Wacky Queue must have at least one item in it
        '''
        # initialize item to be None
        item = None
        # ^why? because if both the lists are empty, then item will be None and
        # the program won't crash
        size_odd = self.loop_odd()
        size_even = self.loop_even()
        # the case where we will only have one item in our list: then the size
        # of odd will be 1 and the size of even will 0. If this is the case,
        # then we will get the first item and make the odd_list point to none
        if (size_odd == 1 and size_even == 0):
            # get the item that is stored in the first node
            item = self._odd_list.get_item()
            # set the odd_list's head to None
            self._odd_list.set_next(None)
        # since the first object that we're inserting goes in the odd list
        # we will only use the odd list for this purpose
        # check if the odd list is not empty (if this is false, then the entire
        # list is empty and we can't do anything there)
        elif (self._odd_list is not None) and (self._even_list is not None):
            # get the first node, get the obj stored in it and store it in a
            # var to return that
            item = self._odd_list.get_item()
            # then rearrange the pointers s.t. you isolate the top most element
            # this will delete the element under the lense
            # for that, get the new head for the odd list and get the new head
            # for the even list
            # the odd head is the same as the even's current head
            new_odd_head = self._even_list.get_next()
            # the new even head is the same as the 2nd element in the odd list
            # step 1 to isolate the first node in the odd list (hence
            # extracting the high in the list)
            new_even_head = self._odd_list.get_next().get_next()
            # we now have both our heads; let's draw our connectors!
            # make the odd_list point to the new odd head
            self._odd_list.set_next(new_odd_head)
            # make the even_list point to the new even head
            self._even_list.set_next(new_even_head)
        # return the obj that was stored in that node
        return item

    def isempty(self):
        ''' (WackyQueue) -> bool
        Returns True if the wacky queue is empty. Otherwise, returns False.
        '''
        # get the sizes of both the lists using the helper methods
        odd_size = self.loop_odd()
        even_size = self.loop_even()
        # set up a bool statement s.t. if the addition == 0, then it evaluates
        # to True. Otherwise, evaluates to False
        is_empty = (odd_size + even_size) == 0
        # return the boolean variable
        return is_empty

    def changepriority(self, item, new_pri):
        ''' (WackyQueue, obj, int) -> None
        Returns None and changes the priority of the first occurence of the
        object <item> to the new priority <new_pri>. If <item> is not found,
        or already has the priority set to <new_pri>, then WackyQueue remains
        unchanged
        '''
        # use the find method to find the item
        (prev, curr, after) = self.find_by_item(item)
        # once we have the item, we can change its priority using
        # the wacky node methods
        curr.set_priority(new_pri)
        # we then need to rearrange the object to its new position aka delete
        # that node and then insert it again
        # to delete this node, we make the prev point to the after. We will
        # not lose the node that has to be rearranged, because curr is pointing
        # to it
        prev.set_next(after)
        # then to insert curr back into the list, use the insert function
        # this way, we will know that curr is in the right position i.e. our
        # priority queue still has order in it
        self.insert(curr)

    def negateall(self):
        ''' (WackyQueue) -> None
        Returns None and negates the priority of every object in the wacky
        queue. This also reverses the the order of insertion time. Hence
        reverses the order of objs with equal priority.
        '''
        # this one is fairly simple:
        # call the negator function on each list
        self.negator(self._odd_list)
        self.negator(self._even_list)
        # call the reverse function and reverse each list independantly
        # why independantly? because we know that the list is in order
        # and negating each element will make the priority reversed. We want
        # our list to be in the same priority that nick set. Hence the easy
        # solution: Reverse it!
        self.reverse(self._odd_list)
        self.reverse(self._even_list)
        # QED! :D

    def getoddlist(self):
        ''' (WackyQueue) -> WackyNode
        Returns the pointer to a linked list of wacky nodes with every other
        object in wacky queue starting from the first object i.e. the list
        must contain every odd indexed object.
        If there is no first object, then an empty list will be returned.
        '''
        # return the odd list
        return self._odd_list

    def getevenlist(self):
        ''' (WackyQueue) -> WackyNode
        Returns the pointer to a linked list of wacky nodes with every other
        object in wacky queue starting from the second object i.e. the list
        must contain every even indexed object.
        If there is no second object, then an empty list will be returned.
        '''
        # return the even list
        return self._even_list

    def __str__(self):
        curr = self._odd_list
        after = self._even_list
        output = ''
        while (curr is not None) and (after is not None):
            output += str(curr) + ' '
            curr, after = after, curr.get_next()
        return output
Пример #19
0
class WackyQueue():
    '''This is the class object of wacky queue'''
    def __init__(self):
        '''
        (WackyQueue) -> NoneType
        REQ: oddlist and evenlist must be link list
        '''
        self._oddlist = WackyNode(None, None)  # dummy node
        self._evenlist = WackyNode(None, None)  # dummy node

    def insert(self, obj, pri):
        '''
        (WackyQueue, obj, int) -> NoneType
        This function takes in an object with a priority
        and insert it into the proper position of the two link list
        REQ: the pri must be an integer
        '''
        # set the new node
        new_node = WackyNode(obj, pri)
        # set the basic pointers for the odd list
        prev = None
        curr = self._oddlist.get_next()
        # set the basic pointer for the even list
        prev_even = None
        curr_even = self._evenlist.get_next()
        # loop through every obj to find a place to insert
        while curr and curr_even and curr.get_priority() >= pri and\
              curr_even.get_priority() >= pri:
            # move forward the pointer on the odd list
            prev = curr
            curr = curr.get_next()
            # move forward the pointer on the even list
            prev_even = curr_even
            curr_even = curr_even.get_next()
        if not curr:
            if self._oddlist._next is None:
                self._oddlist.set_next(new_node)
            else:
                # if curr is none, then the new node is smaller than
                # both prev and prev_even
                prev.set_next(new_node)
        elif not curr_even:
            # if curr is not none but curr_even is none
            # there are two occations:
            if self._evenlist._next is None:
                if pri <= self._oddlist.get_next().get_priority():
                    self._evenlist.set_next(new_node)
                else:
                    self._evenlist.set_next(self._oddlist.get_next())
                    self._oddlist.set_next(new_node)
            else:
                if pri <= curr.get_priority():
                    # if pri is less than odd curr value
                    # then it is inserted into the even list at last
                    prev_even.set_next(new_node)
                else:
                    # if pri is bigger than curr value
                    # of course less or equal to prev_even value
                    # then the new node is inserted after the prev
                    prev.set_next(new_node)
                    prev_even.set_next(curr)
        elif pri > curr_even.get_priority() and pri <= curr.get_priority():
            # if pri is between the value of curr and curr_even
            # then the new node is inserted after the prev_even
            # link the new node with the curr position in even list
            if prev_even is None:
                self._evenlist.set_next(new_node)
            else:
                prev_even.set_next(new_node)
            # link the new node with the next object in odd list
            new_node.set_next(curr.get_next())
            # link the curr position in odd list
            # with the next object in even list
            curr.set_next(curr_even)
        elif pri > curr.get_priority():
            # if pri's value is bigger than curr's value
            # of course less or equal to prev_even value
            # link prev in odd list with new node
            if prev is None:
                self._oddlist.set_next(new_node)
            else:
                prev.set_next(new_node)
            # link the new node with the curr obj in even list
            new_node.set_next(curr_even)
            # link the prev position in even list with curr position in odd
            if prev_even is None:
                self._evenlist.set_next(curr)
            else:
                prev_even.set_next(curr)

    def extracthigh(self):
        '''
        (WackyQueue) -> obj
        This function remove and return the first item in the wacky queue
        REQ: the wacky queue is not empty
        '''
        # store the first item in another variable for retrn
        return_item = self._oddlist.get_next()
        # set the first of the even list be the head of the oddlist
        self._oddlist.set_next(self._evenlist.get_next())
        # set the second of the odd list be the head of the even list
        self._evenlist.set_next(self._oddlist.get_next().get_next())
        # return the item that was removed
        return return_item

    def changepriority(self, obj, pri):
        '''
        (WackyQueue, obj, int) -> NoneType
        This func change the priority of the first copy of object obj to pri
        REQ: the pri must be a integer
        '''
        # main idea: find the obj (if exist), restore it and remove it
        #            then take it as a new node with new pri and insert it
        # set the original pointers
        curr = self._oddlist
        curr_even = self._evenlist
        # while the next item is not none and is not the target
        # use the next item so that moving forward pointers
        # without nonetype error
        while curr.get_next() and curr.get_next().get_item() != obj:
            # move forward the pointers
            temp = curr
            curr = curr_even
            curr_even = temp.get_next()
        # if find the target and the priority is different
        if curr.get_next() and curr.get_next().get_priority() != pri:
            # restore the target item
            item = curr.get_next()
            # reset the priority of the target
            item.set_priority(pri)
            # restore the next of the item for link
            temp = item.get_next()
            # link the curr on odd list with the next on even list
            curr.set_next(curr_even.get_next())
            # link the curr on even list with next of the item
            curr_even.set_next(temp)
            # insert the new node with new priority
            self.insert(obj, pri)

    def _reverse(self, dummy):
        '''
        (WackyQueue, LLNode) -> int
        This is a helper function that negate the priority of each item
        revese the whole link list
        and return the length of the list
        REQ: dummy must be a link list
        '''
        # set the original pointers
        prev = None
        curr = dummy.get_next()
        # set the length counter
        length = 0
        # loop through every node, reverse the pointer between each node
        while curr:
            # negate the priority
            curr.set_priority(-curr.get_priority())
            # move forward the pointers
            temp = curr.get_next()
            curr.set_next(prev)
            prev = curr
            curr = temp
            # count the length
            length += 1
        # set the next of the head be the tail of the original
        dummy.set_next(prev)
        return length

    def negateall(self):
        '''
        (WackyQueue) -> NoneType
        This function negates the priority of every object in the wacky queue
        '''
        if self._reverse(self._oddlist) == self._reverse(self._evenlist):
            # if the two list has the same length
            # reverse the odd list with the even list
            temp = self._oddlist.get_next()
            self._oddlist.set_next(self._evenlist.get_next())
            self._evenlist.set_next(temp)
        else:
            # if odd list has one more item
            # then the two list are the same except the order inside each list
            pass

    def isempty(self):
        '''
        (WackyQueue) -> bool
        This functon returns if the link is empty
        '''
        return self._oddlist.get_next() is None

    def getoddlist(self):
        '''
        (WackyQueue) -> LLNode
        This function returns the odd list
        '''
        return self._oddlist.get_next()

    def getevenlist(self):
        '''
        (WackyQueue) -> LLNode
        This function returns the even list
        '''
        return self._evenlist.get_next()
Пример #20
0
 def __init__(self):
     self._oddlist = WackyNode(None, None)  # dummy node
     self._evenlist = WackyNode(None, None)
Пример #21
0
class WackyQueue:
    def __init__(self):
        '''(WackyQueue) -> NoneType
        constructs an empty queue
        '''
        # Representation invariant:
        # WackyQueue consists of two linked lists
        # _head1 is a dummy head of the linked list of odd nodes
        # _head2 is a dummy head of the linked list of even nodes
        # _head1.get_next() is the first node in the list of odd nodes
        # _head1.get_next() is the first node in the WackyQueue
        # _head2.get_next() is the first node in the list of even nodes
        # _head2.get_next() is the second node in the WackyQueue

        self._head1 = WackyNode(None, None)
        self._head2 = WackyNode(None, None)

    def __str__(self):
        '''(WackyQueue) -> str
        returns a string represention of this queue
        '''
        # create an empty result string
        result = ""
        # if the WackyQueue is empty
        if self._head1.get_next() is None:
            # set the result string
            result = "None"
        # otherwise
        else:
            # set 2 pointers that point to 2 head nodes
            curr1 = self._head1
            curr2 = self._head2
            # while the odd linked list has next node
            while curr1.get_next() is not None:
                # add the item in that node to the result string
                result = result + str(curr1.get_next().get_item()) + " -> "
                # move to the next node in the odd linked list
                curr1 = curr1.get_next()
                # if the even list also has next node
                if curr2.get_next() is not None:
                    # add the item in that node to the result string
                    result = result + str(curr2.get_next().get_item()) + " -> "
                    # move to the next node in the even linked list
                    curr2 = curr2.get_next()
        # return the result string
        return result

    def insert(self, obj, pri):
        '''(WackyQueue, obj, int) -> NoneType
        insert an object to queue, whose priority = pri and item = obj
        '''
        # create a new node with obj and pri given
        new_node = WackyNode(obj, pri)
        # set 3 pointers that point to 2 head nodes and the 1st node
        prev = self._head1
        curr = self._head2
        next = self._head1.get_next()
        # find the right place for insertion by comparing the priority of
        # the current object and the objects that are already in the queue
        while (next is not None) and (next.get_priority() >= pri):
            # move to the next node
            now = next
            next = curr.get_next()
            prev = curr
            curr = now
        # when find the right place
        # insert the new node after the prev node
        prev.set_next(new_node)
        # if the curr node has a _next node
        if (curr.get_next() is not None):
            # set this node to be the _next of the new node
            new_node.set_next(curr.get_next())
        # set next node to be the _next of the curr node
        curr.set_next(next)

    def extracthigh(self):
        '''(WackyQueue) -> Obj
        Remove and return the first item in the wacky queue.
        REQ: The wacky queue is not empty.
        '''
        # find the first node in the queue
        result = self._head1.get_next()
        # set the previous second node to be the current first node
        self._head1.set_next(self._head2.get_next())
        # set the previous third node to be the current second node
        self._head2.set_next(result.get_next())
        # return the item in the first node
        return result.get_item()

    def isempty(self):
        '''(WackyQueue) -> bool
        returns true if the queue is empty
        '''
        # return whether the queue is empty by checking if the head1._next is
        # None
        return self._head1.get_next() is None

    def changepriority(self, obj, pri):
        '''(WackyQueue, obj, int) -> NoneType
        Change the priority of the first copy of object obj to pri.
        The wacky queue is unchanged if obj is not in it or already has
        priority pri.
        If the priority of obj is changed, then the insertion time of obj is
        taken to be the time of the changepriority operation.
        '''
        # set 3 pointers that point to 2 head nodes and the 1st node
        prev = self._head1
        curr = self._head2
        next = self._head1.get_next()
        # check if the obj already exists by comparing the obj and the objects
        # already in the queue
        while (next is not None) and (next.get_item() != obj):
            # move to the next node
            now = next
            next = curr.get_next()
            prev = curr
            curr = now
        # if the obj already exists and it doesn't have priority pri
        if (next is not None) and (next.get_priority() != pri):
            # set the _next of curr node to be the _next of the prev node
            prev.set_next(curr.get_next())
            # set the _next of changing node to be the _next of the curr node
            curr.set_next(next.get_next())
            # insert the pri-changed node
            self.insert(obj, pri)

    def negateall(self):
        '''(WackyNode) -> NoneType
        Negate the priority of every object in the wacky queue.
        The order of insertion times of objects in the wacky queue is reversed.
        Thus the order of objects with equal priority is also reversed.
        '''
        # create pointers to the None's, 2 heads, first and second nodes
        prev1 = None
        prev2 = None
        curr1 = self._head1
        curr2 = self._head2
        next1 = curr1.get_next()
        end1 = next1
        next2 = curr2.get_next()
        end2 = next2
        # create a int to count the number of nodes
        num = 0

        # check the linked list of the odd nodes
        while curr1 is not None:
            # reverse the nodes
            curr1.set_next(prev1)
            # move to the next node
            prev1 = curr1
            curr1 = next1
            # if next1 is a node
            if next1 is not None:
                # negate its priority
                next1.set_priority(-next1.get_priority())
                # move to the next node
                next1 = next1.get_next()
                # add 1 to the number of nodes
                num = num + 1
        # update self._head1
        self._head1.set_next(prev1)
        end1.set_next(None)

        # check the linked list of the even nodes
        while curr2 is not None:
            # reverse the nodes
            curr2.set_next(prev2)
            # move to the next node
            prev2 = curr2
            curr2 = next2
            # if next2 is a node
            if next2 is not None:
                # negate its priority
                next2.set_priority(-next2.get_priority())
                # move to the next node
                next2 = next2.get_next()
                # add 1 to the number of nodes
                num = num + 1
        # update self._head2
        self._head2.set_next(prev2)
        end2.set_next(None)

        # if the number of nodes is even
        if (num % 2) == 0:
            # exchange the two heads
            head = self._head1
            self._head1 = self._head2
            self._head2 = head

    def getoddlist(self):
        '''(WackyNode) -> WackyNode or NoneType
        Return a pointer to a linked list of WackyNodes containing every
        other object in the wacky queue, starting with the first object.
        If there is no first object, then an empty list is returned.
        '''
        # return the pointer to the linked list of odd nodes
        return self._head1.get_next()

    def getevenlist(self):
        '''(WackyNode) -> WackyNode or NoneType
        Return a pointer to a linked list of WackyNodes containing every other
        object in the wacky queue, starting with the second object.
        If there is no second object, then an empty list is returned.
        '''
        # return the pointer to the linked list of even nodes
        return self._head2.get_next()
Пример #22
0
    def insert(self, obj, pri):
        '''(WackyQueue, obj, int) -> NoneType
        Creates a new WackyNode and inserts it into the
        WackyQueue sorted descendingly. Items with
        the same priority are sorted according to which
        item was added first.
        '''
        # Create node
        node = WackyNode(obj, pri)

        # Insert first item
        if self._odd is None:
            self._odd = node
        # Insert the second item if
        # it has less priority than first
        elif self._even is None and node.get_priority(
        ) <= self._odd.get_priority():
            self._even = node
        # Switch the first and second if
        # second node has greater priority
        elif self._even is None and node.get_priority(
        ) > self._odd.get_priority():
            self._even = self._odd
            self._odd = node
        # Insert the nth item, where n > 2
        else:
            # Store the first and second nodes
            cur_node1 = self._odd
            cur_node2 = self._even
            # Keep track of the size of both lists
            sizeodd = 1
            sizeeven = 1

            # Take the nodes with the highest possible
            # priority from both lists
            while (
                    cur_node1.get_next() is not None and
                (cur_node1.get_next().get_priority() >= node.get_priority())):
                sizeodd += 1
                cur_node1 = cur_node1.get_next()

            while (
                    cur_node2.get_next() is not None and
                (cur_node2.get_next().get_priority() >= node.get_priority())):
                sizeeven += 1
                cur_node2 = cur_node2.get_next()

            # First Case:
            # The current nodes priorities taken from the
            # even and odd lists are greater than or equal
            # to the node priority
            if (cur_node1.get_priority() >= node.get_priority()
                    and cur_node2.get_priority() >= node.get_priority()):
                # Find greater value between two current nodes
                # By default assume the odd list contains the higher node
                greatest = cur_node1
                lowest = cur_node2
                if cur_node1.get_priority() < cur_node2.get_priority():
                    greatest = cur_node2
                    lowest = cur_node1
                elif cur_node1.get_priority() == cur_node2.get_priority():
                    # If odd list is longer, add node to the even list
                    if sizeodd > sizeeven:
                        greatest = cur_node2
                        lowest = cur_node1

                temp = greatest.get_next()
                greatest.set_next(node)
                node.set_next(lowest.get_next())
                lowest.set_next(temp)

            # Second Case:
            # The node priority is strictly inbetween the two
            # priorities or equal to the first odd node's priority
            elif (cur_node1.get_priority() >= node.get_priority()
                  and cur_node2.get_priority() < node.get_priority()):
                # Insert in between
                temp = cur_node1.get_next()
                cur_node1.set_next(cur_node2)
                self._even = node
                node.set_next(temp)

            # Third Case:
            # The node priority is strictly greater than both
            elif (cur_node1.get_priority() < node.get_priority()
                  and cur_node2.get_priority() < node.get_priority()):
                # Insert at the beginning
                temp = cur_node1
                self._odd = node
                node.set_next(cur_node2)
                self._even = temp
Пример #23
0
    def insert(self, obj, priority):
        '''(WackyQueue, obj, int) -> None
        Inserts an item named obj with priority given into the 
        WackyQueue. If an item already exists with the same priority,
        the earlier item goes first in the WackyQueue.
        The way insert functions is that when we insert an element, all
        the elements that come after it are swapped from their current
        linked list to the other one. Let's take a look at an example:
        Odd List: [A] -> [D]-> [F]->[H]
        Even List: [B] -> [E] -> [G]
        Now let's say we want to insert C, the lists Become:
        Odd List: [A]->[C]->[E]->[G]
        Even List: [B]->[D]->[F]->[H]
        Notice how elements {D, F, H} that were originally in the odd list
        swapped to the even list, and elements {E,G} that were originally in
        the even list swapped to the odd list. In the code, we usually only have
        to make 1 swap however, because D would point to F which points to H, etc...
        and E would point to G, etc....
        '''

        # creating a new node that we're gonna insert into either
        # the odd linked list or the even linked list
        Node = WackyNode(obj, priority)
        # initializing some variables to keep track of the current
        # objects in the even and odd lists we're looking at.
        currentOdd, currentEven = self._oddListHead, self._evenListHead

        # Let's also initialize some variables to keep track of the previous
        # values, because sometimes we'll need to modify them and the
        # list is only singly linked
        previousOdd, previousEven = None, None
        # make a flag variable so that we know when to stop the loop
        # if we've found the correct spot to insert
        spotFound = False
        # in the case where the head of the even list is none (IE: empty)
        if currentEven == None:
            # in case the odd and even list are none (so the queue is completely empty)
            # we need to make the node the head of the odd list (because its the first element)
            # and indicate that we've found a spot
            if currentOdd == None:
                self._oddListHead = Node
                spotFound = True
            else:
                # now we branch off into two other cases
                # if the element has priority greater than the
                # largest element and the lists arent empty, we need
                # to swap the values of the even and odd lists, and
                # set the node to the highest value
                if priority > self._oddListHead.get_priority():
                    self._evenListHead = self._oddListHead
                    self._oddListHead = Node
                    spotFound = True
                # if the Queue contains only 1 element, we can
                # set the head of the even list as the node
                # and change the flag
                elif priority <= self._oddListHead.get_priority():
                    self._evenListHead = Node
                    spotFound = True
        # in the case where the element to insert is the largest in the queue
        # and the list isn't empty we need to swap the heads of the lists
        # and set the item as the first in the Queue, also make sure
        # that the new item points to the old head of the odd list
        if currentOdd != None and currentEven != None:
            if priority > currentOdd.get_priority():
                (self._oddListHead, self._evenListHead) = (self._evenListHead,
                                                           self._oddListHead)
                Node.set_next(self._oddListHead)
                self._oddListHead = Node
                spotFound = True
        # initialize a counter so that we know whether to increment through the odd list or the
        # even list
        counter = 0
        # the following loop tries to find a spot to place the new element
        # while we're not at the end of both lists and the flag hasn't
        # been set to true(which would mean that we've already found a spot)
        while currentOdd != None and currentEven != None and not spotFound:
            # the following cases account for the cases where we're at the end
            # of one or both lists
            if currentEven.get_next() == None:
                if currentOdd.get_next() == None:
                    # if we're at the end of both lists and the element is less than both the last
                    # elements in each list, we need to set the last element in the WackyQueue to the
                    # node, and change the flag
                    if priority <= currentOdd.get_priority(
                    ) and priority <= currentEven.get_priority():
                        currentOdd.set_next(Node)
                        spotFound = True
                # if we're at the last element in the even list but there's still an element in the odd list
                # we need to set the element to the next even and change the flag
                else:
                    if priority <= currentOdd.get_next().get_priority():
                        currentEven.set_next(Node)
                        spotFound = True

            # in the case where we're looking in the middle of the lists and we still haven't found a place to
            # insert our new element
            if spotFound == False:
                # in the case where our current element is between the element we're looking at in the even
                # list and odd list, we need to link the element inside the even list while switching the even
                # and odd elements that come after it.In all cases, change the flag
                if currentEven.get_priority(
                ) <= priority <= currentOdd.get_priority():
                    if previousEven != None:
                        previousEven.set_next(Node)
                    Node.set_next(currentOdd.get_next())
                    currentOdd.set_next(currentEven)
                    # in the case where the even element is the head, we need
                    # to set the head of the even list to the new element.
                    if currentEven == self._evenListHead:
                        self._evenListHead = Node
                    spotFound = True
                # this case is also where the current element is between our current even and odd element, but the odd
                # element is greater and the even element is smaller, we perform the exact same operations as above, but
                # using the opposite list as above. we also dont need to do any checking for if we're dealing with the
                # heads of the lists because we would have dealt with this outside the while loop.
                if currentOdd.get_priority(
                ) <= priority < currentEven.get_priority():
                    previousOdd.set_next(Node)
                    Node.set_next(currentEven.get_next())
                    currentEven.set_next(currentOdd)
                    spotFound = True
            # the following statements increment our values to check in the odd and even lists
            # we need to make sure that we're not just looking at the n'th elements in each list
            # because we need to compare the nth value of the odd list with the nth value in the even
            # list, and then the nth value of the odd list with the n+1th value in the even list, etc...
            # so we make it so that on every even number, the values in the odd list will be incremented,
            # and on every odd number, the values in the even list will be incremented. Obviously, increment
            # the counter itself as well
            if counter % 2 == 0:
                previousOdd = currentOdd
                currentOdd = currentOdd.get_next()
            else:
                previousEven = currentEven
                currentEven = currentEven.get_next()
            counter += 1
Пример #24
0
class WackyQueue():
    def __init__(self):
        self._oddlist = WackyNode(None, None)  # dummy node
        self._evenlist = WackyNode(None, None)

    def __str__(self):
        result = ""
        curr = self._oddlist.get_next()
        while curr:
            result += str(curr.get_item())
            result += " -> "
            curr = curr.get_next()
        result += "None (odd) \n"

        curr = self._evenlist.get_next()
        while curr:
            result += str(curr.get_item())
            result += " -> "
            curr = curr.get_next()
        return result + "None (even)\n"

    def insert(self, obj, pri, node=None, curr=None, next=None):
        if not node:  # for changepriority (in case you check for same node)
            node = WackyNode(obj, pri)
        if not curr:  # for changepriority (avoid starting from head)
            curr, next = self._oddlist, self._evenlist

        while curr.get_next() and curr.get_next().get_priority() >= pri:
            next, curr = curr.get_next(), next

        node.set_next(next.get_next())
        next.set_next(curr.get_next())
        curr.set_next(node)

    def extracthigh(self):
        remove_node = self._oddlist.get_next()
        self._oddlist.set_next(self._evenlist.get_next())
        self._evenlist.set_next(remove_node.get_next())
        remove_node.set_next(None)
        return remove_node

    def isempty(self):
        return not self._oddlist.get_next()

    def changepriority(self, obj, pri):
        curr, next = self._oddlist, self._evenlist
        while curr.get_next() and curr.get_next().get_item() != obj:
            next, curr = curr.get_next(), next

        if curr.get_next() and curr.get_next().get_priority() != pri:
            old_pri = curr.get_next().get_priority()  # optional
            curr.get_next().set_priority(pri)
            node = curr.get_next()  # optional
            temp = curr.get_next().get_next()
            curr.set_next(next.get_next())
            next.set_next(temp)

            if pri < old_pri:  # optional
                self.insert(obj, pri, node, curr, next)  # optional
            else:
                self.insert(obj, pri, node)

    def _reverse(self, head):
        num_node = 0
        prev = None
        curr = head.get_next()
        while curr:
            curr.set_priority(-curr.get_priority())
            temp = curr.get_next()
            curr.set_next(prev)
            prev = curr
            curr = temp
            num_node += 1
        head.set_next(prev)
        return num_node

    def negateall(self):
        if (self._reverse(self._oddlist) +
                self._reverse(self._evenlist)) % 2 == 0:
            temp = self._oddlist.get_next()
            self._oddlist.set_next(self._evenlist.get_next())
            self._evenlist.set_next(temp)

    def getoddlist(self):
        return self._oddlist.get_next()

    def getevenlist(self):
        return self._evenlist.get_next()