def mirrored(t1, t2): """ Purpose: checks if 2 binary trees satisfy the mirror property preconditions: :param t1: a tree :param t2: a tree that might mirror t1 postconditions: none :return: True if the 2 trees are mirrors of each other, False otherwise """ if t1 is None and t2 is None: #if both are None, return True return True if t1 is None or t2 is None: #if 1 is None, return False return False return tn.get_data(t1) == tn.get_data(t2) and mirrored( tn.get_left(t1), tn.get_right(t2)) and mirrored( tn.get_right(t1), tn.get_left(t2)) #compare data, and the rest
def subst(tnode, t, r): """ Purpose: Find the target value in a Tree and replace it Preconditions: :param tnode: A Node chain :param t: The data to be replaced :param r: Data to replace target Post-conditions: modifies original node data :return: The Tree after replacement of data """ if tnode is None: # Special case where tree node is empty return elif tn.get_data( tnode) == t: # Case where data is found at current tree node tn.set_data(tnode, r) left = tn.get_left(tnode) right = tn.get_right(tnode) subst(left, t, r) subst(right, t, r) return tnode else: left = tn.get_left(tnode) right = tn.get_right( tnode) # Case where data is not found, move to next ree node subst(left, t, r) subst(right, t, r) return tnode
def ordered(tnode): # helper internal function def collect_data_inorder(tnode): if tnode is None: return [] else: return collect_data_inorder(tn.get_left(tnode)) + [tn.get_data(tnode)] \ + collect_data_inorder(tn.get_right(tnode)) # main recursive procedure if tnode is None: return True else: cur_data = tn.get_data(tnode) left_sub = tn.get_left(tnode) right_sub = tn.get_right(tnode) left_list = collect_data_inorder(left_sub) right_list = collect_data_inorder(right_sub) if len(left_list) == 0 and len(right_list) == 0: return True elif len(left_list) == 0 and min(right_list) > cur_data: return ordered(right_sub) elif len(right_list) == 0 and max(left_list) < cur_data: return ordered(left_sub) if max(left_list) < cur_data and min(right_list) > cur_data: return ordered(left_sub) and ordered(right_sub) else: return False
def insert_prim(tnode, value): """ Insert a new value into the binary tree. Preconditions: :param tnode: a binary search tree, created by create() :param value: a value Postconditions: If the value is not already in the tree, it is added to the tree Return :return: flag, tree Flag is True is insertion succeeded; tree is the tree with value in it Flag is False if the value is already in the tree, tree is returned unchanged """ if tnode is None: return True, tn.create(value) else: cval = tn.get_data(tnode) if cval == value: return False, tnode elif value < cval: flag, subtree = insert_prim(tn.get_left(tnode), value) if flag: tn.set_left(tnode, subtree) return flag, tnode else: flag, subtree = insert_prim(tn.get_right(tnode), value) if flag: tn.set_right(tnode, subtree) return flag, tnode
def copy(tnode): """ Purpose: create a new object that is the same as tnode Preconditions: :param tnode: a tree Postconditions: a new object created, tnode not changed :return: reference to the newly created tree """ if tnode == None: return None if tf.is_leaf(tnode) is True: #base: if leaf, create tree with data return tn.create(tn.get_data(tnode)) new_tree = tn.create(tn.get_data(tnode)) #recursive: set left and right to copy() child tn.set_left(new_tree, copy(tn.get_left(tnode))) tn.set_right(new_tree, copy(tn.get_right(tnode))) return new_tree
def to_string(tnode, level=0): """ Produce a formatted string to represent the hierarchy of a tree. Tree diagrams usually have the root at the top. Here the root is at the top left. - every data value appears on its own line - the levels of a tree are columns from left to right - nodes at the same level start in the same column - very long data values might cause the presentation to get messy - subtrees appear below a parent - left subtree immediately - right subtree after the entire left subtree Pre-conditions: :param tnode: a Binary tree (treenode or None) :param level: the level of the tnode (default value 0) Return: A string with the hierarchy of the tree. """ if tnode is None: return 'EMPTY' else: result = '\t' * level result += str(TN.get_data(tnode)) if TN.get_left(tnode) is not None: result += '\n' + to_string(TN.get_left(tnode), level + 1) if TN.get_right(tnode) is not None: result += '\n' + to_string(TN.get_right(tnode), level + 1) return result
def build_fibtree(n): """ Purpose: Build a tree whose structure represents the Fibonacci numbers. The root of the tree has data value Fib(n). This function can return very large trees. Pre-conditions: :param n: a non-negative integer Return: :return: a primitive binary tree whose structure reflects the calculation of fib(n) """ if n <= 1: return tn.create(n) else: ltree = build_fibtree(n-1) rtree = build_fibtree(n-2) return tn.create(tn.get_data(ltree)+tn.get_data(rtree), ltree, rtree)
def reflection(tnode): """ Purpose: create a new tree that is the mirror of the original precoditions: :param tnode: a tree Postconditions: a new object is created :return: the new tree that is the mirror of the original """ if tnode == None: return if tf.is_leaf(tnode) is True: return tn.create(tn.get_data(tnode)) mirrored = tn.create(tn.get_data( tnode)) # recursive: set left and right to right and left of tnode tn.set_left(mirrored, reflection(tn.get_right(tnode))) tn.set_right(mirrored, reflection(tn.get_left(tnode))) return mirrored
def closest(tnode, target): """ Purpose: Find the closes value to the target in the nodes of a tree Preconditions: :param tnode: A Tree node :param target: A target integer :return: The closest value in the nodes to the target """ if tn.get_data( tnode ) == target: # if it is the target cant get any closer so return data return tn.get_data(tnode) if tnode is None: # if tnode is none return return 0 else: closest(tn.get_left(tnode), target) # iterate through the data values closest(tn.get_right(tnode), target)
def mirrored(t1, t2): """ Purpose: Determine if t1 and t2 are mirrored. Pre-conditions: :param t1: a treenode :param t2: a treenode Return: :return: True if they are mirrored, False otherwise """ if t1 is None and t2 is None: return True elif t1 is None or t2 is None: return False else: return (tn.get_data(t1) == tn.get_data(t2) and mirrored(tn.get_left(t1), tn.get_right(t2)) and mirrored(tn.get_right(t1), tn.get_left(t2)))
def subst(tnode, t, r): """ Purpose: replace target value with replacement value in a tree Preconditions: :param tnode: a tree :param t: target value :param r: replacement value Postconditions: values are replaced, if match :return: None """ if tnode == None: return None if tf.is_leaf(tnode) is True: #base if tn.get_data(tnode) == t: tn.set_data(tnode, r) if tn.get_data(tnode) == t: tn.set_data(tnode, r) subst(tn.get_left(tnode), t, r) subst(tn.get_right(tnode), t, r)
def path_to(tnode, value): """ Purpose: to determine if value is found in a tree and return a list with the path to that value from root Preconditions: :param tnode: a tree :param value: a value to find :return: tuple (True, alist) if found, (False, None) if not found """ if tnode is None: return False, None this_node = tn.get_data(tnode) #base if this_node == value: #if match return True, [this_node] #recursive left, left_value = path_to(tn.get_left(tnode), value) if left: return True, left_value + [tn.get_data(tnode)] right, right_value = path_to(tn.get_right(tnode), value) if right: return True, right_value + [tn.get_data(tnode)] return False, None
def in_order(tnode): """ Display the nodes of a tree in pre-order. :param tnode: a primitive tree :return: nothing """ if tnode is None: return else: in_order(tn.get_left(tnode)) print(tn.get_data(tnode), end=" ") in_order(tn.get_right(tnode))
def mirrored(t1, t2): """ Purpose: Determine if two inputted trees are reflections of each other Preconditions: :param t1: A tree node :param t2: A tree node Post-conditions: None :return: A boolean value if the two trees are reflections or not """ if t1 is None and t2 is None: # If both are empty it is a reflection return True elif t1 is None or t2 is None: return False elif tn.get_right(t1) is None and tn.get_left( t1) is None: # If reached end of iteration return tn.get_data(t1) == tn.get_data(t2) elif tn.get_right(t2) is None and tn.get_left(t2) is None: return tn.get_data(t1) == tn.get_data(t2) else: # If not false already iterate though the trees if tn.get_data(t1) == tn.get_data(t2): left1 = tn.get_left(t1) right1 = tn.get_right(t1) left2 = tn.get_left(t2) right2 = tn.get_right(t2) return mirrored(left1, right2) and mirrored(left2, right1) return False
def breadth_first_order(tnode): explore = MyQueue.create() MyQueue.enqueue(explore, tnode) while MyQueue.size(explore) > 0: current = MyQueue.dequeue(explore) print(tn.get_data(current), end=" ") left = tn.get_left(current) if left is not None: MyQueue.enqueue(explore, left) right = tn.get_right(current) if right is not None: MyQueue.enqueue(explore, right)
def refection(tnode): """ Purpose: Copy the inputted tree and return a reflected copy Preconditions: :param tnode: A tree node to be reflected and copied Post-conditions: None :return: The reflected and copied tree """ if tnode is None: # Special case if tree is None return None else: # a new tree with subtrees swapped return tn.create(tn.get_data(tnode), refection(tn.get_right(tnode)), refection(tn.get_left(tnode)))
def copy(tnode): """ Purpose: Copy a tree and return the copy Preconditions: :param tnode: A tree node to be copied Post-conditions: None :return: The reference to the copied tree """ if tnode is None: # Special case if tree is None return None else: return tn.create( tn.get_data(tnode), copy(tn.get_left(tnode)), copy(tn.get_right(tnode))) # return a copy of items in tree
def copy(tnode): """ Purpose: Make a copy of the tree rooted at the given tnode. Pre-conditions: :param tnode: A treenode Return: :return: A copy of the tree. """ if tnode is None: return None else: return tn.create(tn.get_data(tnode), copy(tn.get_left(tnode)), copy(tn.get_right(tnode)))
def collect_data_inorder(tnode): """ Purpose: Return a list of data values with inorder sequence. Pre-conditions: :param tnode: a treenode Return :return: A list of data values, with inorder sequence """ if tnode is None: return [] else: return (collect_data_inorder(tn.get_left(tnode)) + [tn.get_data(tnode)] + collect_data_inorder(tn.get_right(tnode)))
def delete_bst(tnode): if tnode is None: return False, tnode else: cval = tn.get_data(tnode) if cval == value: return reconnect(tnode) elif value < cval: flag, subtree = delete_bst(tn.get_left(tnode)) if flag: tn.set_left(tnode, subtree) return flag, tnode else: flag, subtree = delete_bst(tn.get_right(tnode)) if flag: tn.set_right(tnode, subtree) return flag, tnode
def member(tnode, val): """ Purpose: Determine if val is stored as data in a tree. Pre-conditions: :param tnode: a treenode Post-conditions: none Return :return: the height of the tree as an integer """ if tnode == None: return False elif tn.get_data(tnode) == val: return True else: return member(tn.get_left(tnode), val) \ or member(tn.get_right(tnode), val)
def count_target(tnode, target): """ Purpose: Counts the number of times the given target appears in the given tree Pre-condition: tnode: the given tree node target: the target value Post condition: None Return: the number of times the given target value appears in the given tree """ count = 0 if tnode is None: pass else: if tn.get_data(tnode) == target: count += 1 count += count_target(tn.get_right(tnode), target) count += count_target(tn.get_left(tnode), target) return count
def collect_data_inorder(tnode): """ Purpose: To collect all the data values in the given tree. Returns a list of all the data values, and the data values appear in the list according to the in-order sequence. Pre-conditions: :param tnode: a treenode Post-conditions: None Return: a list of all the values in tnode in inorder sequence """ if tnode is None: return [] else: return collect_data_inorder(tn.get_left(tnode)) + [tn.get_data(tnode)] \ + collect_data_inorder(tn.get_right(tnode))
def smallest_leaf_value(tnode): """ Purpose: Find the smallest value in the leaf nodes of a tree Preconditions: :param tnode: A Tree node :return: The smallest value in the leaf nodes data """ if tnode is None: # If node is none return none return None if tn.get_right(tnode) is None and tn.get_left( tnode) is None: # If it is a leaf node, return data return tn.get_data(tnode) else: left = smallest_leaf_value(tn.get_left( tnode)) # loop through the left and right branches of tree right = smallest_leaf_value(tn.get_right(tnode)) return min(left, right) # Return smallest value
def subst(tnode, t, r): """ Purpose: To substitute a target value t with a replacement value r wherever it appears as a data value in the given tree Pre-conditions: tnode: the given tree node t: target value r: replacement value Post conditions: the target value is replaced with the replacement value Return: None """ if tnode is not None and tn.get_data(tnode) == t: tn.set_data(tnode, r) elif tnode is None: pass else: subst(tn.get_right(tnode), t, r) subst(tn.get_left(tnode), t, r)
def copy(tnode): """ Purpose: To create an exact copy of the given tree, with completely new treenodes, but exactly the same data values, in exactly the same places Pre-conditions: :param tnode: a treenode Post-conditions: None return: A copy of tnode """ if tnode is None: return None else: cur_val = tn.get_data(tnode) new_tnode = tn.create(cur_val) tn.set_left(new_tnode, copy(tn.get_left(tnode))) tn.set_right(new_tnode, copy(tn.get_right(tnode))) return new_tnode
def breadth_first_order(tnode): """ Display the nodes of a tree in breadth-first-order. :param tnode: a primitive tree :return: nothing """ nodes = Queue.create() Queue.enqueue(nodes, tnode) order = Queue.create() # while Queue.size(nodes) > 0: current = Queue.dequeue(nodes) if current is not None: Queue.enqueue(order, tn.get_data(current)) Queue.enqueue(nodes, tn.get_left(current)) Queue.enqueue(nodes, tn.get_right(current)) while not Queue.is_empty(order): n = Queue.dequeue(order) print(n, end=" ")
def subst(tnode, t, r): """ Purpose: Replace every occurrence of data value t with r in the tree Pre-conditions: :param tnode: a treenode :param: t: a target value :param: r: a replacement value Post-conditions: Every occurrence of the target value is replaced Return :return: None """ if tnode == None: return else: if tn.get_data(tnode) == t: tn.set_data(tnode, r) subst(tn.get_left(tnode), t, r) subst(tn.get_right(tnode), t, r)
def count_smaller(tnode, target): """ Purpose: Count the number of times a target value appears in the tree rooted at tnode. Pre-conditions: :param tnode: a treenode :param target: a value Return: The number of times a value appears in the tree. """ if tnode is None: return 0 else: total = count_smaller(tn.get_left(tnode), target) \ + count_smaller(tn.get_right(tnode), target) if tn.get_data(tnode) < target: return 1 + total else: return total
def member_prim(tnode, value): """ Check if value is stored in the binary search tree. Preconditions: :param tnode: a binary search tree :param value: a value Postconditions: none :return: True if value is in the tree """ if tnode is None: return False else: cval = tn.get_data(tnode) if cval == value: # found the value return True elif value < cval: # use the BST property return member_prim(tn.get_left(tnode), value) else: return member_prim(tn.get_right(tnode), value)