如何避免深树递归中的堆栈溢出
我读过很多类似的文章,如果已经回答了这个问题,我深表歉意,但我仍然陷入困境。
我正在编写一个函数来填充一棵树,每个节点有四个分支,这将存储“八块拼图”的可能状态操作,即 http://www.8puzzle.com/images/8_puzzle_start_state_a.png
问题是我已经达到了我所相信的由于当前问题的严重递归性质,堆栈溢出。
尾递归似乎是解决方案,尽管我不确定它是否相关/可能或如何在这种情况下实现它。代码如下:
void Tree::insert(string &initialState, const string &goalState, tree_node *&inNode){
cout<<"insert called"<<endl;
depth++;
cout<<depth<<endl;
string modState;
int zeroPos=0;
if(initialState==goalState){
cout<<"* * * GOAL * * *"<<endl;
getchar();
exit(0);
}
if(inNode==NULL){//is this the first node?
inNode = new tree_node(initialState);
root=inNode;
inNode->parent=NULL;
insert(initialState, goalState, inNode);
}else{
inNode->state = initialState;
for(zeroPos=0;zeroPos<initialState.size();zeroPos++){//where is the empty tile?
if(initialState[zeroPos]=='0'){
break;
}
}
//left
if(zeroPos!=0 && zeroPos!=3 && zeroPos!=6){//can the empty tile move left?
modState=initialState;
modState[zeroPos]=modState[zeroPos-1];
modState[zeroPos-1]='0';
if(isOriginal(modState, inNode) ){//does this state already exist?
cout <<"left " << modState[0]<<modState[1]<<modState[2]<<endl;
cout <<"left " << modState[3]<<modState[4]<<modState[5]<<endl;
cout <<"left " << modState[6]<<modState[7]<<modState[8]<<endl;
inNode->l = new tree_node(modState);
inNode->l->parent= inNode;
if(inNode->l != NULL){
insert(modState, goalState, inNode->l);
}
}
}
}
}
}
I've read many similar articles, I apologise if this has already been answered, but I'm still stuck.
I'm coding a function to populate a tree, each node having four branches, which will store the possible manipulation of states of the "eight tile puzzle" i.e. http://www.8puzzle.com/images/8_puzzle_start_state_a.png
The problem is I've reached, what I believe to be, stack overflow, due to the heavily recursive nature of the problem at hand.
Tail recursion seems like the solution, though I'm not sure if it is relevant/possible or how to implement it in this instance. Code follows:
void Tree::insert(string &initialState, const string &goalState, tree_node *&inNode){
cout<<"insert called"<<endl;
depth++;
cout<<depth<<endl;
string modState;
int zeroPos=0;
if(initialState==goalState){
cout<<"* * * GOAL * * *"<<endl;
getchar();
exit(0);
}
if(inNode==NULL){//is this the first node?
inNode = new tree_node(initialState);
root=inNode;
inNode->parent=NULL;
insert(initialState, goalState, inNode);
}else{
inNode->state = initialState;
for(zeroPos=0;zeroPos<initialState.size();zeroPos++){//where is the empty tile?
if(initialState[zeroPos]=='0'){
break;
}
}
//left
if(zeroPos!=0 && zeroPos!=3 && zeroPos!=6){//can the empty tile move left?
modState=initialState;
modState[zeroPos]=modState[zeroPos-1];
modState[zeroPos-1]='0';
if(isOriginal(modState, inNode) ){//does this state already exist?
cout <<"left " << modState[0]<<modState[1]<<modState[2]<<endl;
cout <<"left " << modState[3]<<modState[4]<<modState[5]<<endl;
cout <<"left " << modState[6]<<modState[7]<<modState[8]<<endl;
inNode->l = new tree_node(modState);
inNode->l->parent= inNode;
if(inNode->l != NULL){
insert(modState, goalState, inNode->l);
}
}
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是一个非常通用的答案,但是您是否尝试过通过堆分配队列或堆栈之类的方式显式管理堆栈?基本上不使用实际的函数调用,只是将东西从你自己的堆栈/队列中推入和拉出。它们涵盖了非递归图遍历算法此处(都是深度优先,以及广度优先搜索)。
This is a very generic answer, but have you tried to explicitly manage your stack through something like a heap allocated queue or a stack? Basically don't use actually function calls, just push and pull things off your own stack/queue. They cover non-recursive graph traversal algorithms here (both depth first, and breadth first search).
优化您的代码,意味着只保留您需要的节点。例如,仅保留叶节点(我的意思是尚未扩展的叶节点)。
是的,您可以在构建树时搜索树,编写一个函数来测量当前状态和目标状态之间的距离,这称为启发式。还有一个更好的算法可以解决8puzzle,它叫做A*,我建议你google一下。
Optimize your code, meaning only keep those nodes you need. For example only keep leaf nodes (I mean the ones you haven't yet expaneded).
And yes you can search the tree while building it, write a function to measure the distance between your current state and your goal state, its called heuristic. There's also a better algorithm that solves 8puzzle, it's called A*, I suggest you google it.