【问题标题】:C++ Non binary tree: getting tree leaves collection (performance question)C++ 非二叉树:获取树叶集合(性能问题)
【发布时间】:2018-11-22 23:56:04
【问题描述】:

我有一个像这样的非二叉树结构构建表单节点:

struct Node
{
    Node*              pa_;
    std::vector<Node*> children_;

    std::vector<Node*> GetLeaves()
};

通过树叶,我理解没有子节点的树节点。提供树叶集合的方法如下所示:

    std::vector<Node*> Node::GetLeaves()
    {
        std::vector<Node*> ret;
        if(!children_.size())
        {
            ret.push_back(this);
        }
        else
        {
            for (auto child : children_)
            {
                auto child_leaves = child->GetLeaves()
                ret.insert( ret.end(),
                            child_leaves.begin(),
                            child_leaves.end() );
            }
        }
        return std::move(ret);
    }

免得说整棵树可以有数百片叶子。

使用向量作为叶子的容器,意味着在插入返回的集合时会发生大量内存重新分配。

问题是:使用 std::list 而不是 std::vector 不是可取的吗?

提前谢谢

【问题讨论】:

  • 由于您的列表仅包含指针,我怀疑您会看到使用 std::list 的好处。大概您的实现也不正确,因为它返回当前节点的大子节点并且不检查它们是否是叶子?
  • const std::vector& GetLeaves() {return children_;} 应该足够快。为什么你还需要别的东西?似乎在设计方面有些不对劲。
  • @Alain 刚刚更正 ;)
  • 嗯,您正在为每个内部节点生成一个新向量。将结果容器作为要填充的函数的参数传递以避免这种情况。替代方法:实现一个迭代器,让用户使用现有结构迭代叶子,而无需生成列表。
  • @Nico 将返回向量作为参数传递对重复插入没有帮助,它会通过重复 push_back 进行更改。 (@Jeffrey 设计已更正)

标签: c++ tree


【解决方案1】:

避免递归将消除一些复制并允许您只构建一个列表:

std::vector<Node*> Node::GetLeaves()
{
    if (children_.empty())
    {
      return std::vector<Node*>(this, 1);
    }
    std::vector<Node*> ret;
    std::stack<Node*> nodes;
    nodes.push(this);
    while (!nodes.empty())
    {
      Node* parent = nodes.top();
      nodes.pop();
      for (auto node : parent->children_)
      {
        if (node->children_.empty())
        {
          ret.push_back(node);
        }
        else
        {
          nodes.push(node);
        }
      }
    }
    return ret;
}

如果要更改遍历顺序,可以将stack 更改为queue

【讨论】:

  • 我可以看到这个想法,但我看不出这个确切的代码是如何工作的。首先 std::stack 不支持基于范围的循环。其次,它会一遍又一遍地推送和弹出同一个节点(推送应该会影响孩子们_我想)。
  • @BudziwojMan 已修复(尽管尚未测试,因为您没有提供 minimal reproducible example 进行测试)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-14
  • 1970-01-01
相关资源
最近更新 更多