英文:
Can i use yield to get the result of all the result in nested function?
问题
我找到了很多验证有效二叉树的代码,但我尝试创建一个简单的版本,但它总是返回True!
抱歉,我不太理解递归。
英文:
I found many code to verify a valid binary tree, but I tried to creat a simple one, however it rise true all the time!
Sorry I don't understand the recursion very well.
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def is_BST():
if root:
return all(is_BST1(root))
def is_BST1(curnode):
if curnode.right:
if curnode.right.val>curnode.val:
is_BST1(curnode.right)
else:
yield False
if curnode.left:
if curnode.left.val<curnode.val:
is_BST1(curnode.left)
else:
yield False
else:
yield True
#tree creation code
print(is_BST)
答案1
得分: 2
你的代码存在几个问题:
-
递归调用的结果被忽略了。由于你将
is_BST1
创建为一个生成器,你应该使用yield from
进行递归调用,像这样:yield from is_BST1(curnode.right)
-
即使有了上面的修复,你仍然会得到错误的结果。例如,对于这个树:
2 / 1 \ 3
你的代码总是会返回 True,但它未能发现值为 3 的节点违反了BST属性,因为它大于 2。
-
并非真正的问题,但是你的代码在发现了BST属性的违规后仍然继续查找。这没有任何好处。一旦发现违规,算法就不应该继续调查任何其他节点,并返回
False
。 -
如果将树的根传递给
is_BST
函数,会更有用,这样调用者可以指定要验证哪棵树。
要正确验证BST,你需要做的不仅仅是比较父节点的值与直接子节点的值。有几种可能的方法,包括以下两种:
-
你可以创建一个生成器,按中序序列生成树的值,然后验证生成的值是否按非递减顺序生成。
-
你可以向每个递归调用传递一个“窗口”,该窗口为访问的子树中的所有值定义了下限和上限,随着在树中的深入,此窗口变得更窄。
两种方法都可以。由于你使用了生成器的思想(使用 yield
),我将为第一种方法提供代码:
from itertools import tee
def is_BST(root):
current, lead = tee(inorder(root))
next(lead, None)
return all(a <= b for a, b in zip(current, lead))
def inorder(curnode):
if curnode:
yield from inorder(curnode.left)
yield curnode.val
yield from inorder(curnode.right)
英文:
There are several issues in your code:
-
The results from the recursive calls are ignored. As you have created
is_BST1
as a generator, you would do the recursive call withyield from
, like so:yield from is_BST1(curnode.right)
-
Even with the above fix, you will get false positives. For instance for this tree:
2 / 1 \ 3
Your code will always yield True, but it fails to see that node with value 3 is violating the BST property as it is greater than 2.
-
Not a real problem, but your code keeps looking further even when it has found a violation of the BST property. This brings no benefit. Once you have a violation, the algorithm should not investigate any other nodes and quit with
False
-
It would be more useful if you would pass the root of the tree to the
is_BST
function, so the caller can indicate which tree to validate.
To validate a BST properly, you need to do more than just compare a parent value with the value of a direct child. There are several approaches possible, including these two:
-
You could create a generator that produces the tree values in in-order sequence, and then verify that the produced values are yielded in non-decreasing order
-
You could pass down a "window" to each recursive call which defines a lower and upper bound for all values in the visited subtree, as you go deeper in the tree this window becomes more narrow.
Either will work. Since you were working with the idea of a generator (using yield
) I will provide the code for the first idea:
from itertools import tee
def is_BST(root):
current, lead = tee(inorder(root))
next(lead, None)
return all(a <= b for a, b in zip(current, lead))
def inorder(curnode):
if curnode:
yield from inorder(curnode.left)
yield curnode.val
yield from inorder(curnode.right)
答案2
得分: -1
你主要的问题是这一行:
is_BST1(curnode.right)
只返回一个生成器,但并没有对其进行任何操作。你至少应该对该生成器进行迭代:
...
if curnode.right:
if curnode.right.val > curnode.val:
# 对从右节点构建的生成器进行迭代
for i in is_BST1(curnode.right):
yield i
else:
...
当然,对左子节点也要做同样的操作...
英文:
Your main problem is that this line:
is_BST1(curnode.right)
only returns a generator, but does nothing with it. You should at least iterate on that generator:
...
if curnode.right:
if curnode.right.val>curnode.val:
# iterate on the generator built from right node
for i in is_BST1(curnode.right):
yield i
else:
...
and of course do the same for the left child...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论