如何在C++;? 我正在研究一个C++项目,它需要频繁地与树结构交互,这意味着很多递归函数,我正在寻找改进代码的方法。前几天我遇到过,我对探索我的应用程序的这一策略很感兴趣 但是,我还没有找到任何C++实现CracururyCurrices的例子。为了使我的问题具体化,我在C++中如何做?

如何在C++;? 我正在研究一个C++项目,它需要频繁地与树结构交互,这意味着很多递归函数,我正在寻找改进代码的方法。前几天我遇到过,我对探索我的应用程序的这一策略很感兴趣 但是,我还没有找到任何C++实现CracururyCurrices的例子。为了使我的问题具体化,我在C++中如何做?,c++,corecursion,C++,Corecursion,如果这样做只是一个坏主意,让我知道。这就是说,在互联网上找到一些答案对那些将来尝试这样做的人来说是有用的。如此匹配的[c++]corecursion是没有问题的,互联网的其他部分似乎缺乏关于这个主题的有用信息。因此有几种方法 您可以按照建议等待wait关键字到达,但这似乎是长期的。如果你等待等待,至少乍一看应该在C++中工作。 您可以编写一个生成迭代器助手,或者从boost中借用一个,并从中生成一个生成器 您可以使用存储在std::function中的可变lambda,可能返回std::expe

如果这样做只是一个坏主意,让我知道。这就是说,在互联网上找到一些答案对那些将来尝试这样做的人来说是有用的。如此匹配的
[c++]corecursion
是没有问题的,互联网的其他部分似乎缺乏关于这个主题的有用信息。

因此有几种方法

您可以按照建议等待wait关键字到达,但这似乎是长期的。如果你等待等待,至少乍一看应该在C++中工作。 您可以编写一个生成迭代器助手,或者从boost中借用一个,并从中生成一个生成器

您可以使用存储在
std::function
中的可变lambda,可能返回
std::experimental::optional
(或boost optional)

但这些大多只是让它变得漂亮。所以让我们变丑吧。我将用C++14编写这个,因为我很懒

struct generator {
  using trees=std::vector<tree>;
  trees m_cur;      
  trees m_next;
  bool next(value* v){
    while(true){
      if (m_cur.empty()){
        m_cur=std::move(m_next);
        m_next.clear();
        std::reverse(begin(m_cur),end(m_cur));
        if(m_cur.empty())
          return false;
      }
      auto t = m_cur.back();
      m_cur.pop_back();
      if(!t)continue;
      *v = get_value(t);
      m_next.push_back(get_left(t));
      m_next.push_back(get_right(t));
      return true;
    }
  }
  generator(tree t):m_cur{t}{};
};
这基本上是python代码的行到行翻译。我确实编写了一个helper函数的
vec\u来替换python中的
[]

使用:

