def add_to_back(alist, val): """ Purpose Insert val into alist at the end of the node chain Preconditions: :param alist: a list created by create() :param val: a value of any kind Post-conditions: The list increases in size. The new value is last in the list. Return: :return None """ if size(alist) == 0: new_node = node.create(val, None) alist['head'] = new_node alist['tail'] = new_node alist['size'] += 1 else: cur_last_node = alist['tail'] new_node = node.create(val, None) node.set_next(cur_last_node, new_node) alist['tail'] = new_node alist['size'] += 1 return None
def reverse_a(chain): """ Purpose Reverse the sequence of the nodes in the given chain. Preconditions: :param chain: a node chain Post-conditions: The values in the chain are in the reversed order. Return: :return: the reversed node chain """ if chain is None: return None elif node.get_next(chain) is None: return chain else: # remember the first two nodes first = chain second = node.get_next(chain) # reverse the chain starting at the second node reved = reverse_a(second) # second is now last! hook the first node node.set_next(second, first) node.set_next(first, None) return reved
def copy(node_chain, new_chain=None, head=None): """ Purpose: Create a new node-chain Pre-conditions: :param node_chain: a node chain, possibly empty return: :return: a seperate distinct chain that has the same values as node-chain """ if node_chain is None: if new_chain is None: return None node.set_next(new_chain, None) return head else: value = node.get_data(node_chain) if new_chain is None: new_chain = node.create(value, None) head = new_chain return copy(node.get_next(node_chain), new_chain, head) else: node.set_next(new_chain, node.create(value)) return copy(node.get_next(node_chain), node.get_next(new_chain), head)
def remove_chain(node_chain, val): """ Purpose: Remove the first occurrence of val from node_chain. Pre-conditions: :param node_chain: a node chain, possibly empty :param val: a value to be removed Post-conditions: The first occurrence of the value is removed from the chain. If val does not appear, the node-chain is unmodified. Return: :return: The resulting node chain with val removed """ # special case: empty node chain if node_chain is None: return None # special case: node to be removed is first if node.get_data(node_chain) == val: return node.get_next(node_chain) # walk along the chain walker = node.get_next(node_chain) prev = node_chain while walker is not None and node.get_data(walker) != val: prev = walker walker = node.get_next(walker) # found first occurrence of val? if walker is not None: node.set_next(prev, node.get_next(walker)) return node_chain
def reverse_chain(node_chain): """ Purpose: Completely reverses the order of the given node_chain. Pre-conditions: :param node_chain: a node chain, possibly empty Post-conditions: The front of the node_chain is altered to be the back, with all nodes now pointing next the opposite direction. Return: :return: The resulting node chain that has had its order reversed """ #if node_chain is not a single node or empty, step through and reverse if a5q2.count_chain(node_chain) > 1: cur_node = node_chain prev_node = None next_node = node.get_next(node_chain) #step through and reverse each node while True: node.set_next(cur_node, prev_node) prev_node = cur_node cur_node = next_node #If next_node is None break, otherwise, move next to next node if next_node is None: break else: next_node = node.get_next(next_node) node_chain = prev_node return node_chain
def remove_from_back(alist): """ Purpose Removes and returns the last value in alist Preconditions: :param alist: a list created by create() Post-conditions: The list decreases in size. The returned value is no longer in in the list. Return: :return The pair True, value if alist is not empty :return The pair False, None if alist is empty """ if is_empty(alist): return False, None if size(alist) == 1: anode = alist['head'] alist['head'] = None alist['tail'] = None alist['size'] = 0 return True, node.get_data(anode) # general case aprev = alist['head'] anode = node.get_next(aprev) while node.get_next(anode) is not None: aprev = anode anode = node.get_next(anode) alist['tail'] = aprev node.set_next(aprev, None) alist['size'] -= 1 return True, node.get_data(anode)
def reverse_b(to_reverse, reversed=None): """ Purpose Move all of the nodes in to_reverse to reversed Preconditions: :param to_reverse: a node chain to be reversed :param reversed: a node chain already reversed Post-conditions: to_reverse is reversed Return: :return: the resulting node chain with all nodes """ # "pop" off a node from q, push it on s if to_reverse == None: return reversed else: # conceptually, grab the first node in to_reverse this_node = to_reverse # conceptually, grab the nodes after the first the_rest = node.get_next(this_node) # connect the first node to the ones that are already reversed node.set_next(this_node, reversed) # recursively reverse all the rest return reverse_b(the_rest, this_node)
def push(self, node): if self.currentNode == None: self.currentNode = node #self.set_next(None) else: node.set_next(self.currentNode) self.currentNode = node
def delete_item_at_index(alist, idx): """ Purpose Delete the value at index idx in alist. Preconditions: :param alist: a list created by create() :param idx: a non-negative integer Post-conditions: The list decreases in size if the index is valid The value at idx is no longer in the list. Return: :return True if index was valid, False otherwise """ if idx < 0 or idx >= size(alist): return False if idx == 0: remove_from_front(alist) return True if idx == size(alist) - 1: remove_from_back(alist) return True # general case anode = alist['head'] aprev = None i = 0 while anode is not None and i < idx: aprev = anode anode = node.get_next(anode) i += 1 node.set_next(aprev, node.get_next(anode)) alist['size'] -= 1 return True
def remove_from_back(alist): """ Purpose Removes and returns the last value in alist Preconditions: :param alist: a list created by create() Post-conditions: The list decreases in size. The returned value is no longer in in the list. Return: :return The tuple (True, value) if alist is not empty :return The tuple (False, None) if alist is empty """ if alist["tail"] is None: return False, None val = node.get_data(alist["tail"]) if size(alist) is 1: #singleton alist["head"] = None alist["tail"] = None alist["size"] -= 1 return True, val walker = alist["head"] count = 1 while count < size(alist) - 1: #point walker to second last node walker = node.get_next(walker) count += 1 node.set_next(walker, None) alist["tail"] = walker alist["size"] -= 1 return True, val
def delete_item_at_index(alist, idx): """ Purpose Delete the value at index idx in alist. Preconditions: :param alist: a list created by create() :param idx: a non-negative integer Post-conditions: The list decreases in size if the index is valid The value at idx is no longer in the list. Return: :return True if index was valid, False otherwise """ if idx >= alist["size"] or idx < 0: #if index out of range return False if idx is 0: #if remove from front remove_from_front(alist) return True elif idx is size(alist) - 1: #if remove from rear remove_from_back(alist) return True walker = node.get_next(alist["head"]) #all other cases previous = alist["head"] index = 1 while True: if index == idx: node.set_next(previous, node.get_next(walker)) alist["size"] -= 1 return True walker = node.get_next(walker) previous = node.get_next(previous) index += 1
def copy_chain(node_chain): """ Purpose: Make a new node chain with the same values as in node_chain. Pre-conditions: :param node_chain: a node chain, possibly None Return: :return: A copy of node chain, with new nodes, but the same data. """ # special case: empty node chain if node_chain is None: return None else: walker = node_chain # remember the first node result = node.create(node.get_data(walker)) walker = node.get_next(walker) walker2 = result # walk along the first chain, making copies of each node while walker is not None: node.set_next(walker2, node.create(node.get_data(walker))) walker2 = node.get_next(walker2) walker = node.get_next(walker) # return the anchor to the copy return result
def reverse_c(chain): """ Purpose Reverse the sequence of the nodes in the given chain. Preconditions: :param chain: a node chain Post-conditions: The values in the chain are in the reversed order. Return: :return: the reversed node chain """ if chain is None: return None elif node.get_next(chain) is None: return chain else: # remember the first two nodes first = chain second = node.get_next(chain) # reverse the chain starting at the second node reved = reverse_c(second) walker = reved prev = None while walker is not None: prev = walker walker = node.get_next(walker) if prev is not None: node.set_next(prev, first) node.set_next(first, None) return reved
def extend(alist, blist): """ Purpose append all the nodes in blist on the end of alist Preconditions: :param alist: a list created by create() :param blist: a list created by create() Post-conditions: alist has all the nodes of blist appended to it alist's tail is the same as blist's tail alist's size = alist's size + blist's size Return: None """ if is_empty(alist) and is_empty(blist): pass elif is_empty(alist): alist = blist elif is_empty(blist): pass else: atail = alist['tail'] node.set_next(atail, blist['head']) alist['tail'] = blist['tail'] alist['size'] += blist['size']
def delete_item_at_index(alist, idx): """ Purpose Delete the value at index idx in alist. Preconditions: :param alist: a list created by create() :param idx: a non-negative integer Post-conditions: The list decreases in size if the index is valid The value at idx is no longer in the list. Return: :return True if index was valid, False otherwise """ #check if idx is within scope of alist or check if alist is empty if alist['size'] - idx < 1 or is_empty(alist): return False #check if list is a singleton elif alist['size'] == 1: remove_from_front(alist) return True #check if idx is the first index elif idx == 0: remove_from_front(alist) return True #check if idx is the last index elif alist['size'] - idx == 1: remove_from_back(alist) return True #general case else: cur_node = alist['head'] next_node = node.get_next(cur_node) next_idx = 1 while next_node is not None: if next_idx == idx: after_next = node.get_next(next_node) node.set_next(cur_node, after_next) alist['size'] -= 1 return True else: cur_node = next_node next_node = node.get_next(next_node) next_idx += 1
def insert_value_at_index(alist, val, idx): """ Purpose Insert val into alist at index idx Preconditions: :param alist: a list created by create() :param val: a value of any kind :param idx: a valid index for the list Post-conditions: The list increases in size. The new value is at index idx. The values previously in the list at idx or later appear after the new value. Return: :return If the index is valid, insert_value_at_index returns True. :return If the index is not valid, insert_value_at_index returns False. """ #check if idx beyond alist['size'] + 1 or idx is negative, return False if alist['size'] - idx < 0 or idx < 0: return False #if index is the first index or is empty, add new val at the front if idx == 0 or is_empty(alist): add_to_front(alist, val) return True #if index is immediately after the last index of alist, add new val to back elif idx == alist['size']: add_to_back(alist, val) return True #general case else: cur_node = alist['head'] next_node = node.get_next(cur_node) next_idx = 1 #index of next_node while next_node is not None: if next_idx == idx: new_node = node.create(val, next_node) node.set_next(cur_node, new_node) alist['size'] += 1 return True else: cur_node = next_node next_node = node.get_next(next_node) next_idx += 1
def reverse_chain(node_chain, prev_node=None): """ Purpose: Completely reverses the order of the given node_chain. Pre-conditions: :param node_chain: a node chain, possibly empty Post-conditions: The front of the node_chain is altered to be the back, with all nodes now pointing next the opposite direction. Return: :return: The resulting node chain that has had its order reversed """ if node_chain is None: return prev_node else: next = node.get_next(node_chain) node.set_next(node_chain, prev_node) return reverse_chain(next, node_chain)
def copy(chain): """ Purpose Make a completely new copy of the given node-chain. Preconditions: :param chain: a node-chain Post-conditions: None Return: :return: A new copy of the chain is returned """ if chain == None: return None else: newnode = node.create(node.get_data(chain)) newnext = copy(node.get_next(chain)) node.set_next(newnode, newnext) return newnode
def remove_from_back(alist): """ Purpose Removes and returns the last value in alist Preconditions: :param alist: a list created by create() Post-conditions: The list decreases in size. The returned value is no longer in in the list. Return: :return The tuple (True, value) if alist is not empty :return The tuple (False, None) if alist is empty """ #check if linked list is already EMPTY if is_empty(alist): return False, None #check if linked list is a singleton elif size(alist) == 1: node_to_remove = alist['head'] removed_data = node.get_data( node_to_remove) #data to be removed and returned alist['head'] = None alist['tail'] = None alist['size'] = 0 return True, removed_data else: prev_node = alist['head'] next_node = node.get_next(prev_node) while next_node is not None: #if next_node is the same as tail, then prev_node becomes the new tail if next_node == alist['tail']: removed_data = node.get_data( next_node) #data to be removed and returned node.set_next(prev_node, None) alist['tail'] = prev_node alist['size'] -= 1 return True, removed_data else: prev_node = next_node next_node = node.get_next(next_node)
def add_to_back(alist, val): """ Purpose Insert val into alist at the end of the node chain Preconditions: :param alist: a list created by create() :param val: a value of any kind Post-conditions: The list increases in size. The new value is last in the list. Return: :return None """ anode = node.create(val) if is_empty(alist): alist['head'] = anode else: node.set_next(alist['tail'], anode) alist['tail'] = anode alist['size'] += 1
def insert_value_at_index(alist, val, idx): """ Purpose Insert val into alist at index idx Preconditions: :param alist: a list created by create() :param val: a value of any kind :param idx: a valid index for the list Post-conditions: The list increases in size. The new value is at index idx. The values previously in the list at idx or later appear after the new value. Return: :return If the index is valid, insert_value_at_index returns True. :return If the index is not valid, insert_value_at_index returns False. """ if idx > alist["size"] or idx < 0: #if index out of range return False new = node.create(val) if alist["head"] is None and idx is 0: #if empty list add_to_front(alist, val) return True else: if idx is 0: #if add to front add_to_front(alist, val) return True if idx is size(alist): #if add to rear: idx is the same as size add_to_back(alist, val) return True walker = node.get_next(alist["head"]) previous = alist["head"] index = 1 while True: #add in between if index == idx: node.set_next(previous, new) node.set_next(new, walker) alist["size"] += 1 return True walker = node.get_next(walker) previous = node.get_next(previous) index += 1
def split_chain(node_chain): """ Purpose: Splits the given node chain in half, returning the second half. If the given chain has an odd length, the extra node is part of the second half of the chain. Pre-conditions: :param node_chain: a node-chain, possibly empty Post-conditions: the original node chain is cut in half! Return: :return: A tuple (nc1, nc2) where nc1 and nc2 are node-chains each containing about half of the nodes in node-chain """ # calculate size n = a5q2.count_chain(node_chain) # special case: empty chain if n == 0: return None, None # special case: chain with one node if n == 1: return None, node_chain # calculate halfway mid = n // 2 # walk along the chain until half-way walker = node_chain prev = None counter = 0 while counter < mid: prev = walker walker = node.get_next(walker) counter += 1 # terminate the first half with a well-placed None node.set_next(prev, None) # return the two new chains return node_chain, walker
def add_to_back(alist, val): """ Purpose Insert val into alist at the end of the node chain Preconditions: :param alist: a list created by create() :param val: a value of any kind Post-conditions: The list increases in size. The new value is last in the list. Return: :return None """ new = node.create(val) if alist["tail"] is None: alist["head"] = new alist["tail"] = new else: node.set_next(alist["tail"], new) alist["tail"] = new alist["size"] += 1
def insert_at(node_chain, value, index): """ Purpose: Insert the given value into the node-chain so that it appears at the the given index. Pre-conditions: :param node_chain: a node-chain, possibly empty :param value: a value to be inserted :param index: the index where the new value should appear Assumption: 0 <= index <= n where n is the number of nodes in the chain Post-condition: The node-chain is modified to include a new node at the given index with the given value as data. Return :return: the node-chain with the new value in it """ # special case: insert at index 0 if index == 0: return node.create(value, node_chain) # walk along the chain until the indicated index walker = node_chain counter = 0 prev = None while walker is not None and counter < index: prev = walker walker = node.get_next(walker) counter += 1 # If there is a node at the index if counter == index: # insert a new node node.set_next(prev, node.create(value, walker)) else: # insert at the very end node.set_next(prev, node.create(value, None)) return node_chain
def insert_value_sorted(node_chain, number_value): """ Purpose: Insert the given number_value into the node-chain so that it appears after a previous value that is <= value. If the node_chain was empty, new value is simply placed at the front. Pre-conditions: :param node_chain: a node-chain, possibly empty, containing only numbers :param number_value: a numerical value to be inserted Assumption: node_chain only contains numbers (which can be compared to the given number_value) Post-condition: The node-chain is modified to include a new node with number_value as its data after a previous node's data value is <= number_value. Return :return: the node-chain with the new value in it """ #if the node chain is empty, add the new node if a5q2.count_chain(node_chain) < 1: node_chain = node.create(number_value, None) #if chain is not empty, find the proper place else: cur_node = node_chain prev_node = None next_node = node.get_next(node_chain) while True: cur_val = node.get_data(cur_node) #check if the value should be placed in front of current node if cur_val == number_value + 1: #check if the target node is the first node if prev_node == None: node_chain = node.create(number_value, cur_node) else: new_node = node.create(number_value, cur_node) node.set_next(prev_node, new_node) break #check if the value should be placed after the current node if cur_val == number_value - 1: #check if target node is the last node in chain if next_node == None: new_node = node.create(number_value, None) node.set_next(cur_node, new_node) else: new_node = node.create(number_value, next_node) node.set_next(cur_node, new_node) break #break if at the end of the node chain if next_node == None: break #move to next node if not at the end of the chain else: prev_node = cur_node cur_node = next_node next_node = node.get_next(next_node) return node_chain
def enqueue(queue, value): """ Purpose adds the given data value to the given queue Pre-conditions: queue: a queue created by create() value: data to be added Post-condition: the value is added to the queue Return: (none) """ new_node = node.create(value, None) if is_empty(queue): queue['front'] = new_node queue['back'] = new_node else: prev_last_node = queue['back'] node.set_next(prev_last_node, new_node) queue['back'] = new_node queue['size'] += 1
def insert_value_at_index(alist, val, idx): """ Purpose Insert val into alist at index idx Preconditions: :param alist: a list created by create() :param val: a value of any kind :param idx: a valid index for the list Post-conditions: The list increases in size. The new value is at index idx. The values previously in the list at idx or later appear after the new value. Return: :return If the index is valid, insert_value_at_index returns True. :return If the index is not valid, insert_value_at_index returns False. """ if idx < 0 or idx > size(alist): return False if idx == 0: add_to_front(alist, val) return True if idx == size(alist): add_to_back(alist, val) return True # general case anode = alist['head'] i = 1 while anode is not None and i < idx: anode = node.get_next(anode) i += 1 new_node = node.create(val, node.get_next(anode)) node.set_next(anode, new_node) alist['size'] += 1 return True
# Remove the 3 from the sequence chain = node.get_next(chain) # Add 6 to the front chain = node.create(6, chain) # add 7 to the end anode = node.create(7) bnode = chain while node.get_next(bnode) != None: bnode = node.get_next(bnode) node.set_next(bnode, anode) # Extra exercises: # Exercise 1 # Display all numbers in the chain # Turn this code into a function! # chain-->[ 3 | *-]-->[ 2 | *-]-->[ 1 | *-]-->[ 5 | *-]-->[ 4 | / ] # Exercise 2 # Count the even numbers # chain-->[ 3 | *-]-->[ 2 | *-]-->[ 1 | *-]-->[ 5 | *-]-->[ 4 | / ] # anode --------------------------^ # Exercise 3 # Check if the data values 2, 9 are in the chain # Turn this code into a function!
def insert_value_sorted(node_chain, number_value): """ Purpose: Insert the given number_value into the node-chain so that it appears after a previous value that is <= value. If the node_chain was empty, new value is simply placed at the front. Pre-conditions: :param node_chain: a node-chain, possibly empty, containing only numbers :param number_value: a numerical value to be inserted Assumption: node_chain only contains numbers (which can be compared to the given number_value) Post-condition: The node-chain is modified to include a new node with number_value as its data after a previous node's data value is <= number_value. Return :return: the node-chain with the new value in it """ if node_chain == None: return node.create(number_value) #1 node anode = node_chain current = node.get_data(anode) if number_value <= current: #add to front, regardless of node size return node.create(number_value, anode) if node.get_next(anode) == None: #add after node.set_next(anode, node.create(number_value)) return anode #2 nodes next1 = node.get_data(node.get_next(anode)) if node.get_next(node.get_next(anode)) == None: if number_value <= next1: #add in middle node.set_next(anode, node.create(number_value, node.get_next(anode))) return anode if number_value > next1: node.set_next(node.get_next(anode), node.create(number_value)) return anode #3+ next1 = node.get_data(node.get_next(anode)) while node.get_next( node.get_next(anode)) != None: #step until the second last one if number_value > current and number_value <= next1: #if larger than current and smaller than next node.set_next(anode, node.create(number_value, node.get_next(anode))) return node_chain anode = node.get_next(anode) current = node.get_data(anode) next1 = node.get_data(node.get_next(anode)) if number_value <= next1: #check last 2 values node.set_next(anode, node.create(number_value, node.get_next(anode))) return node_chain node.set_next(node.get_next(anode), node.create(number_value)) return node_chain