【问题标题】:Testing members of a Binary Tree测试二叉树的成员
【发布时间】:2012-10-08 10:20:18
【问题描述】:

我目前正在尝试遍历二叉树以检查某些值是否在其中。 一个 for 循环正在测试从 1 到 50 的所有值,并且将为每个匹配的值返回 true。

这是当前树:

              8
            /    \
           4      38
          / \    /  \
         3  7   31  39
        /      / \   \
       1     16  33  45

IntegerData test(0);
for (int i = 0; i < 50; i++) {
  test.value = i;
  if (bt->member(&test)) {
   cout << "member true for " << i << endl;
  }
}

现在我必须实现成员函数并且我有正确的想法,但是它在检查根、根->左和根->右后停止。我觉得好像我使用了正确的递归形式,但我想不是。这是我的代码:

bool BinaryTreeNode::member(Data * data) {
BinaryTreeNode *newNode = new BinaryTreeNode(data);
   if (data->compareTo(this->nodeData) == 0) {
       return true;
   }
   else if (data->compareTo(this->left->nodeData) == 0) {
       return true;
       newNode->member(data);
   }
   else if (data->compareTo(this->right->nodeData) == 0) {
       return true;
       newNode->member(data);
   }
   return false;
}

前面所说的for循环打印出来

member true for 8
member true for 4
member true for 38

但没有别的。

有人会通过伪代码或脚本提供一些指导吗?你不必给我代码,因为我想自己解决这个问题。谢谢。

【问题讨论】:

  • 这是否总是像您的示例中那样是有序的 BST?
  • 好,那我就不用修改答案了!

标签: recursion binary-tree member


【解决方案1】:

假设这是一个有序的 BST:

bfs(root) {
    if (root is null) 
        return false // if we get to leaves without finding the target, it's not there
    if (root is target value)
        return true // if we found it, then YAY
    if (root is less than target value)
        return bfs(right child) // if target > root, target must lie in right subtree
    return bfs(left child) // otherwise target < root, check left subtree

您只想检查 root 处的值是否为目标值。如果你检查孩子,你会检查他们中的一些人两次(一次是孩子,一次是根)。它还使代码更加复杂,这可能是导致您的逻辑错误的原因。


编辑:刚刚找到this算法的解释。

编辑:我还想强调你犯的一个小错误,我见过很多人都这样做 - 调用一个返回一些东西但没有对返回值做任何事情的函数。

我所说的行是newNode-&gt;member(data); 行。在那里你调用了递归的下一步,但你还没有使用结果。这意味着一旦您的程序在树中找到较低的目标,它就不会回溯。要在递归函数中使用返回值,您必须拥有 return next_call()(在本例中为 return newNode-&gt;member(data);)。

【讨论】:

  • 这很聪明。我没有考虑顺序
  • 根据您上次的编辑,他必须找到一种方法将newNode 设置为正确的方向,然后才能返回next_call()。通过设置控制流的方式,代码最终可能看起来像if (newNode = newNode-&gt;right &amp;&amp; newNode-&gt;member(data))。假设是第一个方面应始终评估为某种true 形式。如果那部分代码有问题,就很难调试了
  • 我不完全确定你在说什么。提问者在返回下一个调用之前绝对应该将 newNode 设置为正确的方向,以避免搜索树的冗余部分。此外,'newNode=newNode->right' 在 BST 中永远不应该为真(节点不应该是它们自己的子节点)。我也不知道你说的“方面”是什么意思。那是 Ruby 的东西吗?
  • 我已经找到答案了。事实证明我的成员代码工作正常,但我的插入代码有问题。我会把注意力转向那个。谢谢你们俩花时间帮助我。我很感激。
  • 确实如此。我进行了必要的更改以使其正常运行
【解决方案2】:

这是一个树遍历算法的不稳定实现。但是,如果您想保留现有的内容,请考虑将 return 语句的位置与它下面的语句交换。

不过,这就是我重构代码的方式

bool member(BinaryTreeNode *node, Data *data) {
   // Create wrapper for data
   BinaryTreeNode *newNode = new BinaryTreeNode(data);

   if (data->compareTo(node->nodeData) == 0) { // Check the current node only!
       return true;
   else  // delegate the rest of the tree to recursion.
       if (member(node->left,  data)) // Check the left
       || (member(this->right, data)) // Check the right
           return true;
       else
         return false;
}

再一次,你应该测试一下,让我知道它是否有效。我来自 Ruby,有一段时间没有用 C++ 编程了。

哦,当你想在你的驱动程序代码中调用它时,将二叉树的根节点作为第一个节点传递。如果这是一个类或模块函数,请尝试传递self。我希望self 指向root 节点

【讨论】:

  • 你的意思是:newNode->member(data);返回真; ?我只是尝试过,它没有改变任何东西。还有其他想法吗?
  • 您可能遇到了一些奇怪的行为,因为如果找不到元素,则没有明确调用返回 false。我修好了。
  • 我试图以一种与我当前代码相关的方式来实现它,但它对我不起作用。不过感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-01
相关资源
最近更新 更多