如何让这个算法更有效?

时间:2015-05-15 07:08:28

标签: c++ performance algorithm memory breadth-first-search

我似乎已经在这段代码上工作了几天 对于相对较小的搜索树工作得很好,但使用较高的搜索树会产生分段错误。

我试图通过使用打印标志来找到出现此类错误的特定位置,并且它似乎在is_goal()函数处中断。但是可以假定该函数的代码是正确的。

所以问题似乎是一个内存问题,这就是为什么我在堆中有队列,以及我正在创建的节点。但它仍然崩溃。

是否有更多的内存节省技巧可以考虑到我没有使用?或者可能有更好的方法来保存这些节点?

重要的是要注意我需要使用BFS(我不能使用A *来缩小搜索树)。

另外,如果你需要知道,地图是一个哈希表,我保存节点的颜色,所以我在探索时没有重复(这是因为哈希保存取决于状态信息而不是节点信息)。

编辑:我被告知要指出要完成的目标,比如在搜索树中找到目标状态,目标是能够迭代 像rubik 3x3x3,n-puzzle 4x4 5x5,河内之塔这样的大问题。这样做,所使用的内存必须是最小的,因为这类问题的搜索树真的很大,最终的目标是将这个算法与其他算法进行比较像a *,dfid,ida *等。我希望这是足够的信息。

  Node* BFS(state_t start ){

    state_t state, child;  
    int d, ruleid;
    state_map_t *map = new_state_map();
    ruleid_iterator_t iter;
    std::queue<Node*> *open = new std::queue<Node*>();

    state_map_add( map, &start, 1); 

    Node* n = new Node(start);
    open->push(n);

    while( !open->empty() ) {
        n = open->front();
        state = n->get_state();
        open->pop();

        if (is_goal(&state) == 1) return n;

        init_fwd_iter( &iter, &state ); 

        while( ( ruleid = next_ruleid( &iter ) ) >= 0 ) {
            apply_fwd_rule( ruleid, &state, &child );


            const int *old_child_c = state_map_get( map, &child );
            if ( old_child_c == NULL ) {
                state_map_add( map, &child, 1 );
                Node* nchild = new Node(child); 
                open->push(nchild);
            }

        }

    }

    return NULL;
}  

1 个答案:

答案 0 :(得分:3)

我看到了一些内存泄漏。

open永远不会删除,但也许可以在堆栈中而不是在堆中分配。

std::queue<Node*> open;

更重要的是,您在队列中推送的节点都没有被删除,这可能是内存消耗非常大的原因。

删除您从队列中删除的节点以及您不打算重复使用的节点。在摆脱队列之前删除队列的节点。

Node* BFS(state_t start ){

    state_t state, child;  
    int d, ruleid;
    state_map_t *map = new_state_map();
    ruleid_iterator_t iter;
    std::queue<Node*> open;

    state_map_add( map, &start, 1); 

    Node* n = new Node(start);
    open.push(n);

    while( !open.empty() ) {
        n = open.front();
        state = n->get_state();
        open.pop();

        if (is_goal(&state) == 1) {
            for (std::queue<Node*>::iterator it = open.begin(); it != open.end(); ++it)
                delete *it;

            return n;
        }
        else {
            delete n;
        }

        init_fwd_iter( &iter, &state ); 

        while( ( ruleid = next_ruleid( &iter ) ) >= 0 ) {
            apply_fwd_rule( ruleid, &state, &child );


            const int *old_child_c = state_map_get( map, &child );
            if ( old_child_c == NULL ) {
                state_map_add( map, &child, 1 );
                Node* nchild = new Node(child); 
                open.push(nchild);
            }

        }

    }

    return NULL;
}