def _clone(root): if not root: return None root_ = Node(root.value) root_.left = _clone(root.left) root_.right = _clone(root.right) return root_
def _from_traversal(inorder, postorder): # Empty traversal lists, return empty node if not inorder: return None # Create root node for this subtree root = Node(postorder[-1]) # Locate root in inorder traversal sequence root_idx = inorder.index(postorder[-1]) root.left = _from_traversal(inorder[:root_idx], postorder[:root_idx]) root.right = _from_traversal(inorder[root_idx + 1:], postorder[root_idx:-1]) return root
def clone_i(bintree): s = Stack() # contains cloned node references, a', for each node a # doubles as visited[] map => if cloned_nodes[a] is not empty => a is visited cloned_nodes = {} if not bintree or not bintree.root: return None # Helper function to check if a node is already 'done'/processed # a node is considered 'done' # if its value is None # or # if it has already been cloned. isDone = lambda node, cloned_node: True if (node is None or cloned_node is not None) else False s.push(bintree.root) while s: node = s.top() left_clone = cloned_nodes.get(node.left) right_clone = cloned_nodes.get(node.right) # Both left and right subtrees are done # pop 'node' off the stack, create a clone, and map the clone to the original # Link cloned node's left and right children if isDone(node.left, left_clone) and isDone( node.right, right_clone): s.pop() node_ = Node(node.value) node_.left = left_clone node_.right = right_clone cloned_nodes[node] = node_ else: # push both left and right children to the stack # NOTE: This actually processes reverse post-order (right-left-root) # unless we push right, followed by left onto the stack # but order shouldnt really matter s.push(node.left) if node.left else None s.push(node.right) if node.right else None return BinaryTree(root=cloned_nodes[bintree.root])
def fromList(array): # lambda helper functions to get parent, left, and right nodes indices # from current index parent = lambda i: (i - 1) / 2 left = lambda i: 2 * i + 1 right = lambda i: 2 * i + 2 # All odd indices are left children, # even indices are right children in the binary tree isLeftChild = lambda i: (i & 1 == 1) # root cannot be empty if not array or array[0] is None: return None root = Node(array[0]) btree = BinaryTree(root) nodes_list = [root] for i in xrange(1, len(array)): n = None if array[i] is not None: n = Node(array[i]) p = nodes_list[parent(i)] if p is None: continue if isLeftChild(i): p.left = n else: p.right = n nodes_list.append(n) return btree
def populated_tree_2(): n1 = Node(42) n2 = Node(100) n3 = Node(600) n4 = Node(15) n5 = Node(160) n6 = Node(200) n7 = Node(350) n8 = Node(125) n9 = Node(175) n10 = Node(4) n11 = Node(500) n1.left = n2 n1.right = n3 n2.left = n4 n2.right = n5 n3.left = n6 n3.right = n7 n5.left = n8 n5.right = n9 n7.left = n10 n7.right = n11 bt = BinaryTree(n1) return bt
def traversals(): # prefix equation tree : "+a*bc" ''' + / \ a * / \ b c ''' root = Node("+") lnode = Node("a") rnode = Node("*") root.setChildren(lnode, rnode) rlnode = Node("b") rrnode = Node("c") rnode.setChildren(rlnode, rrnode) btree = BinaryTree(root) print 'Preorder: ', btree.preorder_traversal() print l = [] # define a lambda function that collates individual node values into a list collate_fn = lambda kwargs, data : kwargs['lst'].append(data) btree.preorder_traversal(collate_fn, lst=l) assert (l == ['+', 'a', '*', 'b', 'c']) print 'Postorder: ', btree.postorder_traversal() print l = [] btree.postorder_traversal(collate_fn, lst=l) assert (l == ['a', 'b', 'c', '*', '+']) print 'Inorder: ', btree.inorder_traversal() print l = [] btree.inorder_traversal(collate_fn, lst=l) assert (l == ['a', '+', 'b', '*', 'c']) print 'Level order: ', btree.levelorder_traversal() print l = [] btree.levelorder_traversal(collate_fn, lst=l) assert (l == ['+', 'a', '*', 'b', 'c']) print 'Left View: ', btree.left_view() print l = [] btree.left_view(collate_fn, lst=l) assert (l == ['+', 'a', 'b']) print 'Right View: ', btree.right_view() print l = [] btree.right_view(collate_fn, lst=l) assert (l == ['+', '*', 'c']) print 'Top View: ', btree.top_view() print l = [] btree.top_view(collate_fn, lst=l) assert (l == ['+', 'a', '*', 'c']) print 'Top View L-R: ', btree.top_view_LR() print l = [] btree.top_view_LR(collate_fn, lst=l) assert (l == ['a', '+', '*', 'c']) print 'Bottom View: ', btree.bottom_view() print l = [] btree.bottom_view(collate_fn, lst=l) assert (l == ['a', 'b', '*', 'c']) print 'Testcase TC1 passed!'
def basic_tests(): # prefix equation tree : "+a*bc" ''' + / \ a * / \ b c ''' root = Node("+") lnode = Node("a") rnode = Node("*") root.setChildren(lnode, rnode) rlnode = Node("b") rrnode = Node("c") rnode.setChildren(rlnode, rrnode) btree = BinaryTree(root) assert(btree.height() == 3) assert btree.span() == 3 assert btree.width() == 2 ''' 1 / \ 3 2 / \ \ 5 3 9 ''' root = Node("1") root.setChildren(Node("3"), Node("2")) root.left.setChildren(Node("5"), Node("3")) root.right.right = Node("9") btree2 = BinaryTree(root) assert(btree2.height() == 3) assert btree2.span() == 4 assert btree2.width() == 3 ''' 1 / \ 3 2 / 5 ''' root = Node("1") root.setChildren(Node("3"), Node("2")) root.left.left = Node("5") btree3 = BinaryTree(root) assert(btree3.height() == 3) assert btree3.span() == 3 assert btree3.width() == 2 btree4 = BinaryTree(Node('blah')) assert(btree4.height() == 1) assert btree4.span() == 0 assert btree4.width() == 1
def test_path_and_lca(): ''' 1 / \ 2 3 / \ / \ 4 5 6 7 ''' root = Node(1) lnode = Node(2) rnode = Node(3) root.setChildren(lnode, rnode) lnode.setChildren(Node(4), Node(5)) rnode.setChildren(Node(6), Node(7)) btree = BinaryTree(root) assert(btree.height() == 3) nodes = btree.path_n(7) path = [1,3,7] i=0 assert(len(nodes) == 3) for n in nodes: assert n.value == path[i] i += 1 # find path using a node reference nodes = btree.path_n(rnode) path = [1,3] i=0 for n in nodes: assert n.value == path[i] i += 1 assert(btree.path_n(8) == []) assert btree.path_1(7) == [1,3,7] assert btree.path_1(5) == [1,2,5] assert btree.path_1(6) == [1,3,6] assert btree.path_1(1) == [1] assert btree.path_1(2) == [1, 2] assert btree.path_1(9) == [] assert btree.path_2(7) == [1,3,7] assert btree.path_2(5) == [1,2,5] assert btree.path_2(6) == [1,3,6] assert btree.path_2(1) == [1] assert btree.path_2(2) == [1, 2] assert btree.path_2(9) == [] assert btree.path(2) == [1, 2] assert btree.path(9) == [] # Test paths-based LCA n1 = rnode.left n2 = lnode.right assert n1.value == 6 assert n2.value == 5 assert btree.lca_p(n1, n2) == root assert btree.lca_p(rnode, lnode) == root assert btree.lca_p(rnode.right, rnode.left) == rnode assert btree.lca_p(lnode.right, lnode.left) == lnode assert btree.lca_p(lnode.left, rnode.right) == root assert btree.lca_p(rnode, 2) == root assert btree.lca_p(7, rnode.left) == rnode assert btree.lca_p(5, 4) == lnode assert btree.lca_p(4, 7) == root assert btree.lca_p(2, 4) == root.left assert btree.lca_p(4, 2) == root.left assert btree.lca_p(3, 7) == root.right assert btree.lca_p(7, 3) == root.right # Test efficient LCA that obviates the need for storing paths assert btree.lca(n1, n2) == root assert btree.lca(rnode, lnode) == root assert btree.lca(rnode.right, rnode.left) == rnode assert btree.lca(lnode.right, lnode.left) == lnode assert btree.lca(lnode.left, rnode.right) == root assert btree.lca(rnode, 2) == root assert btree.lca(4, 5) == root.left assert btree.lca(5, 4) == root.left assert btree.lca(7, rnode.left) == rnode assert btree.lca(5, 4) == lnode assert btree.lca(4, 7) == root assert btree.lca(2, 4) == root.left assert btree.lca(4, 2) == root.left assert btree.lca(3, 7) == root.right assert btree.lca(7, 3) == root.right