返回或不返回递归函数

时间:2018-06-03 20:27:04

标签: python recursion search return binary-search-tree

在询问之前,我搜索了一些旧问题并且更好地将“返回”放在内部重新调用函数以获得预期结果。 其中一些人喜欢: How to stop python recursion Python recursion and return statements。但是当我对我的问题做同样的事情时,它会变得更糟。

我有一个二进制搜索树,并希望通过给定一个节点的键来获取TreeNode实例,因此它看起来更容易遍历,我已经很容易实现下面的类似函数,我没有把它放在函数前面:

def getNode(treeNode,key):
    if(treeNode):
        if(treeNode.key==key):
            print("got it=",treeNode.key)
            return treeNode
        else:
            return getNode(treeNode.left_child(),key)    
            return getNode(treeNode.right_child(),key)   

所以对于我的新要求,我首先将其组成如下:

{{1}}

然后问题出现了,它找到了键/节点但是一直运行并最终报告一个None错误,然后我把返回放在左右两个分支的前面,如下所示:

{{1}}

但是这会让事情变得更糟,它确实达到了找到的密钥并且更早地返回。

然后我尝试删除分支的一个“返回”,无论是右还是左。它工作(更新:当我的测试用例只包含3个节点,当我放置更多节点,它没有工作,或者说预期节点是否来自右边,然后在右分支调用工作前面返回时,这有用)对于左边一个,它没有)。什么是更好的解决方案?

3 个答案:

答案 0 :(得分:1)

您需要return递归通话的结果,但您并不总是无条件地这样做。有时你不会从第一次递归中得到你需要的结果,所以你需要在返回任何东西之前递归另一个。

处理此问题的最佳方法通常是将递归的结果分配给变量,然后可以对其进行测试。因此,如果getNode返回一个节点(如果找到了密钥),或None(如果它没有),则可以执行以下操作:

result = getNode(treeNode.left_child(),key)    
if result is not None:
    return result
return getNode(treeNode.right_child(),key)

在这种特定情况下,由于None是假的,您可以使用or运算符执行"短路"为你:

return getNode(treeNode.left_child(),key) or getNode(treeNode.right_child(),key)

只有在第一个返回假名值(例如None)时才会进行第二次递归调用。

请注意,对于某些递归算法,您可能需要无条件地多次递归,然后在返回结果之前将结果组合在一起。例如,在树中添加(数字)键值的函数可能如下所示:

def sum_keys(node):
    if node is None:  # base case
        return 0
    left_sum = sumKeys(node.left_child())   # first recursion
    right_sum = sumKeys(node.right_child()) # second recursion
    return left_sum + right_sum + node.key  # add recursive results to our key and return

答案 1 :(得分:0)

而不是(defn map-invert+ [kfn vfn data] (reduce (fn [acc entry] (assoc acc (kfn entry) (vfn entry))) {} data)) user> (def data {1 ["bar" "choco"] 2 ["some" "thing"]}) #'user/data user> (def inverted (map-invert+ (comp first val) key data)) #'user/inverted user> inverted ;;=> {"bar" 1, "some" 2} user> (inverted "bar") ;;=> 1 ,请使用return

yield

输出:

class Tree:
   def __init__(self, **kwargs):
      self.__dict__ = {i:kwargs.get(i) for i in ['left', 'key', 'right']}

t = Tree(key=10, right=Tree(key=20, left=Tree(key=18)), left=Tree(key=5))
def find_val(tree, target):
  if tree.key == target:
    yield target
    print('found')
  else:
    if getattr(tree, 'left', None) is not None:
      yield from find_val(tree.left, target)
    if getattr(tree, 'right', None) is not None:
      yield from find_val(tree.right, target)

print(list(find_val(t, 18)))

但是,您也可以通过实现found [18] 方法将get_node函数实现为二叉树类中的方法:

__contains__

输出:

class Tree:
   def __init__(self, **kwargs):
     self.__dict__ = {i:kwargs.get(i) for i in ['left', 'key', 'right']} 
   def __contains__(self, _val):
     if self.key == _val:
        return True
     _l, _r = self.left, self.right
     return _val in [[], _l][bool(_l)] or _val in [[], _r][bool(_r)]

t = Tree(key=10, right=Tree(key=20, left=Tree(key=18)), left=Tree(key=5))
print({i:i in t for i in [10, 14, 18]})

答案 2 :(得分:0)

不了解您的对象:

三个基本案例:

  • 当前节点为None - >返回无
  • 当前节点与密钥匹配 - >回来吧
  • 当前节点不匹配,是分支的结尾 - >返回无

如果不是基础案例递归。使用or短接递归:如果匹配则返回左分支或返回正确的分支结果(也可能是None)

def getNode(treeNode,key):
    if treeNode == None:
        return None
    elif treeNode.key == key:
        print("got it=",treeNode.key)
        return treeNode
    elif not any(treeNode.has_left_child(), treeNode.has_right_child()):
        return None
    #left_branch = getNode(treeNode.left_child(),key)    
    #right_branch = getNode(treeNode.right_child(),key)
    #return left_branch or right_branch
    return getNode(treeNode.left_child(),key) or getNode(treeNode.right_child(),key)