【发布时间】:2019-07-25 14:42:24
【问题描述】:
最近我通过了一个编程面试,我必须创建一个返回节点地址的方法(属于树)。该方法将整数值作为参数。
我的代码在一棵小树上工作,但是在搜索一棵大树(300,000 个节点)时,我收到一条错误消息,指出“无法访问地址 '0x.....'”。 我应该怎么做才能解决这个问题?
'''
struct Node
{
int value;
Node* left = nullptr;
Node* right = nullptr;
Node* find_node(int);
};
Node* Node::find_node(int v)// The function is working on small trees only
{
if(this->value == v) //comparing the the value inside the root with the function's argument
return this;
else if(this->value > v) //if v is smaller than the node's value, search the next left node
{
if(this->left == nullptr) //checking if the next node on the left exists
return nullptr; //null returned if there is no more nodes
else
return (this->left)->find_node(v); //Call the find_node function recursively on the left node
}
else if(this->value < v) //if v is bigger than the node's value, search the next right node
{
if(this->right == nullptr) //checking if the next node on the left exists
return nullptr; //null returned if there is no more nodes
else
return (this->right)->find_node(v);// Call the find_node function recursively on the right node
}
return nullptr;// If the value is not found
}
'''
【问题讨论】:
-
给定的代码看起来很合理。使用 300,000 个节点,如果树不平衡或者您有少量自动存储,您可能会耗尽可用的自动存储。
-
以更高的优化级别编译以优化尾递归调用的堆栈开销。
-
如何制作一个可重现的最小示例: 1. 备份您的程序。 2.从程序中删除不需要暴露错误的所有内容,同时仍然有一个可以编译和运行的程序。是的,这比听起来更难,但它几乎总是消除了提问的需要。如果你一直带着 MCVE,你最终会得到一个只有几行的程序,但你几乎不需要走那么远。通常在代码大小减半后,该错误几乎没有隐藏的空间,以至于它会跳出来打你一巴掌。
-
检查分配失败。处理异常。只要你没有耗尽内存或溢出堆栈,这个函数对我来说看起来没问题。我的钱用于分配节点时未被发现的失败。 (旁注,你不能只使用 std::set,并争辩说它已经作为树实现了吗?)
-
恕我直言,将
find_node移出Node类并进入树类。Node是单个对象,而不是对象容器。 tree 是Nodes 的容器。您可以搜索容器,但在Node中搜索Node是没有意义的。