我想修改下面的c ++代码,以使用循环而不是递归。 我知道两种修改方法:

  1. 从代码中学习并制定循环算法。 在这种情况下,我认为代码的含义是按级别顺序将printB(叶除外)和printA(预期根)。 对于二叉树(搜索树),如何在循环中将其从叶遍历到根(没有指向父树的指针)?

  2. 使用堆栈来模仿堆栈上的过程。 在这种情况下,我做不到,您能帮我说些有用的想法吗?

     void func(const Node& node) { if (ShouldReturn(node)) { return; } for (int i = 0; i < node.children_size(); ++i) { const Node& child_node = node.child(i); func(child_node); PrintA(); } PrintB(); } 

#1楼 票数:0

假设您正在使用C ++

对于堆栈部分,可以说,代码执行以下操作。

  1. 如果Node是叶子,则什么也没有。
  2. 否则,对每个孩子都做同样的事情,然后在每个孩子之后打印一个。
  3. 然后printB。

那如果我稍微调整一下代码该怎么办。 该调整仅适合于迭代方式。

void func(const Node& node) {
    if(ShouldReturn(node)) return;
    PrintB();
    for(int i = 0; i < node.children_size(); ++i) {
        printA();
        const Node& child_node = node.child(i);
        func(child_node, false);
    }
}
// This way should make it print As & Bs in reverse direction.
// Lets re-adjust the code even further.

void func(const Node& node, bool firstCall = true) {
    if(!firstCall) printA; //Placed that here, as printA is always called if a new Node is called, but not for the root Node, that's why I added the firstCall.
    if(ShouldReturn(node)) return;
    PrintB();
    for(int i = 0; i < node.children_size(); ++i) {
        const Node& child_node = node.child(i);
        func(child_node, false);
    }
}

那应该颠倒了打印A和B的顺序,希望我没错:D所以,现在我想有2个向量。

// Lets define an enum
typedef enum{fprintA, fprintB} printType;

void func(const Node& node){
     vector<printType> stackOfPrints;
     vector<Node*> stackOfNodes; stackOfNodes.push_back(node);
     bool first = true; //As we don't need to printA before the root.
     while ((int)stackOfNodes.size() > 0){
         const Node& fNode = stackOfNodes.back();
         stackOfNodes.pop_back();
         if (!first) stackOfPrints.push_back(fprintA); // If not root printA.
         first = false;
         if(ShouldReturn(fNode)) continue;
         stackOfPrints.push_back(fprintB);
         // here pushing the Nodes in a reverse order so that to be processed in the stack in the correct order.
         for(int i = (int)fNode.children_size() - 1; i >= 0; --i){
               stackOfNodes.push_back(fNode.child(i));
         }
     }

     // Printing the stackOfPrints in reverse order (remember we changed the code, to initially print As & Bs in reverse direction) 
     // this way, it will make the function print them in the correct required order
     while((int)stackOfPrints.size() > 0){
         switch(stackOfPrints.back()){
            case fprintA: printA(); break;
            case fprintB: printB(); break;
            default: break;
         };
         stackOfPrints.pop_back();
     }
}

希望我能正确编写代码。 :)希望对您有所帮助。

  ask by xunzhang translate from so

未解决问题?本站智能推荐:

3回复

Haskell:二叉树深度的尾递归版本

首先,我有两种不同的实现,我认为它们是正确的,并且对它们进行了分析并认为它们具有相同的性能: 我只是想知道人们不是在谈论尾递归如何对性能有益吗? 很多问题涌入我的脑海: 如何使深度函数更快? 我读到一些关于 Haskell 的懒惰如何减少尾递归需要的内容,这是真的吗? 每次递归都可以转化为尾递
2回复

如何将以下函数转换为尾递归函数?

我正在跟随这里 ,我正在尝试将正常的递归函数转换为尾递归函数。 我设法理解斐波纳契和阶乘版本,但这个让我很难过。 我理解算法在做什么,以及在转换中让我困惑的else语句。 在其他内部,它试图找到一个更接近你正在寻找的数字,然后放弃并找到它找到的数字小于你建议的数字。 我不知道如何编写
3回复

在Haskell中使用尾递归拆分BinTree

所以本周我们在Haskell中了解了联合类型,尾递归和二叉树。 我们定义了我们的树数据类型: 现在我们被要求编写一个函数来查找最左边的节点,返回它,将其剪切掉,并返回剩下的树而没有我们刚剪切的节点。 我们做了类似的事情,效果很好: 现在我需要使这个函数尾递归。 我想我理解尾递归是
2回复

二叉树尾的Scalasum是递归的

所以我有以下代码定义二叉树。 sum方法尾递归吗? 我怀疑是不是尾递归,因为对right.sumAcc的调用必须等待left.sumAcc(elem + acc)终止。 如果它不是尾递归,我怎么能改变呢?
1回复

如何对二叉树进行尾递归?

如果你有一个二叉树,你如何使用尾递归迭代(按顺序)? 我知道尾部递归涉及您在迭代时计算新值,然后当您到达基本情况时,您只需返回累积。 但是当你必须调用函数调用两次时,如何为树执行此操作?
1回复

如何消除以下函数中的尾递归(从两个递归调用到一个)?

我有以下功能: 其中 d 是方向,可以是“L”或“R”。 node->r 和 node->l 分别是一个节点的左右子节点。 我试图从中删除尾递归,以便它在功能上等效 - 它现在进行两次递归函数调用,但我希望它进行一次。 如何重写函数以实现此目标? 谢谢你。
3回复

在函数式语言中,编译器如何能够将非尾递归转换为循环以避免堆栈溢出(如果有的话)?

我最近一直在学习函数式语言,有多少不包含for循环。 虽然我个人并不认为递归比for循环更难(并且通常更容易推理),但我意识到许多递归的例子不是尾递归的,因此不能使用简单的尾递归优化来避免堆栈溢出。 根据这个问题 ,所有迭代循环都可以转换为递归,并且那些迭代循环可以转换为尾递归,所以当像这样
4回复

数尾递归的威力

我正在尝试使用运行时间为 log(n) 的尾递归来计算 num 的幂。 据我了解,使用 power // 2 而不是 power - 1 的区别在于减少运行时间。 因此,当我计算该值时,我需要将旧值与另外两个总和相乘而不是一个。 我的代码工作 find 直到它达到 power_of(2,6)