【问题标题】:searching a binary tree搜索二叉树
【发布时间】:2009-07-11 03:37:59
【问题描述】:

我正在编写一个迭代函数来搜索二叉树的某个值。在我了解如何泛化类之前,这已本地化为带符号的整数。

假设我的类是 BinarySearchTree,它有一个指向树根节点的指针。还假设节点是通过插入函数插入的,并且具有指向两个子节点的指针。这是 Node 结构的一个非常简略的版本:

struct Node
{
   public:
      Node *left_, *right_;
      int value_

      Node(int val) : value_(val), left_(0), right_(0) { }
      //done in this manner to always make sure blank children are
      //init to zero, or null
      Node(int val, Node *left, Node *right) : value_(val), left_(0), right_(0) 
          { left_ = left; right_ = right; } 
}

因此,您可以放心地假设节点的 uninit 指针将为 NULL。

这是我的代码:

int BinarySearchTree::search(int val)
{
    Node* next = this->root();

    while (next->left() != 0 || next->right () != 0)
    {
        if (val == next->value())
        {
            return next->value();
        }    
        else if (val < next->value())
        {
            next = next->left();   
        }
        else if (val > next->value())
        {
            next = next->right();
        }
    } 

    //not found
    return 0;
}

此代码被朋友拒绝有两个原因:

1) 如果 next 没有子节点,则两者的计算结果都为零,我将提前退出循环(我永远不会检查搜索到的 val 与 next 的值)。

2) 如果 next 有一个子节点,但您要搜索的数据应该在树的空边,next 将被设置为 0,它会再次循环,将 next(即 0)与像while(0-&gt;left()) 这样的左右树,导致未定义的行为。

有人告诉我,这两个问题的解决方案都在于循环条件,但我看不出我能做些什么来轻松解决这种情况。 Stack Overflow 社区能否提供任何见解?

【问题讨论】:

  • 我讨厌添加作业标签。这不是作业,我不在学校,这是一种爱好。
  • @Hooked:我刚刚添加了算法标签。另外,我意识到我刚刚发布了几乎相同的代码,但请阅读我的帖子...考虑返回 bool 而不是 int。
  • @Hooked:无意冒犯。我只是误解了“代码被拒绝”。既然你拒绝的朋友没有给你一个理由,我认为这是因为这是家庭作业——在这种情况下,放弃答案是不好的形式。
  • @Hooked:你明白我为什么建议你将返回值更改为 bool 吗?当你搜索 0 时会发生什么?你怎么知道是否找到了 0,或者什么也没找到?您将编写类似“if (tree.Search(0) == 0)”的代码,但这是错误的。即使 "if (tree.Search(1) == 1)" 可以工作,它也很尴尬。您希望能够编写“if (tree.Search(0))”... 这有意义吗?
  • @tvanfosson:没关系,但是作业有你不愿意做自己的工作的内涵。我这样做只是因为它很有趣。我现在进入了一个论坛帖子的第 22 页(20 个帖子/页),有两个共同的朋友(和程序员)教我如何编程。

标签: algorithm binary-tree treenode tree-search


【解决方案1】:

我认为您应该像这样测试循环中的 next 是否不为 NULL:

int BinarySearchTree::search(int val)
{
    Node* next = this->root();

    while (next)
    {
        if (val == next->value())
        {
            return next->value();
        }    
        else if (val < next->value())
        {
            next = next->left();   
        }
        else if (val > next->value())
        {
            next = next->right();
        }
    } 

    //not found
    return 0;
}

【讨论】:

  • 不,我为什么要那个?如果它的计算结果为 null,那么我应该因为之前没有找到该值而返回。
  • 它确实返回了。循环中断并返回 0;
  • 在您的示例中,while (next) 只有在 next 为 NULL 时才会评估为 true,因为 C++ 中的 NULL == 0。因此,我认为您的示例与所需要的完全相反。
  • 不,如果 next 不为空,则计算结果为 true。 NULL 为假(即 0)。
  • 哈...我刚刚写了相同的答案(几乎)...我不知道我怎么没看到你写了这个。对 OP 来说有一件事......由于我在帖子中提到的原因,他可能应该返回 bool。
【解决方案2】:

试试这个:

while (next != NULL)?

【讨论】:

    【解决方案3】:

    首先,我不确定你为什么要返回一个 int。如果您在树中搜索 0 怎么办。你可能想要这样的东西:

    bool BinarySearchTree::Search(int val) {
      Node* current = root();
      while (current != NULL) {
        // Check if it's here
        if (val == current->value()) {
          return true;
        }
        if (val < current->value()) {
          current = current->left();
        } else {
          current = current->right();
        }
      }
      // Not found
      return false;
    }
    

    注意循环不变量:在每个循环开始时,您处于一个需要“处理”的非空节点。首先检查它是否是您想要的节点。如果不是,则创建一个分支,并让循环决定分支是否“好”(即 - 非空)。然后,您将让下一个循环迭代负责测试。

    【讨论】:

    • 这个网站上有多少个“Tom”?另一个汤姆想通了。呵呵。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2010-10-26
    相关资源
    最近更新 更多