コード例 #1
0
def find_immediate_common_ancestor_5(root, value1, value2):
    """find_immediate_common_ancestor_5

    algorithm:
      pre-order traversal with value for each level
    """
    if not root:
        return

    ancestor, immediate_ancestor_level = {}, -1
    stack = Stack([(root, 0)])
    while stack:
        p, level = stack.pop()
        #^#
        ancestor[level] = p

        if p.value in (value1, value2):
            if immediate_ancestor_level == -1:
                immediate_ancestor_level = level - 1
            else:
                return ancestor[immediate_ancestor_level].value

        if immediate_ancestor_level > level - 1:
            immediate_ancestor_level = level - 1
        #$#
        if p.right:
            stack.append((p.right, level+1))
        if p.left:
            stack.append((p.left, level+1))
コード例 #2
0
ファイル: traversal.py プロジェクト: dyno/tree
def postorder_traverse_4(root):
    """postorder_traverse_4

    algorithm:
      improve postorder_traverse_3 based on the fact that if last visited
    node is current node's right child, then current node should be popped up
    """
    stack = Stack([], debug=True)
    node = root
    last_visited = None

    while True:
        # push
        while node:
            stack.append(node)
            node = node.left

        if not stack: break

        # top/pop
        node = stack[-1]
        if not node.right or node.right == last_visited:
            node = stack.pop()
            yield node
            last_visited = node

            # prepare next
            node = None

        else:
            # prepare next
            node = node.right
コード例 #3
0
def postorder_traverse_4(root):
    """postorder_traverse_4

    algorithm:
      improve postorder_traverse_3 based on the fact that if last visited
    node is current node's right child, then current node should be popped up
    """
    stack = Stack([], debug=True)
    node = root
    last_visited = None

    while True:
        # push
        while node:
            stack.append(node)
            node = node.left

        if not stack: break

        # top/pop
        node = stack[-1]
        if not node.right or node.right == last_visited:
            node = stack.pop()
            yield node
            last_visited = node

            # prepare next
            node = None

        else:
            # prepare next
            node = node.right
コード例 #4
0
def find_immediate_common_ancestor_2(root, value1, value2):
    """find_immediate_common_ancestor_2

    algorithm:
      in post-order, the stack holds all the parent node
    when find the first value, the parent list only shrink on the
    road to find the 2nd value.
    """
    p, last_visited, immediate_ancestor = root, None, None
    #stack = Stack([], debug=True)
    stack = Stack([])
    while p or stack:
        while p:
            stack.append(p)
            p = p.left

        p = stack[-1]
        if not p.right or p.right == last_visited:
            stack.pop()
            #^#
            if p.value in (value1, value2):
                if not immediate_ancestor:
                    immediate_ancestor = stack[-1]
                else:
                    return immediate_ancestor.value
            if p == immediate_ancestor:
                if stack:
                    immediate_ancestor = stack[-1]
            #$#
            last_visited = p
            p = None
        else:
            p = p.right
コード例 #5
0
def postorder_traverse_3(root):
    """postorder_traverse_3

    algorithm:
      push/pop node to stack according to current node's state
    """
    ns = [root, VISIT_LEFT]  #(node, state)
    stack = Stack([], debug=True)
    while ns or stack:
        while ns:
            stack.append(ns)
            node, state = ns
            #ns[1] == VISIT_LEFT
            ns[1] = VISIT_RIGHT
            if node.left:
                ns = [node.left, VISIT_LEFT]
            else:
                ns = None

        ns = stack[-1]
        if ns[1] == VISIT_RIGHT:
            ns[1] = VISIT_SELF
            if ns[0].right:
                ns = [ns[0].right, VISIT_LEFT]
            else:
                ns = None
        elif ns[1] == VISIT_SELF:
            yield ns[0]
            stack.pop()
            ns = None
