简体   繁体   English

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

[英]Understanding Logic of Inorder traversal of BST, Python

I'm studying for coding interviews and working with a lot of different data structures. 我正在研究采访编码并使用许多不同的数据结构。

I'm relatively new to Tree problems and have been doing problems daily to practice. 我对Tree问题相对较新,并且每天都在练习问题。

It's one thing to have formulas committed to memory, and another to truly understand them. 将公式提交给内存是一回事,而要真正理解它们则是另一回事。 When I understand something it is easy to apply that understanding to more difficult problems. 当我理解某些东西时,很容易将这种理解应用于更困难的问题。

Recursive solutions are a little harder for me to mentally visualize and while intuitively they make sense, I am trying to get a deep understanding of what's happening on the Stack. 递归解决方案对我来说很难在视觉上实现可视化,尽管直观上它们是有意义的,但我试图深入了解堆栈上正在发生的事情。

I have a tree and want to do in order traversal. 我有一棵树,想按顺序遍历。 No problem. 没问题。

在此处输入图片说明

data = [] 

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

I created the data variable to print out what is being stored on each pass through the method. 我创建了数据变量以打印出每次通过该方法存储的内容。

It printed 它印了

[]
[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]

I am trying to logically look at what is happening and want to know if my Logic is correct. 我试图从逻辑上看正在发生的事情,并想知道我的逻辑是否正确。

There are 15 printed results and 7 Nodes. 有15个打印结果和7个节点。 However we get to 15 because there are 8 places checked for Nodes where Node is None . 但是我们到达15,因为有8个地方检查Node,其中Node为None That happens on Nodes 1, 3, 5, 7. 这发生在节点1、3、5、7上。

We are checking the left half of the tree before the right. 我们正在检查树的左半部分,然后再右半部分。

[] 
#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]

The right side will be checked just like the left so I didn't write my logic as it'd be redundant. 右侧将像左侧一样进行检查,因此我没有写逻辑,因为它很多余。

I just want clarification if I am looking at this problem in the correct format. 我只是想澄清一下我是否以正确的格式查看此问题。

Thanks for any help in understanding this! 感谢您对理解此问题的任何帮助!

The comments in the output are not always correct. 输出中的注释并不总是正确的。

The first output ( [] ) happens when a function call reaches the end. 当函数调用到达末尾时,将出现第一个输出( [] )。 The first call where this happens is when root is node 1 and from there the first recursive call is made. 发生此情况的第一个调用是在root是节点1的情况下,从那里进行第一个递归调用。 That call will have None as argument, and so it is the first time a call reaches the print statement. 该调用将None参数作为参数,因此这是调用首次到达print语句。

So we have these ongoing calls: 因此,我们正在进行以下通话:

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

When that deepest call finishes, the function with node 1 will append 1 to the data list, and then make the recursive call for the right child, which also is None and [1] is printed. 当最深层调用结束时,带有节点1的函数将在数据列表后追加1,然后对正确的子对象进行递归调用,该子对象也为None并显示[1]

Here is a visualisation of the process. 这是过程的可视化。 The columns represent the depth of the recursion, and the rows represent the sequence of events as time progresses (downwards). 列代表递归的深度,行代表随着时间的推移(向下)事件的顺序。 The last column is reserved for showing what the current value of data is. 最后一列保留用于显示当前data值是什么。 When it has a yellow background it means it is printed. 背景为黄色时表示已打印。

Light blue means that code is executed at that recursion depth. 浅蓝色表示在该递归深度执行代码。 Darker blue means the corresponding function call is pending (on the stack), waiting for the nested recursive call to return. 深蓝色表示相应的函数调用正在挂起(在堆栈上),正在等待嵌套的递归调用返回。

在此处输入图片说明

From this image you can also see why the same output is sometimes repeated: it is printed at different recursion levels as the algorithm is backtracking. 从该图像中,您还可以看到为什么有时会重复相同的输出:随着算法的回溯,它以不同的递归级别打印。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM