理解BST的顺序遍历逻辑,Python

时间:2017-10-28 18:18:16

标签: python algorithm tree

我正在学习编码访谈和使用大量不同的数据结构。

我对树问题比较陌生,每天都在做练习。

让公式致力于记忆是一回事,而另一个是真正理解它们。当我理解某些东西时,很容易将这种理解应用于更困难的问题。

递归解决方案对我来说有点难以进行心理可视化,而直觉上它们是有意义的,我试图深入了解堆栈上发生的事情。

我有一棵树,想按顺序进行遍历。没问题。

enter image description here

data = [] 

def checkBST(root):
    if root:
        checkBST(root.left)
        data.append(root.data)
        checkBST(root.right)
    print(data)   

我创建了数据变量来打印出通过该方法每次传递时存储的内容。

打印

[]
[1]
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]

我正在尝试从逻辑上看看发生了什么,并想知道我的逻辑是否正确。

共有15个打印结果和7个节点。但是我们得到15,因为有8个位置检查Node是None的节点。这发生在节点1,3,5,7上。

我们正在检查右边的树的左半部分。

[] 
#nothing stored because we move onto Node 2 as we don't hit the base case.
[1] 
#1 stored because Node 1 doesn't have a left value. So we move onto the append call. 
[1] 
#1 returned because Node 1 doesn't have a right value.
[1, 2] 
#2 stored because because we finished checking the left side and moved onto append data.
[1, 2, 3] 
#3 is stored because we are calling the in order traversal on the right side of two now. 
[1, 2, 3]
#3 is returned again because it doesn't have a root.left
[1, 2, 3]
#3 is returned again because it doesn't have a root.right
[1, 2, 3, 4]
# we hit the append method for 4, now we move onto the in order traversal on the right
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]

右侧将像左侧一样被检查,所以我没有写出我的逻辑,因为它是多余的。

如果我以正确的格式查看此问题,我只想澄清一下。

感谢您对此有任何帮助!

1 个答案:

答案 0 :(得分:3)

输出中的注释并不总是正确的。

当函数调用到达结束时,会发生第一个输出([])。发生这种情况的第一个调用是root是节点1并且从那里进行第一次递归调用。该调用将以None作为参数,因此这是第一次调用到达print语句。

所以我们有这些正在进行的电话:

 checkBST(4)
     checkBST(2) # left child of 4
         checkBST(1) # left child of 2
             checkBST(None) # left child of 1
                 print # --> []

当最深的调用结束时,具有节点1的函数将1附加到数据列表,然后对正确的子项进行递归调用,同时打印None[1]

以下是该过程的可视化。列表示递归的深度,行表示随时间推移(向下)的事件序列。最后一列保留用于显示data的当前值。当它具有黄色背景时,表示它已被打印。

淡蓝色表示代码在该递归深度处执行。深蓝色表示相应的函数调用挂起(在堆栈上),等待嵌套的递归调用返回。

enter image description here

从这张图片中你还可以看到为什么有时会重复相同的输出:当算法回溯时,它会以不同的递归级别打印。