【问题标题】:Binary tree recursive problem二叉树递归问题
【发布时间】:2011-07-24 16:26:20
【问题描述】:

我发现了这个问题,我不太确定我的方法是否正确:

"二叉树可以使用编码 两个函数 l 和 r 使得对于 a 节点 n,l(n) 给出左子节点 n(如果没有,则为 nil)和 r(n) 给出正确的孩子(如果有,则为 nil 是无)。让 Test(l,r,x) 是一个简单的 递归算法 由 l 和 r 编码的二叉树 与根节点一起工作 x 表示二叉树,并返回 “是”,如果树中没有节点 正好一个孩子。给出伪代码 对于这个算法。”

我试过这个:

test(l,r,x)
  if((l(x)!=null && r(x)!=null) || (l(x)==null && r(x)==null)) 
     return "yes"
   else return "no"

  if(test(l,r,l(x))=="yes") test (l,r,l(x)) else return "no"
  if(test(l,r,r(x))=="yes") test (l,r,r(x)) else return "no"

 return "yes"

正确吗?如果 l 和 r 是函数,为什么在调用函数时它们作为普通参数传递?

提前感谢您的回答!

【问题讨论】:

  • 是什么让您认为函数不能被视为“普通参数”?那有什么问题?你的问题似乎暗示了类似的东西。
  • @AndreyT 取决于 OP 的背景,他可能不知道某些语言允许该功能。
  • 无论如何,据我估计,他似乎真正理解了它们像普通参数一样被很好地传递的概念。

标签: algorithm recursion binary-tree pseudocode


【解决方案1】:

您要做的第一件事是返回是或否,因此最后一部分是无法访问的。

我会更改它,如果您有一个孩子,则返回“否”,否则返回“是”或“否”,具体取决于您的孩子是否符合条件。

test(l,r,x)
  if((l(x)!=null && r(x)==null) || (l(x)==null && r(x)!=null)) 
     return "no"
  if(l(x) == null && r(x) == null) 
    return "yes"
  return test(l,r,l(x)) && test(l,r,r(x))

【讨论】:

  • 好的,但是返回的“是”在哪里?
  • @EOS 好点。仅在到达叶节点时才返回 yes(left 和 right 都为 null。)Fixed. 这个想法是您只知道您的节点。您知道您的节点是否失败,因此您可以返回 no 并让它向上传播。您知道您是否没有孩子,因此您可以返回“是”并让它传播。否则,您必须低头才能看到发生了什么。
  • 一提:与大多数编程语言匹配,而不是 "no" ,返回 0。因此,该程序作为一个想法和一个可能的实现都保持其有效性。
【解决方案2】:

我不认为这是正确的。我看到的问题在第一步:

if((l(x)!=null && r(x)!=null) || (l(x)==null && r(x)==null)) 
    return "yes"
else return "no"

问题是您无法在第一步确定整个树的“是”。你要做的就是把它分解成组件:

if this node has both children
    return the result of test(l,r,l(x)) && (test(l,r,r(x))
if this node has no children
    return true
if this node has 1 child
    return false

根据您的最后一个问题(“如果 l 和 r 是函数,为什么在调用函数时将它们作为普通参数传递?”),答案是它们没有必须作为参数传递。这正是他们在说“可以使用两个函数 l 和 r [...] 编码二叉树”时选择的符号

【讨论】:

  • 您在解决方案中使用了布尔变量,因此它在第一次测试中运行良好。但是使用 "yes" ,我还必须在第一次返回时对其进行测试,对吧?
  • @EOS 我使用布尔值是因为该函数必须能够进行布尔代数:它必须将其子项的返回合并为一个结果。布尔值使这更容易。
【解决方案3】:

你有三个基本条件:两个孩子都为空,一个孩子为空,或者两个孩子都不为空。我也会按这个顺序测试它们(因为它简化了一点逻辑):

if l(x) == null && r(x) == null
    return true;
if l(x) == null || r(x) == null  // only need inclusive OR, due to previous test.
    return false;
return test(l, r, l(x)) && test(l, r, r(x))

至于将l 和r 作为参数传递,这完全取决于:某些语言(例如,函数式语言)允许您将函数作为参数传递。其他人(例如,C、C++ 等)让你传递一个指向函数的指针——但这几乎无关紧要。有些人不会让你传递函数之类的东西,在这种情况下,你必须硬连线它。在这种情况下,通过传递l 和 r 并没有真正获得太多(什么?)反正参数。将函数作为参数传递主要在/如果接收函数不知道它将先验地接收什么函数(它在这里)时很有用。

【讨论】:

  • 我个人不同意“简化”逻辑意味着它的语句更少的想法。每当您的逻辑是隐式而不是显式时,都会降低可读性(由于需要增加程序员的思维)并增加出现错误的机会。
  • 不是它的语句更少(它没有),而是每个语句本身都更容易理解。如果您坚持以另一种方式进行,我认为最好明确使用 XOR:if (l(x) == null XOR r(x) == null) 而不是相当复杂的if (l(x) == null && r(x) != null || l(x) != null && r(x) == null)。 IMO,后者(本身)比我编写的整个函数更难阅读或理解。
猜你喜欢
  • 2012-08-04
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 2016-04-19
  • 2014-03-29
  • 2020-05-21
  • 2017-04-09
  • 1970-01-01
相关资源
最近更新 更多