for(自动和值:宽度优先(树)){

std::cout一个有趣的问题。这个问题更多的是关于通过联合迭代器产生的
的性质

基本上,如果您需要在C++中使用代码>收益率<代码>,那么您需要实现一个迭代器式状态机,这几乎就是协同递归的概念。 一个有效的示例需要实现一个树类,但这里是BFS的部分实现,使用的基本上是wiki文章中的策略(修复了一点,因为他们的算法有点愚蠢)

for(bfs_生成器i=bfs_生成器(myTree);
i、 好吗;
i、 next())
{
打印(i.值());
}
//迭代器风格的操作重载可能更合适,但我不想讨论语法细节
//我假设一个标准的C节点结构,带有树的左指针和右指针实现。
类bfs_迭代器
{
//Python示例有点奇怪,因为它将状态表示为两个列表,而只需要一个列表
std::队列树\u列表;
公众:
bfs_迭代器(节点*根)
{
树列表。向后推(根);
}
布尔很好
{
返回树_list.empty();
}
作废下一页()
{
//弹出队列的前端,然后将子项添加到队列中。
如果(!tree_list.empty())
{
Node*Node=tree_list.front();
tree_list.pop();
如果(节点->左)
树列表。推送(节点->左);
如果(节点->右侧)
树列表。推送(节点->右侧);
}
}
MyTree::value()值
{
返回树\u list.front()->值;
}
};
从技术上讲,您不需要模仿他们的
yield
generator策略来实现这一点。您可以直接在代码中使用队列,而不是定义类


这与wikipedia算法有点不同,因为wiki算法并不理想。它们基本相同,但wikipedia示例有点像穷人的队列。

以下内容与给定的python实现几乎相同,您现在可以在生产中使用它:

#include <vector>
#include <iostream>
#include <boost/coroutine/all.hpp>

using namespace std;

struct Node {
    char value;
    Node *left;
    Node *right;
};

using generator =
    boost::coroutines::asymmetric_coroutine<decltype(Node::value)>::pull_type;

generator bf(Node *tree) {                                //def bf(tree):
    return generator([=](auto &yield) {                   //
        vector<Node *> tree_list = {tree};                //    tree_list = [tree]
        while (!tree_list.empty()) {                      //    while tree_list:
            vector<Node *> new_tree_list;                 //        new_tree_list = []
            for (auto tree : tree_list) {                 //        for tree in tree_list:
                if (tree != nullptr) {                    //            if tree is not None:
                    yield(tree->value);                   //                yield tree.value
                    new_tree_list.push_back(tree->left);  //                new_tree_list.append(tree.left)
                    new_tree_list.push_back(tree->right); //                new_tree_list.append(tree.right)
                }                                         //
            }                                             //
            tree_list = move(new_tree_list);              //        tree_list = new_tree_list
        }                                                 //
    });                                                   //
}                                                         //

int main() {
    Node a{'a'}, b{'b'}, c{'c'}, d{'d'}, e{'e'};

    a.left = &b;
    a.right = &c;
    b.right = &d;
    d.left = &e;

    for (auto node_value : bf(&a))
        std::cout << node_value << " ";
}
#包括
#包括
#包括
使用名称空间std;
结构节点{
字符值;
节点*左;
节点*右;
};
使用发电机=
boost::coroutines::不对称_coroutine::pull_类型;
生成器bf(节点*树){//def bf(树):
返回生成器([=](自动和产量){//
向量树列表={tree};//树列表=[tree]
while(!tree_list.empty()){//while tree_list:
向量新建树列表;//新建树列表=[]
对于(自动树:树列表){//对于树列表中的树:
如果(tree!=nullptr){//如果tree不是None:
产量(tree->value);//产量tree.value
新建树列表。向后推(树->左);//新建树列表。追加(树.左)
新建树列表。向后推(树->右);//新建树列表。追加(树.右)
}                                         //
}                                             //
树列表=移动(新树列表);//树列表=新树列表
}                                                 //
});                                                   //
}                                                         //
int main(){
节点a{'a'},b{'b'},c{'c'},d{'d'},e{'e'};
a、 左=&b;
a、 右=&c;
b、 右=&d;
d、 左=&e;
用于(自动节点_值:bf(&a))

Std::CUT@ FrBru:是的,你缺少了一些东西。在Python中,CurrurSurviod很容易表达,所以OP使用Python来表达它。OP想在C++中做CycururyC++Python,但不知道如何。@ Yakk,那么他也应该标记它Python。至少,旧学校的鬼鬼祟祟的C东西可能会有些皱眉,但是有一个很酷的实现:)@ForceBru:不,我不这么认为。我也喜欢等待
wait
…是的,lambda可以捕获自身作为递归的一种手段,同样的概念似乎也适用于返回自身,尽管有一两处褶皱-您必须使用嵌套lambda,并且可能(?)动态分配。这是我正在看的页面:。似乎付出了更多的努力,但大部分是b
generator g(some_tree);
value v;
while(g.next(&v)){
  std::cout<<v<<'\n';
}
template<class T0, class...Ts>
std::vector<std::decay_t<T0>> vec_of(T0&& t0, Ts&&... ts) {
  return {std::forward<T0>(t0), std::forward<Ts>(ts)...};
}
auto breadth_first = [](auto&& tree){
  auto tree_list = vec_of(decltype(tree)(tree));
  while(!tree_list.empty()) {
    decltype(tree_list) new_tree_list;
    for(auto&& tree:tree_list) {
      if (tree) {
        yield get_value(tree);
        new_tree_list.push_back(get_left(tree));
        new_tree_list.push_back(get_right(tree));
      }
    }
    tree_list = std::move(new_tree_list);
  }
};
for(auto&& value : breadth_first(tree)) {
  std::cout << value;
}
for (bfs_generator i = bfs_generator(myTree);
    i.is_good();
    i.next())
{
  print (i.value());
}

// Iterator-style operation overloads may be more appropriate, but I don't want to deal with the syntactic details
// I assume a standard C Node struct with left and right pointers implementation of your tree.
class bfs_iterator
{
  // The Python example is a little strange because it expresses the state as two lists, when only one is necessary
  std::queue<Node *> tree_list;

  public:
  bfs_iterator (Node * root)
  {
    tree_list.push_back(root);
  }

  bool is_good()
  {
    return tree_list.empty();
  }

  void next()
  {
    // Pop the front of the queue then add the children to the queue.
    if (!tree_list.empty())
    {
      Node * node = tree_list.front();
      tree_list.pop();

      if (node->left)
        tree_list.push(node->left);
      if (node->right)
        tree_list.push(node->right);
    }
  }

  MyTree::value value()
  {
    return tree_list.front()->value;
  }
};
#include <vector>
#include <iostream>
#include <boost/coroutine/all.hpp>

using namespace std;

struct Node {
    char value;
    Node *left;
    Node *right;
};

using generator =
    boost::coroutines::asymmetric_coroutine<decltype(Node::value)>::pull_type;

generator bf(Node *tree) {                                //def bf(tree):
    return generator([=](auto &yield) {                   //
        vector<Node *> tree_list = {tree};                //    tree_list = [tree]
        while (!tree_list.empty()) {                      //    while tree_list:
            vector<Node *> new_tree_list;                 //        new_tree_list = []
            for (auto tree : tree_list) {                 //        for tree in tree_list:
                if (tree != nullptr) {                    //            if tree is not None:
                    yield(tree->value);                   //                yield tree.value
                    new_tree_list.push_back(tree->left);  //                new_tree_list.append(tree.left)
                    new_tree_list.push_back(tree->right); //                new_tree_list.append(tree.right)
                }                                         //
            }                                             //
            tree_list = move(new_tree_list);              //        tree_list = new_tree_list
        }                                                 //
    });                                                   //
}                                                         //

int main() {
    Node a{'a'}, b{'b'}, c{'c'}, d{'d'}, e{'e'};

    a.left = &b;
    a.right = &c;
    b.right = &d;
    d.left = &e;

    for (auto node_value : bf(&a))
        std::cout << node_value << " ";
}
generator bf(Node *tree) {
    return generator([=](auto &yield) {
        vector<Node *> tree_list = {tree}, new_tree_list;
        while (!tree_list.empty()) {
            for (auto tree : tree_list) {
                if (tree != nullptr) {
                    yield(tree->value);
                    new_tree_list.push_back(tree->left);
                    new_tree_list.push_back(tree->right);
                }
            }
            swap(tree_list, new_tree_list);
            new_tree_list.clear();
        }
    });
}