【问题标题】:How to recursively print out all the nodes in a binary search tree using stringstream C++如何使用stringstream C++递归打印出二叉搜索树中的所有节点
【发布时间】:2016-09-15 18:45:35
【问题描述】:

我想通过使用字符串流和递归来打印我的二叉搜索树中所有节点的内容。问题是当我使用这段代码时,只显示根目录的内容。我知道原因是每次我递归调用函数 InOrder(BSTNode* bst_node) 时,都会再次创建我的 stringstream 变量。我可以对我的代码做些什么来解决这个问题,同时仍然使用字符串流进行输出?

这是我的代码:

string BSTree::InOrder(BSTNode* bst_node) {
  stringstream ss;
  if (root_ ==  NULL) {
    return "";
  } else {
    if (bst_node->GetLeftChild() != NULL) {
      InOrder(bst_node->GetLeftChild());
    }
    ss << bst_node->GetContents() << " ";
    if (bst_node->GetRightChild() != NULL) {
      InOrder(bst_node->GetRightChild());
    }
  }
  return ss.str();
}

【问题讨论】:

    标签: c++ recursion binary-search-tree inorder


    【解决方案1】:

    可能是这样的吗?

    string BSTree::InOrder(BSTNode* bst_node)
    {
      if (!bst_node)
        return "";
      ostringstream ss;
      ss << InOrder(bst_node->GetLeftChild());
      ss << bst_node->GetContents() << " ";
      ss << InOrder(bst_node->GetRightChild());
      return ss.str();
    }
    

    或者,您可以传递相同的字符串流实例:

    void BSTree::InOrderImpl(BSTNode* bst_node, ostringstream &ss)
    {
      if (bst_node)
      {
        InOrderImpl(bst_node->GetLeftChild(), ss);
        ss << bst_node->GetContents() << " ";
        InOrderImpl(bst_node->GetRightChild(), ss);
      }
    }
    
    string BSTree::InOrder(BSTNode* bst_node)
    {
      ostringstream ss;
      InOrder(bst_node, ss);
      return ss.str();
    }
    

    【讨论】:

    • 这不起作用。不幸的是,代码给了我一个分段错误。
    • 第一行好像有错字; if 子句应该是(bst_node == NULL),即不是!
    • @CarlosEscobedo 可能由于其他原因导致段错误,除了提供的代码显示通用 DFS 遍历
    • 对您提交的代码所做的更改有效。谢谢
    • @CarlosEscobedo 不要忘记接受解决方案。欢迎来到stackoverflow
    【解决方案2】:

    简单:只需定义一个实用函数,其中stringstream 作为参数传递:

    void BSTree::InOrder(BSTNode *root, std::stringstream &ss)
    {
      if (root == nullptr) { return; }
      InOrder(root->GetLeftChild(), ss)
      ss << root->GetContents() << " ";
      InOrder(root->GetRightChild(), ss)
    }
    
    string BSTree::InOrder(BSTNode* bst_node) {
      stringstream ss;
      InOrder(bst_node, ss);
      return ss.str();
    }
    

    请注意,仅实例化一个 stringstream 转储整个树的位置可能比为树的每个节点实例化 stringstream 效率更高(如果您将实用程序函数定义为采用节点和返回一个字符串)。

    【讨论】:

      【解决方案3】:

      我对此毫无疑问 - 通过引用此方法将字符串流作为参数传递:

      static stringstream existingSSreference;
      string BSTree::InOrder(BSTNode* bst_node, stringstream & ss = existingSSreference) {
      
        if (root_ ==  NULL) {
          return "";
        } else {
          if (bst_node->GetLeftChild() != NULL) {
            InOrder(bst_node->GetLeftChild(), ss);
          }
          ss << bst_node->GetContents();
          if (bst_node->GetRightChild() != NULL) {
            InOrder(bst_node->GetRightChild(), ss);
          }
        }
        return ss.str();
      }
      

      或者你想在使用方法之前声明字符串流:

      stringstream ss;
      string myResult = bstreeObj->InOrder(bstNode, ss);
      

      或者不通过就直接使用

      string myResult = bstreeObj->InOrder(bstNode);
      

      这应该可以。最好在函数外部定义字符串流,并在调用函数时传递。

      编辑

      正如 Ajay 所指出的,引用参数不能具有默认值,除非我们将实际存在的实例作为默认值传递(这样我们就可以保留省略第二个参数的可能性)。

      【讨论】:

      • stringstream &amp; ss = NULL - 这还能编译吗?
      • 嗯,你是对的。我正在考虑测试这个例子,让我试试,我会用这个更正来更新它
      猜你喜欢
      • 1970-01-01
      • 2017-10-30
      • 1970-01-01
      • 2017-12-20
      • 2012-01-26
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多