如何在函数的递归调用之间传递值?

时间:2021-01-25 00:40:51

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

我有一个名为 inorderHelperArray 的函数,它接受一个数组和一个指向二叉搜索树根节点的指针,并使用有序遍历从 BST 中的每个节点获取数据并将数据放入数组中。下面是这个函数的样子:

void BinTree::inorderHelperArray(NodeData* a[], Node *startNode) const{
    /*static*/ int i = 0;
    //This code works if I set i as a static int.
    //However, I cannot call this function again, as i is never reset to 0.
    
    if(startNode != nullptr){
        inorderHelperArray(a, startNode->left);
        cout << "i: " << i << endl;
        a[i++] = startNode->data;
        inorderHelperArray(a, startNode->right);
    }
}

如果在 static int i = 0; 中将 i 声明为静态,我只能让 inorderHelperArray 函数正常工作。但是,这是一个问题,就好像我再次调用 inorderHelperArray 一样,代码会中断。 i 永远不会重置为 0,我最终将数组中的值分配给我“离开”的任何地方。例如,如果我调用 inorderHelperArray 并且 BST 有 13 个节点,那么我将是 13。如果我再次调用 inorderHelperArray ,我将从 13 开始,这意味着我将在我试图从索引 13 开始创建数组。如果 i 未声明为静态 int i=0;,那么这不起作用,因为每次对该函数进行递归调用时,我都保持在 0。

谁能给我一些关于如何使上述代码正常工作的建议?有没有一种方法可以让我获得静态变量的好处,但在最终递归调用后退出 inorderHelperArray 时让它自行重置?

3 个答案:

答案 0 :(得分:0)

您可以将调用 inorderHelperArray(NULL, NULL) 解释为有效调用、重置请求,并在这种情况下将 i 重置为 0。所以在用实际数据调用它之前,你总是要进行这个“重置请求”调用。

所以函数看起来像

void BinTree::inorderHelperArray(NodeData* a[], Node *startNode) const{
    static int i = 0;

    if(startNode != nullptr){
        inorderHelperArray(a, startNode->left);
        cout << "i: " << i << endl;
        a[i++] = startNode->data;
        inorderHelperArray(a, startNode->right);
    }
    else{   
        if( a == nullptr) i = 0;   ///// NB
    }
}

答案 1 :(得分:0)

我建议您更改界面。可能最好的改变是通过引用传入一个向量,并在您访问数据时将其 push_back 到它上面。由于移动语义,这应该是有效的返回。

void inorderHelper(std::vector<NodeData*>& a, Node *startNode) {
    if(startNode != nullptr) {
        inorderHelper(a, startNode->left);
        a.push_back(startNode->data);
        inorderHelper(a, startNode->right);
    }
}

auto inorder(Node * startNode) {
    std::vector<NodeData*> result;
    inorderHelper(result, startNode);
    return result;
}

另一种方法,更接近您的原始方法——但前提是您必须使用数组(恕我直言,这是个坏主意,因为没有防止内存覆盖的保护,并且容易出错并可能导致泄漏),是通过引用传递整数,与我在上面做向量的方式类似:

void inorderHelper(NodeData* a[], int& i, NodeData *startNode) {
    if(startNode != nullptr) {
        inorderHelper(a, i, startNode->left);
        a[i++] = startNode->data;
        inorderHelper(a, startNode->right);
    }
}

void inorder(NodeData* a[], Node * startNode) {
    int i = 0;
    inorderHelper(a, i, startNode);
}

我从类中删除了这些函数,以便可以单独显示它们。

答案 2 :(得分:0)

您可以执行以下操作:

int BinTree::inorderHelperArray(NodeData* a[], Node *startNode, int i = 0) const
{
    if (startNode != nullptr) {
        i = inorderHelperArray(a, startNode->left, i);
        std::cout << "i: " << i << std::endl;
        a[i++] = startNode->data;
        i = inorderHelperArray(a, startNode->right, i);
    }
    return i;
}

但使用 std::vector 作为结果似乎更好:

// private
void BinTree::inorderHelperArrayRec(Node *startNode, std::vector<NodeData*>& res) const
{
    if (startNode != nullptr) {
        inorderHelperArray(startNode->left);
        std::cout << "i: " << res.size() << std::endl;
        res.push_back(startNode->data);
        inorderHelperArray(startNode->right);
    }
}
// public interface
std::vector<NodeData*> BinTree::inorderHelperArray(Node *startNode) const
{
    std::vector<NodeData*> res;
    inorderHelperArrayRec(startNode, res);
    return res;
}
相关问题