Exemple #1
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()
Exemple #2
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 -> '
Exemple #3
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()
Exemple #4
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()
Exemple #5
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
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()