Beispiel #1
0
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
Beispiel #2
0
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)
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
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
Beispiel #7
0
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
Beispiel #8
0
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
Beispiel #9
0
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
Beispiel #10
0
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
Beispiel #11
0
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
Beispiel #12
0
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)
Beispiel #13
0
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
Beispiel #14
0
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
Beispiel #15
0
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)
Beispiel #16
0
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
Beispiel #17
0
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
Beispiel #18
0
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
Beispiel #19
0
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)))
Beispiel #20
0
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
Beispiel #21
0
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
Beispiel #22
0
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)
Beispiel #23
0
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)
Beispiel #24
0
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)
Beispiel #25
0
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
Beispiel #26
0
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))
Beispiel #27
0
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
Beispiel #28
0
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
Beispiel #29
0
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)
Beispiel #30
0
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