コード例 #6
0
ファイル: graph.py プロジェクト: GeorgeDav9/Graphs
    def dfs(self, starting_vertex, destination_vertex):
        """
        Return a list containing a path from
        starting_vertex to destination_vertex in
        depth-first order.
        """
        #make a stack
        s = Stack()

        #make set to track nodes visited
        visited = set()

        #mark node as visited
        visited.add(starting_vertex)

        while s.size() > 0:
            current_node = s.pop()

            if current_node in visited:
                continue
            visited.append(current_node)
            neighbors = self.get_neighbors(current_node)
            for neighbor in neighbors:
                s.append(neighbor)
            return s
コード例 #7
0
ファイル: traversal.py プロジェクト: dyno/tree
def postorder_traverse_3(root):
    """postorder_traverse_3

    algorithm:
      push/pop node to stack according to current node's state
    """
    ns = [root, VISIT_LEFT] #(node, state)
    stack = Stack([], debug=True)
    while ns or stack:
        while ns:
            stack.append(ns)
            node, state = ns
            #ns[1] == VISIT_LEFT
            ns[1] = VISIT_RIGHT
            if node.left:
                ns = [node.left, VISIT_LEFT]
            else:
                ns = None

        ns = stack[-1]
        if ns[1] == VISIT_RIGHT:
            ns[1] = VISIT_SELF
            if ns[0].right:
                ns = [ns[0].right, VISIT_LEFT]
            else:
                ns = None
        elif ns[1] == VISIT_SELF:
            yield ns[0]
            stack.pop()
            ns = None
コード例 #8
0
ファイル: traversal.py プロジェクト: dyno/tree
def postorder_traverse(root):
    """postorder_traverse

    algorithm:
        postorder (left, right, root) is the reverse of (root, right, left)
    """
    stack = Stack([root], debug=True)
    while stack:
        p = stack.pop()
        yield p
        if p.left: stack.append(p.left)
        if p.right: stack.append(p.right)
コード例 #9
0
ファイル: traversal.py プロジェクト: dyno/tree
def preorder_traverse(root):
    """preorder traversal
    """
    stack = Stack([root], debug=True)
    while stack:
        node = stack.pop()
        yield node

        if node.right:
            stack.append(node.right)
        if node.left:
            stack.append(node.left)
コード例 #10
0
def postorder_traverse(root):
    """postorder_traverse

    algorithm:
        postorder (left, right, root) is the reverse of (root, right, left)
    """
    stack = Stack([root], debug=True)
    while stack:
        p = stack.pop()
        yield p
        if p.left: stack.append(p.left)
        if p.right: stack.append(p.right)
コード例 #11
0
def preorder_traverse(root):
    """preorder traversal
    """
    stack = Stack([root], debug=True)
    while stack:
        node = stack.pop()
        yield node

        if node.right:
            stack.append(node.right)
        if node.left:
            stack.append(node.left)
コード例 #12
0
def find_nodes_with_sum(root, _sum):
    """find 2 nodes that their sum is _sum in a binary search tree.

    algorithm:
      basically 2 pointer for the left and right side of the list and move
    it closer based on the sum of the 2 nodes.
    """

    #stack1 = Stack([], name="ascend ", debug=True)
    stack1 = Stack([], name="ascend ")
    #stack2 = Stack([], name="descend", debug=True)
    stack2 = Stack([], name="descend")

    p1 = p2 = root
    while (p1 or stack1) and (p2 or stack2):
        while p1:
            stack1.append(p1)
            p1 = p1.left

        while p2:
            stack2.append(p2)
            p2 = p2.right

        p1 = stack1[-1]
        p2 = stack2[-1]

        if p1 == p2:  #same node
            stack2.pop()
            p2 = p2.left
            p1 = None
            continue

        if p1.value + p2.value > _sum:
            stack2.pop()
            p2 = p2.left
            p1 = None
        elif p1.value + p2.value < _sum:
            stack1.pop()
            p1 = p1.right
            p2 = None
        else:
            return (p1.value, p2.value)
