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 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_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 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 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 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 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 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 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
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 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 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 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 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 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 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: 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 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 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
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 == None: return None if node.get_next == None: # only 1 data, return node chain return node_chain anode = node_chain new_node = node.create(node.get_data(anode)) # end of new node while node.get_next( anode ) != None: # step through original and create new node in reverse new_node = node.create(node.get_data(node.get_next(anode)), new_node) anode = node.get_next(anode) return new_node
def contains_duplicates(node_chain): """ Purpose: Returns whether or not the given node_chain contains one or more duplicate data values. Pre-conditions: :param node_chain: a node-chain, possibly empty Return: :return: True if duplicate data value(s) were found, False otherwise """ if node_chain == None or node.get_next(node_chain) == None: return False anode = node_chain values = [] # store values in a list while node.get_next(anode) != None: this_data = node.get_data(anode) if this_data in values: #check if current data is in list return True anode = node.get_next(anode) values.append(this_data) if node.get_data(anode) in values: # check last node return True return False
def remove_from_front(alist): """ Purpose Removes and returns the first 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: node_to_remove = alist['head'] removed_data = node.get_data( node_to_remove) #data to be removed and returned new_head = node.get_next(node_to_remove) alist['head'] = new_head alist['size'] -= 1 return True, removed_data
def value_is_in(alist, val): """ Purpose Check if the given value is in the given list Preconditions: :param alist: a list created by create() :param val: a value of any kind Post-conditions: none Return: :return True if the value is in the list, False otherwise """ if alist["head"] is None: #if empty return False walker = alist["head"] while node.get_next(walker) is not None: value = node.get_data(walker) if value == val: return True walker = node.get_next(walker) value = node.get_data(walker) #check last value if value == val: return True return False
def insert_at_node(self, data, node): if data < node.get_data(): if node.get_left() == None: temp = node.Node(); temp.set_data(data); node.set_left(temp); else: self.insert_at_node(data, node.get_left()); else: if node.get_right() == None: temp = node.Node(); temp.set_data(data); node.set_right(temp); else: self.insert_at_node(data, node.get_right())
def insert_at_node(self, data, node): if data < node.get_data(): if node.get_left() == None: temp = node.Node() temp.set_data(data) node.set_left(temp) else: self.insert_at_node(data, node.get_left()) else: if node.get_right() == None: temp = node.Node() temp.set_data(data) node.set_right(temp) else: self.insert_at_node(data, node.get_right())
def peek(queue): """ Purpose returns the value from the front of given stack without removing it Pre-conditions: queue: a non-empty queue created by create() Post-condition: None Return: the value at the front of the queue """ assert not is_empty(queue), 'peeked into an empty queue' first_node = queue['front'] result = node.get_data(first_node) return result
def average(node_chain, sum=0, count=0): """ Purpose: returns the average of all the data in the node chain Pre-conditions: :param node_chain: a node chain, possibly empty, only contains numbers as data Return: :return: The average of all the data in the node chain """ if node_chain is None: if count == 0: return 0 else: return sum / count else: value = node.get_data(node_chain) return average(node.get_next(node_chain), sum + value, count + 1)
def peek(stack): """ Purpose returns the value from the front of given stack without removing it Pre-conditions: stack: a stack created by create() Post-condition: None Return: the value at the front of the stack """ assert not is_empty(stack), 'peeked into an empty stack' first_node = stack['top'] result = node.get_data(first_node) return result
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 pop(stack): """ Purpose removes and returns a data value from the given stack Pre-conditions: stack: a stack created by create() Post-condition: the first value is removed from the stack Return: the first value in the stack, or None """ assert not is_empty(stack), 'popped an empty stack' prev_first_node = stack['top'] result = node.get_data(prev_first_node) stack['top'] = node.get_next(prev_first_node) stack['size'] -= 1 return result