如何避免深树递归中的堆栈溢出

时间:2011-04-30 05:07:34

标签: c++ recursion tree stack-overflow

我读过很多类似的文章,如果这已经得到回答,我道歉,但我仍然被卡住了。

我正在编写一个函数来填充树,每个节点有四个分支,这将存储“八个拼图”状态的可能操作,即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);
            }
        }
    }

    }
 }
}

2 个答案:

答案 0 :(得分:2)

这是一个非常通用的答案,但您是否尝试通过堆分配队列或堆栈等方式显式管理堆栈?基本上不要使用实际的函数调用,只需从你自己的堆栈/队列中推送和拉出东西。它们涵盖了非递归图遍历算法here(深度优先和广度优先搜索)。

答案 1 :(得分:0)

优化代码,意味着只保留您需要的节点。例如,只保留叶子节点(我的意思是那些你尚未透露的节点)。 是的,您可以在构建树时搜索树,编写一个函数来测量当前状态和目标状态之间的距离,称为启发式。还有一个更好的算法解决了8puzzle,它被称为A *,我建议你谷歌吧。