コード例 #13
0
ファイル: find_nodes_with_sum.py プロジェクト: dyno/tree
def find_nodes_with_sum(root, _sum):
    """find 2 nodes that their sum is _sum in a binary search tree.

    algorithm:
      basically 2 pointer for the left and right side of the list and move
    it closer based on the sum of the 2 nodes.
    """

    #stack1 = Stack([], name="ascend ", debug=True)
    stack1 = Stack([], name="ascend ")
    #stack2 = Stack([], name="descend", debug=True)
    stack2 = Stack([], name="descend")

    p1 = p2 = root
    while (p1 or stack1) and (p2 or stack2):
        while p1:
            stack1.append(p1)
            p1 = p1.left

        while p2:
            stack2.append(p2)
            p2 = p2.right

        p1 = stack1[-1]
        p2 = stack2[-1]

        if p1 == p2: #same node
            stack2.pop()
            p2 = p2.left
            p1 = None
            continue

        if p1.value + p2.value > _sum:
            stack2.pop()
            p2 = p2.left
            p1 = None
        elif p1.value + p2.value < _sum:
            stack1.pop()
            p1 = p1.right
            p2 = None
        else:
            return (p1.value, p2.value)
コード例 #14
0
def find_immediate_common_ancestor(root, value1, value2):
    """find_immediate_common_ancestor

    algorithm:
      in post-order, the stack holds all the ancestor node.
    record the 2 ancestor lists and compare them.
    """
    p = root
    #stack = Stack([], debug=True)
    stack = Stack([])
    last_visited = None
    count_found = 0
    while p or stack:
        while p:
            stack.append(p)
            p = p.left

        p = stack[-1]
        if not p.right or p.right == last_visited:
            stack.pop()
            #^#
            if p.value in (value1, value2):
                count_found += 1
                if count_found == 1:
                    parent_stack1 = stack[:]
                elif count_found == 2:
                    common_idx = -1
                    min_len = len(stack) < len(parent_stack1) and len(stack) or len(parent_stack1)
                    idx = 0
                    while idx < min_len:
                        if stack[idx] == parent_stack1[idx]:
                            common_idx = idx
                            idx += 1
                        else:
                            break
                    return stack[common_idx].value
            #$#
            last_visited = p
            p = None
        else:
            p = p.right
コード例 #15
0
ファイル: traversal.py プロジェクト: dyno/tree
def inorder_traverse(root):
    """inorder traversal
    """
    stack = Stack([], debug=True)
    node = root

    while True:
        # push
        while node:
            stack.append(node)
            node = node.left

        if len(stack) == 0: break

        # pop
        node = stack.pop()

        yield node

        # next
        node = node.right
コード例 #16
0
def inorder_traverse(root):
    """inorder traversal
    """
    stack = Stack([], debug=True)
    node = root

    while True:
        # push
        while node:
            stack.append(node)
            node = node.left

        if len(stack) == 0: break

        # pop
        node = stack.pop()

        yield node

        # next
        node = node.right
コード例 #17
0
def postorder_traverse_2(root):
    """postorder_traverse_2

    algorithm:
      improve postorder_traverse by using 2 stacks and make the output in the rite order.
    """
    stack1, stack2 = Stack([], debug=True), Stack([])
    stack1.append(root)
    while stack1:
        p = stack1.pop()
        stack2.append(p)
        if p.left: stack1.append(p.left)
        if p.right: stack1.append(p.right)

    while stack2:
        p = stack2.pop()
        yield p
コード例 #18
0
ファイル: traversal.py プロジェクト: dyno/tree
def postorder_traverse_2(root):
    """postorder_traverse_2

    algorithm:
      improve postorder_traverse by using 2 stacks and make the output in the rite order.
    """
    stack1, stack2 = Stack([], debug=True), Stack([])
    stack1.append(root)
    while stack1:
        p = stack1.pop()
        stack2.append(p)
        if p.left: stack1.append(p.left)
        if p.right: stack1.append(p.right)

    while stack2:
        p = stack2.pop()
        yield p
