我有一个名为 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 时让它自行重置?
答案 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;
}