(even_curr.get_priority() >= new_node.get_priority())): odd_prev = odd_curr even_prev = even_curr odd_curr = odd_curr.get_next() even_curr = even_curr.get_next() # If we need to insert in between the positions of the first two # nodes of the WackyQueue if (odd_prev is None) or (even_prev is None): # If we need to insert new node before the first node of queue if odd_curr.get_priority() < new_node.get_priority(): # Set the even head pointer to the first node and then add # the new node at the first position self._even_head = self._odd_head self._odd_head = new_node # Switch the nodes to their correct positions new_node.set_next(even_curr) # If we need to insert the new node before the second node of # the WackyQueue elif even_curr.get_priority() < new_node.get_priority(): self._even_head = new_node new_node.set_next(odd_curr.get_next()) odd_curr.set_next(even_curr) # Given that there are atleast two WackyNodes in WackyQueue # If we need to insert at the end of the odd linked list elif odd_curr is None: odd_prev.set_next(new_node) # If we need to insert at the end of the even linked list elif ((even_curr is None) and (odd_curr.get_priority() >= new_node.get_priority())): even_prev.set_next(new_node)
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 -> '
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)
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()
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 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
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()
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
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()
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()