コード例 #19
0
def reconstruct_tree_2(preorder, inorder):
    """reconstruct_tree_2

    @param: preorder traversal list
    @param: inorder traversal list
    @return: root node

    algorithm:
      nonrecursive
    """
    cur_pre_idx, pre_pre_idx = 0, -1
    #stack = Stack([], debug = True)
    stack = Stack([])
    while cur_pre_idx < len(preorder) or stack:
        if cur_pre_idx != pre_pre_idx:
            value = preorder[cur_pre_idx]
            #node
            node = Node(None, None, value)
            #split scheme
            idx = inorder.index(value)
            if stack:
                parent_range = stack[-1][1]
                parent_operation = stack[-1][2]
            else:
                parent_range = (0, len(inorder), -1)
                parent_operation = VISIT_LEFT
            if parent_operation == VISIT_LEFT:
                _range = (parent_range[0], idx, parent_range[1])
            else:
                _range = (parent_range[1], idx, parent_range[2])
            #current operation
            operation = VISIT_LEFT

            #push
            stack.append([ node, _range, operation])
            pre_pre_idx = cur_pre_idx

        #check next value and continue build the stack
        if cur_pre_idx < len(preorder) -1:
            next_value = preorder[cur_pre_idx + 1]
            next_in_idx = inorder.index(next_value)
        else:
            next_value = None
            next_in_idx =  -1

        node, _range, operation = stack[-1]
        if operation == VISIT_LEFT and _range[0] <= next_in_idx < _range[1]:
                cur_pre_idx += 1
                continue
        elif operation == VISIT_RIGHT and _range[1] <= next_in_idx < _range[2]:
                cur_pre_idx += 1
                continue

        r = stack.pop()
        if not stack:
            return r[0]

        if stack[-1][2] == VISIT_LEFT:
            stack[-1][0].left = r[0]
            stack[-1][2] = VISIT_RIGHT
        elif stack[-1][2] == VISIT_RIGHT:
            stack[-1][0].right = r[0]
            stack[-1][2] = VISIT_SELF
コード例 #20
0
def reconstruct_tree_2(preorder, inorder):
    """reconstruct_tree_2

    @param: preorder traversal list
    @param: inorder traversal list
    @return: root node

    algorithm:
      nonrecursive
    """
    cur_pre_idx, pre_pre_idx = 0, -1
    #stack = Stack([], debug = True)
    stack = Stack([])
    while cur_pre_idx < len(preorder) or stack:
        if cur_pre_idx != pre_pre_idx:
            value = preorder[cur_pre_idx]
            #node
            node = Node(None, None, value)
            #split scheme
            idx = inorder.index(value)
            if stack:
                parent_range = stack[-1][1]
                parent_operation = stack[-1][2]
            else:
                parent_range = (0, len(inorder), -1)
                parent_operation = VISIT_LEFT
            if parent_operation == VISIT_LEFT:
                _range = (parent_range[0], idx, parent_range[1])
            else:
                _range = (parent_range[1], idx, parent_range[2])
            #current operation
            operation = VISIT_LEFT

            #push
            stack.append([node, _range, operation])
            pre_pre_idx = cur_pre_idx

        #check next value and continue build the stack
        if cur_pre_idx < len(preorder) - 1:
            next_value = preorder[cur_pre_idx + 1]
            next_in_idx = inorder.index(next_value)
        else:
            next_value = None
            next_in_idx = -1

        node, _range, operation = stack[-1]
        if operation == VISIT_LEFT and _range[0] <= next_in_idx < _range[1]:
            cur_pre_idx += 1
            continue
        elif operation == VISIT_RIGHT and _range[1] <= next_in_idx < _range[2]:
            cur_pre_idx += 1
            continue

        r = stack.pop()
        if not stack:
            return r[0]

        if stack[-1][2] == VISIT_LEFT:
            stack[-1][0].left = r[0]
            stack[-1][2] = VISIT_RIGHT
        elif stack[-1][2] == VISIT_RIGHT:
            stack[-1][0].right = r[0]
            stack[-1][2] = VISIT_SELF