def complete(tnode): """ Purpose : Determine if the given tree is complete . Pre - conditions : : param tnode : a primitive binary tree Return : return : A tuple (True , height ) if the tree is complete , A tuple (False , None ) otherwise . """ print("TNODE", tnode) if tnode is None: return False, None if tn.get_left(tnode) is None and tn.get_right( tnode) is None: # complete subtree print("subtree complete") return True, +1 if tn.get_left(tnode) is None and tn.get_right( tnode) is not None: # incomplete subtree print("this") return False, None if tn.get_right(tnode) is None and tn.get_left( tnode) is not None: # incomplete subtree print("that") return False, None else: ldepth = complete(tn.get_left(tnode)) rdepth = complete(tn.get_right(tnode)) return True, +1
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 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 ordrd(tnode): # Check for no tree if tnode is None: return True, None else: # Check for tree end if Tn.get_left(tnode) is None and Tn.get_right(tnode) is None: return True, Tn.get_data(tnode) # Check for proper order # Check for proper order without left elif Tn.get_left(tnode) is None: if ordrd(Tn.get_right(tnode))[1] > Tn.get_data(tnode): return True, Tn.get_data(tnode) else: return False, Tn.get_data(tnode) # Check for proper order without right elif Tn.get_right(tnode) is None: if ordrd(Tn.get_left(tnode))[1] < Tn.get_data(tnode): return True, Tn.get_data(tnode) else: return False, Tn.get_data(tnode) if ordrd(Tn.get_left(tnode))[1] < Tn.get_data(tnode) and ordrd( Tn.get_right(tnode))[1] > Tn.get_data(tnode): return True, Tn.get_data(tnode) else: return False, Tn.get_data(tnode)
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 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 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 reflect(tnode): """ Purpose: swap every left and right sub tree in a tree preconditions: :param tnode: a tree postconditions: left and right in tree and sub tree swapped :return: nothing """ if tnode is None or tf.is_leaf(tnode) is True: #base: do nothing if end return left = tn.get_left(tnode) right = tn.get_right(tnode) tn.set_left(tnode, right) #swap left and right. tn.set_right(tnode, left) reflect(tn.get_left(tnode)) reflect(tn.get_right(tnode))
def min_level(tnode): """ Purpose: Returns the height of the leaf node with the smallest level Pre-condition: tnode: the given tree node Post condition: None Return: the height of the leaf node at with the smallest level """ height = 0 if tnode is None: pass else: if tn.get_right(tnode) is not None or tn.get_left(tnode) is not None: height += 1 height += min_level(tn.get_left(tnode)) height += min_level(tn.get_right(tnode)) return height
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 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 count_node_types(tnode): """ Purpose: count the number of leaf nodes and non-leaf nodes in a tree. Preconditions :param tnode: a tree node Postconditions: nothing :return: a tuple(# leaf, # non-leaf) """ if tnode == None: return (0, 0) leaf_count = 0 root_count = 0 if tf.is_leaf(tnode) is True: #base case, 1 leaf return (leaf_count + 1, root_count) else: #recursive case leaf_count += count_node_types(tn.get_left(tnode))[0] + count_node_types(tn.get_right(tnode))[0] root_count += (count_node_types(tn.get_left(tnode))[1] + count_node_types(tn.get_right(tnode))[1]) + 1 return (leaf_count, root_count)
def is_leaf(tnode): """ Purpose: Determine if tnode is a leaf. Pre-conditions: :param tnode: a treenode Return: True if the tnode has zero children """ return TN.get_left(tnode) is None and TN.get_right(tnode) is None
def int_cmplt(tnode): if tnode is None: return (True, 0) else: flag_left, ldepth = int_cmplt(tn.get_left(tnode)) flag_right, rdepth = int_cmplt(tn.get_right(tnode)) if ldepth == rdepth: return (flag_left and flag_right, rdepth + 1) else: return (False, 0)
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 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: 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 isLeaf(tnode): """ Purpose: Determine a tree is a leaf node. Pre-conditions: :param tnode: a treenode Post-conditions: none Return :return: True is the treenode has no children """ return tnode != None \ and tn.get_left(tnode) is None \ and tn.get_right(tnode) is None
def nodes_at_level(tnode, level): """ Purpose: count how many nodes are at the given level of a tree. Preconditions: :param tnode: a tree :param level: the level to be counted postconditions: none :return: the number of nodes at the level, 0 if invalid """ if tnode is None: return 0 if level == 0: #base: if we are on the level we want, each node is 1. level is a counter return 1 return nodes_at_level(tn.get_left(tnode), level - 1) + nodes_at_level(tn.get_right(tnode), level -1) #recursive: traverse through tree until level is 0.
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 complete(tnode): """ Purpose: Determine if the given tree is complete. Pre-conditions: :param tnode: a primitive binary tree :return: A tuple (True, height) if the tree is complete, A tuple (False, None) otherwise. """ if tnode is None: return False, None if tf.is_leaf(tnode) is True: #base 1: if leaf return True, 1 elif tn.get_left(tnode) is None or tn.get_right( tnode) is None: #base 2: if incomplete return False, None left_flag, left_height = complete( tn.get_left(tnode)) #check left side first if left_flag is False: return False, None right_flag, right_height = complete( tn.get_right(tnode)) #check right side first if right_flag is False: return False, None if left_height == right_height: #if height is equal, then tree is complete return True, left_height + 1
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 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 count(tnode): """ Purpose: Determine the number of nodes in the tree. Pre-conditions: :param tnode: a treenode Post-conditions: none Return :return: the number of nodes as an integer """ if tnode == None: return 0 else: return 1 + count(tn.get_left(tnode)) \ + count(tn.get_right(tnode))
def sum_leaf_values(tnode): """ Purpose: returns the sum of all the leaf values in the given tree Pre-conditions: tnode: the given tree node Post condition: None Return: the sum of all the leaf values in the tree """ count = 0 if tnode is None: pass elif tf.is_leaf(tnode): count += 1 else: count += sum_leaf_values(tn.get_left(tnode)) count += sum_leaf_values(tn.get_right(tnode)) return count
def cmplt(tnode): if tnode is None: flag = True depth = 0 return flag, depth else: ldepth = cmplt(TN.get_left(tnode)) rdepth = cmplt(TN.get_right(tnode)) if (rdepth[1] is not None) and (ldepth[1] is not None) and ldepth == rdepth: flag = True depth = rdepth[1] + 1 return flag, depth else: flag, depth = False, None return flag, depth
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 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