如何递归遍历二叉树?

时间:2017-08-31 14:46:42

标签: python algorithm tree binary-tree

对于我无法解决的测验,我有以下问题:

给定一个树代表(5, (3, (20, (6, None, None), None), None), (10, (1, None, None), (15, (30, None, (9, None, None)), (8, None, None)))),其中第一个项目是节点,第二个项目是左分支树,第三个项目是右分支树,找到最大的锯齿形(改变方向的选项)树)。

所以这棵树从5开始,向左移动到3或从右移到10,从3开始向左移动到20(它不能向右移动,右边是None)。从10步行,它可以左转到1,或者右转到15等等。

我失败了,因为我甚至在递归走树时遇到了问题。我无法确定如何选择向左或向右走,当在树上走第二,第三等时间时,怎么知道它之前走过那条路?

我在这里

 class Tree(object):

     def __init__(self, zigzags, node, left, right):
         self.zigzags = zigzags
         self.node = node
         self.left = left
         self.right = right

TREE = (5, (3, (20, (6, None, None), None), None), (10, (1, None, None), (15, (30, None, (9, None, None)), (8, None, None))))



def walk_tree(tree, current_direction='l', zigzag_count=0, this_path=''):
    left = tree[1]
    right = tree[2]

    print('left:')
    print(left)

    print('right:')
    print(right)

    print('zigzag_count:')
    print(zigzag_count)

    possible_left_path = this_path + 'l'  # say like 'lrl'
    possible_right_path = this_path + 'r' # say like 'lrr'

    if left:
        if current_direction == 'r':
            zigzag_count += 1
        return walk_tree(left, 'l', zigzag_count)

    elif right:
        if current_direction == 'l':
            zigzag_count += 1
        return walk_tree(right, 'r', zigzag_count)

    else:
        return zigzag_count

count = walk_tree(TREE)
print(count)

我认为走在左侧然后停了下来:

$ ./exam_question_2.py 
left:
(3, (20, (6, None, None), None), None)
right:
(10, (1, None, None), (15, (30, None, (9, None, None)), (8, None, None)))
zigzag_count:
0
left:
(20, (6, None, None), None)
right:
None
zigzag_count:
0
left:
(6, None, None)
right:
None
zigzag_count:
0
left:
None
right:
None
zigzag_count:
0
0

预期答案是2,向右,向右,向左,向右走。

我想尝试解决之字形只是为了学习,但我想知道如何以这种格式递归地遍历这个二叉树,并知道我何时改变行走(当我再次从顶部开始)时,如果可能的话,背后有一些理论。我更喜欢Python或JavaScript中的一个例子。

2 个答案:

答案 0 :(得分:4)

这是一个典型的分而治之的问题。给定一个带子节点的节点,该节点的之字形得分是具有最高之字形得分的子节点(如果达到该子节点需要更改方向,则添加1):

2013-05-14

当左侧节点可用时,您的代码从未被视为正确的路径。

这会产生您的预期路径:

def zigzagscore(node):
    left, right = node[1:]

    left_zigzag, left_path = 0, ''
    if left is not None:
        left_zigzag, left_path = zigzagscore(left)
        if left_path.startswith('r'):
            # We zigged for left
            left_zigzag += 1
        left_path = 'l' + left_path

    right_zigzag, right_path = 0, ''
    if right is not None:
        right_zigzag, right_path = zigzagscore(right)
        if right_path.startswith('l'):
            # We zagged for right
            right_zigzag += 1
        right_path = 'r' + right_path

    if left_zigzag > right_zigzag:
        return left_zigzag, left_path
    else:
        return right_zigzag, right_path

答案 1 :(得分:1)

采用递归方法,您可以声明以下规则:

当前节点的最长曲折,如果从左边到达,则是最长的左曲折和最长的右曲折加1之间的最长曲折;相反,如果从右边到达。

根节点的规则不同,因为不能从任何一方到达。

def Length(Node, FromLeft):
  if Node == None:
    return 0
  return max(Length(Node.Left, True) + (1 if not FromLeft else 0), Length(Node.Left, False) + (1 if FromLeft else 0))

print max(Length(Root.Left, True), Length(Root.Right, False))

我没有使用之字形,但当然这是可行的。