def delete_front_nodes(node_chain, n): """ Purpose: Deletes the first n nodes from the front of the node chain. Pre-Conditions: :param node_chain: a node-chain, possibly empty :param n: integer, how many nodes that should be removed off the front of the node chain Post-conditions: The node-chain is changed, by removing the first n nodes. If n>length of node_chain, node_chain is set to be empty (None) Return: :return: The resulting node chain, which may now be empty (None) """ cur_node = node_chain count = 0 #increment through the node chain until cur_node is the nth node to delete while True: count += 1 if cur_node == None: node_chain = None break elif count == n: node_chain = node.get_next(cur_node) cur_node = node.get_next(cur_node) return node_chain
def sorted(alist): """ Purpose sort alist in increasing order Preconditions: :param alist: a list created by create() Post-conditions: alist is rearranged in increasing order Return: None """ new_llist = create() for i in range(size(alist)): small_idx = None small_val = None cur_node = alist['head'] cur_idx = 0 while cur_node is not None: cur_val = node.get_data(cur_node) if small_idx is None or cur_val < small_val: small_idx = cur_idx small_val = cur_val else: cur_idx += 1 cur_node = node.get_next(cur_node) add_to_back(new_llist, small_val) delete_item_at_index(alist, small_idx) #add back every value to alist in increasing order cur_node = new_llist['head'] while cur_node is not None: cur_val = node.get_data(cur_node) add_to_back(alist, cur_val) cur_node = node.get_next(cur_node)
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 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 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 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 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 to_string_correct(node_chain): """ Purpose: Create a string representation of the node chain. E.g., [ 1 | *-]-->[ 2 | *-]-->[ 3 | / ] Pre-conditions: :param node_chain: A node-chain, possibly empty Post_conditions: None Return: A string representation of the nodes. """ # special case: empty node chain if node_chain is None: result = 'EMPTY' else: # walk along the chain walker = node_chain value = node.get_data(walker) # print the data result = '[ ' + str(value) + ' |' while node.get_next(walker) is not None: walker = node.get_next(walker) value = node.get_data(walker) # represent the next with an arrow-like figure result += ' *-]-->[ '+str(value)+' |' # at the end of the chain, use '/' result += ' / ]' return result
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 to_string(node_chain): """ Purpose: Create a string representation of the node chain. E.g., [ 1 | *-]-->[ 2 | *-]-->[ 3 | / ] Pre-conditions: :param node_chain: A node-chain, possibly empty Post_conditions: None Return: A string representation of the nodes. """ # special case: empty node chain if node_chain is None: return 'EMPTY' value = node.get_data(node_chain) # print the data result = '[ ' + str(value) + ' |' if node.get_next(node_chain) is None: # at the end of the chain, use '/' result += ' / ]' else: result += ' *-]-->' result += to_string(node.get_next(node_chain)) return result
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 get_index_of_value(alist, val): """ Purpose Return the smallest index of the given val in the given alist. Preconditions: :param alist: a list created by create() :param val: a value of any kind Post-conditions: none Return: :return the tuple (True, idx) if the val appears in alist :return the tuple (False, None) if the vale does not appear in alist """ if alist["head"] is None: #if empty return False, None walker = alist["head"] index = 0 while node.get_next(walker) is not None: value = node.get_data(walker) if value == val: return True, index walker = node.get_next(walker) index += 1 value = node.get_data(walker) #check last value if value == val: return True, index return False, None
def replace_last(node_chain, target_val, replacement_val): """ Purpose: Replaces the last occurrence of target data value with the new_value. The chain should at most have 1 data value changed. Pre-conditions: :param node_chain: a node chain, possibly None :param target_val: the target data value we are searching to replace the last instance of :param replacement_val: the data value to replace the target_val that we found Post-conditions: The node-chain is changed, by replacing the last occurrence of target_val. If target_val is not present, then the node_chain returns unaltered. Return: :return: The altered node chain where any data occurrences of target_val has been replaced with replacement_val. """ if node_chain == None: return None anode = node_chain #step through all nodes but last target_node = None while node.get_next( anode ) != None: #referece the node with matching value while stepping through all nodes if node.get_data(anode) == target_val: target_node = anode anode = node.get_next(anode) if node.get_data(anode) == target_val: #check last node target_node = anode if target_node == None: #if no match, return list return node_chain else: #if found, replace and return node.set_data(target_node, replacement_val) #if found, replace and return 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 to_string(node_chain): """ Purpose: Create a string representation of the node chain. E.g., [ 1 | *-]-->[ 2 | *-]-->[ 3 | / ] Pre-conditions: :param node_chain: A node-chain, possibly empty Post_conditions: None Return: A string representation of the nodes. """ # special case: empty node chain if node_chain == None: #added return here so rest of the code wont be executed return 'EMPTY' walker = node_chain value = node.get_data(walker) result = '[ ' + str(value) + ' |' while node.get_next( walker) != None: #Heres the bug, didnt index dictionary walker = node.get_next(walker) value = node.get_data(walker) # represent the next with an arrow-like figure result += ' *-]-->[ ' + str(value) + ' |' # at the end of the chain, use '/' result += ' / ]' return result
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 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 copy(node_chain): """ purpose: create a new node chain that is identical to node_chain Preconditions: node_chain: a node chain post-conditions: an identical node chain is created return: the newly created node chain """ if node_chain == None: return None if node.get_next(node_chain) == None: #base case, 1 node return node.create(node.get_data(node_chain)) else: value = node.get_data(node_chain) return node.create(value, copy(node.get_next(node_chain)))
def replace_last(node_chain, target_val, replacement_val): """ Purpose: Replaces the last occurrence of target data value with the new_value. The chain should at most have 1 data value changed. Pre-conditions: :param node_chain: a node chain, possibly None :param target_val: the target data value we are searching to replace the last instance of :param replacement_val: the data value to replace the target_val that we found Post-conditions: The node-chain is changed, by replacing the last occurrence of target_val. If target_val is not present, then the node_chain returns unaltered. Return: :return: The altered node chain where any data occurrences of target_val has been replaced with replacement_val. """ cur_node = node_chain target_node = None #increment through the node chain to find the last example that matches target_val while cur_node != None: cur_value = node.get_data(cur_node) if cur_value == target_val: target_node = cur_node cur_node = node.get_next(cur_node) #if there is a target node, change its data value if target_node != None: node.set_data(target_node, replacement_val) 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 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 retrieve_data_at_index(alist, idx): """ Purpose Return the value stored in alist at the index idx Preconditions: :param alist: a list created by create() :param idx: a non-negative integer Post-conditions: none Return: :return (True, val) if val is stored at index idx and idx is valid :return (False, None) if the idx is not valid for the list """ #check if target index is within scope of alist if alist['size'] - idx < 1: return False, None else: cur_idx = 0 cur_node = alist['head'] while cur_node is not None: if cur_idx == idx: return True, node.get_data(cur_node) else: cur_idx += 1 cur_node = node.get_next(cur_node)
def set_data_at_index(alist, idx, val): """ Purpose Store val into alist at the index idx Preconditions: :param alist: a list created by create() :param val: a value of any kind :param idx: a non-negative integer Post-conditions: The value stored at index idx changes to val Return: :return True if the index was valid, False otherwise """ cur_node = alist['head'] cur_idx = 0 #check if target index is within scope of alist if alist['size'] - idx < 1: return False else: while cur_node is not None: if cur_idx == idx: node.set_data(cur_node, val) return True else: cur_idx += 1 cur_node = node.get_next(cur_node)
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 slice(alist, start, end, step=1): """ Purpose creates a new list of nodes from index start to index end selecting each node index start + i * step Preconditions: :param alist: a list created by create() :param start: integer of desired start :param end: integer of desired end :param step: integer of desired step or None if empty Post-conditions: None Return: :new_llist: a new list """ cur_idx = 0 target_idx = start cur_node = alist['head'] data_list = [] while cur_idx < end: if cur_idx == target_idx: data_list.append(node.get_data(cur_node)) target_idx += step cur_node = node.get_next(cur_node) cur_idx += 1 new_llist = create() while len(data_list) > 0: add_to_back(new_llist, data_list.pop(0)) return new_llist
def to_string(node_chain): """ purpose: represent a node chain using string notation. Preconditions: node_chain: a node chain post-conditions: none return: a string that represent the node chain """ if node_chain == None: #empty chain return "EMPTY" if node.get_next(node_chain) == None: #single node return '[ ' + str(node.get_data(node_chain)) + ' |' + ' / ]' else: #more than 1 nodes return '[ ' + str( node.get_data(node_chain)) + ' | * -]-->' + to_string( node.get_next(node_chain))
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 count_chain(node_chain): """ Purpose: Counts the number of nodes in the node chain. Pre-conditions: :param node_chain: a node chain, possibly empty Return: :return: The number of nodes in the node chain. """ if node_chain == None: return 0 count = 1 anode = node_chain while node.get_next(anode) != None: anode = node.get_next(anode) count += 1 return count
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 replace(node_chain, target, replacement): """ purpose: replace data in node chain if data matches target Preconditions: node_chain: a node chain post-conditions: data in node chain possibly altered return: reference to the node_chain """ if node_chain == None: return None if node.get_next(node_chain) == None: #base case if node.get_data(node_chain) == target: node.set_data(node_chain, replacement) return node_chain if node.get_data(node_chain) == target: node.set_data(node_chain, replacement) replace(node.get_next(node_chain), target, replacement) else: replace(node.get_next(node_chain), target, replacement) return node_chain