实现指针队列

时间:2018-02-22 02:04:40

标签: c++ pointers queue

我正在尝试使用两个指针队列来实现8-puzzle(BFS)。我无法将未分类的节点添加到打开的列表中。我哪里错了?

#include <iostream>
#include <string>
#include <iostream>     
#include <algorithm>    
#include <vector>       
#include <queue>
using namespace std;
class Node {
public:
    vector<Node> children;
    vector<int> puzzle;
    vector<int> goal = {1, 2, 3, 4, 5, 6, 7, 8, 0};
    Node *parent;

    Node(vector<int> _puzzle, Node *_parent){
        puzzle=_puzzle;
        parent=_parent;
    }

    void printPuzzle() {
        int count = 0;
        for (auto i: puzzle) {
            if ( count % 3 == 0)
                std::cout << std::endl;
            std::cout << i << ' ';
            count++;   
        }
    }

    int findZero(){
        std::vector<int>::iterator it;
        it = find (puzzle.begin(), puzzle.end(), 0);
        auto z = std::distance(puzzle.begin(), it);
        return (int)z;
    }

    bool isGoal(){
        bool goalFound = false;
        if(puzzle == goal)
            goalFound = true;
        return goalFound;
    }

    void moveUp(){
        int zPos = findZero();
        vector<int> temp = puzzle;
        if ( zPos != 0 && zPos != 1 && zPos != 2 )
            std::swap(temp[zPos], temp[zPos-3]);
        Node child = Node(temp, this);
        children.push_back(child);        
    }

    void moveDown(){
        int zPos = findZero();
        vector<int> temp = puzzle;
        if ( zPos != 6 && zPos != 7 && zPos != 8 )
            std::swap(temp[zPos], temp[zPos+3]);
        Node child = Node(temp, this);
        children.push_back(child); 
    }

    void moveRight(){
        int zPos = findZero();
        vector<int> temp = puzzle;
        if ( zPos != 2 && zPos != 5 && zPos != 8 )
            std::swap(temp[zPos], temp[zPos+1]);
        Node child = Node(temp, this);
        children.push_back(child);
    }

    void moveLeft(){ 
        int zPos = findZero();
        vector<int> temp = puzzle;
        if ( zPos != 0 && zPos != 3 && zPos != 6 )
        std::swap(temp[zPos], temp[zPos-1]);
        Node child = Node(temp, this);
        children.push_back(child); 
    }

    bool isSamePuzzle(vector<int> p){
        bool samePuzzle = false;
        if(puzzle == p)
        samePuzzle =  true;
        return samePuzzle;

    }
};


bool contains(std::queue<Node*> q, Node n){
    bool exist = false;
    while (!q.empty()){
        cout << endl;
        if (q.front()->puzzle == n.puzzle)
        exist = true;
        q.pop();
    }
    return exist;
}

int main()
{
    std::vector<int> initial;
    initial.push_back(2);
    initial.push_back(1);
    initial.push_back(3);
    initial.push_back(4);
    initial.push_back(0);
    initial.push_back(6);
    initial.push_back(7);
    initial.push_back(5);
    initial.push_back(8);
    Node init = Node(initial, NULL);
    std::queue<Node*> openList;
    std::queue<Node*> closedList;
    openList.push(&init);
    bool goalFound = false;
    while(!openList.empty() && !goalFound){
        Node* currentNode = openList.front();
        closedList.push(currentNode);
        cout << "open list size " << openList.size() <<endl;
        cout << "closed list size " << closedList.size() <<endl;
        openList.pop();
        currentNode->moveUp();
        currentNode->moveDown();
        currentNode->moveRight();
        currentNode->moveLeft();

        for (auto i: currentNode->children){
            Node currentChild = i;
            if (currentChild.isGoal()){
                std::cout << "Goal Found." << endl;
                goalFound = true;                
            }
            if (!contains(openList, currentChild) && !contains(closedList, currentChild))
                openList.push(&currentChild);             
        }
    }
}

这似乎是有问题的一点:

            if (!contains(openList, currentChild) && !contains(closedList, 
 currentChild))
            openList.push(&currentChild); 

将一个或两个节点添加到打开列表后,程序崩溃。当我在打开的列表中打印出这个谜题时,我发现在开始时有一些垃圾值,然后是实际的傻瓜。

3 个答案:

答案 0 :(得分:0)

我将您的代码粘贴到我的IDE中并通过我的调试器运行它。我在这里看到的是当你在2 nd 迭代中经历你的while循环时;它打印出两行代码,它从openList弹出,调用并执行moveUp()但是当它进入moveDown()时就会崩溃。

它在这一行崩溃了:

std::swap( temp[zPos], temp[zPos+3] );

你可能想在调试器中检查这行代码,同时逐步检查你的变量和容器,看看它们是否有有效信息;还要检查您exceeding的{​​{1}}是否bound。您可能还想在上次调用container后调用memory后查看swap是否仍然有效。

不是在对moveUp()的1 st 调用期间,而是在2 nd 调用中,您将moveDown()设置为等于temp此处的问题是puzzle的值或大小为puzzle。因此,当您尝试在0&amp;上拨打std::swaptemp[zPos]索引无效,因为temp[zPos+3]temp

答案 1 :(得分:0)

您的程序的主要问题是,您将指针推送到打开列表中的本地变量。一旦保留范围,变量currentChild将被销毁(所以只要你进入循环的下一次迭代或离开循环),然后指针指向未使用/垃圾内存。

但是,您会在其他地方遇到类似的问题,因为您无法可靠地将指针保存到vector<Node>列表中的任何节点。这是因为std::vector类会在第一次达到某个大小时销毁/复制其中的所有内容,这将使其内部任何指针无效。因此,要么只保存 指向所有投币器(queuevector中的节点的指针,所以只有指针被销毁/复制),或者你不保存任何指向节点的指针,但只有节点本身 - 无论你最好的套房。

答案 2 :(得分:0)

我能够通过使子节点成为Node指针的向量来修复代码,如下所示:

vector<Node*> children;

并且每个子节点都是一个节点指针:

Node* child = new Node(temp, this);