简体   繁体   English

双向链表父指针改变

[英]Doubly-Linked list Parent pointer changing

implementing a greedy solution to solve and 8-puzzle实现一个贪心的解决方案来解决和 8-puzzle

Greedy.h:贪婪.h:

class Greedy {
    const string Goal = "12345678_";
    State current;
    string startState;
    int nodesCreated, nodesExpanded;
    priority_queue<State> greedyQueue;
    set<string> visited;
    stack<string> solutionStack;    
public:
    Greedy(const string start);
    ~Greedy();    
    void doGreedy();
};

Greedy.cpp:贪婪.cpp:

tuple<int, int> getTarget(int n);


Greedy::Greedy(const string start) : startState(start), nodesCreated(0), nodesExpanded(0) {}

Greedy::~Greedy() {}    

void Greedy::doGreedy() {
    greedyQueue.emplace(startState, "");
    while (!greedyQueue.empty()) {
        current = greedyQueue.top();
        greedyQueue.pop();
        if (visited.find(current.stateString) == visited.end()) {
            visited.insert(current.stateString);
            if (current.stateString == Goal) {  //end has been reached, calculate path, print out stats, and end.
                cout << "Solution Found!" << endl;
                //solutionStack.push(current.moveFromParent);
                State* tempParent = current.parent;
                while ( solutionStack.size() < 20 && tempParent != NULL) {
                    solutionStack.push(tempParent->moveFromParent);
                    tempParent = tempParent->parent;
                }
                break;
            }
            vector<State> childrenFound = current.expandNode();
            for (int i = 0; i < childrenFound.size(); ++i) {    // for each child found, add it to the priority queue, set its parent, and set it as a child of parent
                State temp = childrenFound[i];
                if (visited.find(temp.stateString) == visited.end()) {  // We haven't been here before, put it in the queue
                    greedyQueue.push(temp);
                }
            }
        }
    }
    cout << "Last 20 moves:" << endl;
    while (!solutionStack.empty()) {
        cout << solutionStack.top() << endl;
        solutionStack.pop();
    }
}

State.h:状态.h:

class State {
public:
    string moveFromParent;
    State* parent;
    string stateString;
    int distance;
    State();
    State(const string str, State * _parent, string _moveFromParent);
    State (const string str, string _moveFromParent);
    State(const string str, int dist, State * _parent, string _moveFromParent);
    ~State();

    bool operator<(const State & state) const;
    bool operator==(const State & state) const;
    int findBlank();
    vector<State> expandNode();
};

State.cpp:状态.cpp:

int manhattan(const string str);
tuple<int, int> getTarget(int n);

State::State() {}

State::State(const string str, State * _parent, string _moveFromParent) : stateString(str), moveFromParent(_moveFromParent) {
    parent = _parent;
}

State::State(const string str, string _moveFromParent) : stateString(str), moveFromParent(_moveFromParent) {
    parent = NULL;
    distance = manhattan(stateString);
}

State::State(const string str, int dist, State* _parent, string _moveFromParent) : stateString(str), distance(dist), moveFromParent(_moveFromParent) {
    parent = _parent;
    distance = manhattan(stateString);
}

State::~State() {}

bool State::operator<(const State & state) const {
    return distance > state.distance;
}

bool State::operator==(const State & state) const {
    return ((stateString == state.stateString));
}

int State::findBlank() {
    for (int i = 0; i < stateString.length(); ++i) {
        if (stateString[i] == '_') {
            return i;
        }
    }
}

vector<State> State::expandNode() {
    vector<State> returnStates;
    int blank = findBlank();
    if (blank % 3 > 0) { // can move left
        string newState = stateString;
        newState[blank] = newState[blank - 1];
        newState[blank - 1] = '_';
        int heuristic = manhattan(newState);
        State * childsParent = this;
        string move = "left";
        State temp = State(newState, heuristic, childsParent, move);
        returnStates.push_back(temp);
    }
    if (blank % 3 < 2) { //can move right
        string newState = stateString;
        newState[blank] = newState[blank + 1];
        newState[blank + 1] = '_';
        int heuristic = manhattan(newState);
        State * childsParent = this;
        string move = "right";
        State temp = State(newState, heuristic, childsParent, move);
        returnStates.push_back(temp);
    }
    if (blank / 3 > 0) { //can move up
        string newState = stateString;
        newState[blank] = newState[blank - 3];
        newState[blank - 3] = '_';
        int heuristic = manhattan(newState);
        State * childsParent = this;
        string move = "up";
        State temp = State(newState, heuristic, childsParent, move);
        returnStates.push_back(temp);
    }
    if (blank / 3 < 2) { // can move down
        string newState = stateString;
        newState[blank] = newState[blank + 3];
        newState[blank + 3] = '_';
        int heuristic = manhattan(newState);
        State * childsParent = this;
        string move = "down";
        State temp = State(newState, heuristic, childsParent, move);
        returnStates.push_back(temp);
    }
    return returnStates;
}

int manhattan(const string str) {
    int distance = 0;
    for (int i = 0, length = str.length(); i != length; ++i) {
        tuple<int, int> target;
        if (str[i] == '_') {
            target = { 2, 2 };
        }
        else {
            int temp = str[i] - '0';
            target = getTarget(temp);
        }
        tuple<int, int> current = getTarget(i + 1);
        int localSum = abs(get<0>(current) - get<0>(target)) + abs(get<1>(current) - get<1>(target));
        distance += localSum;
    }
    return distance;
}

tuple<int, int> getTarget(int n) {
    return { (n - 1) / 3, (n - 1) % 3 };
}

I'm having a problem where the pointer to the State member parent is changing when I expand more nodes.我遇到了一个问题,当我展开更多节点时,指向 State 成员父级的指针会发生变化。

State has a member variable State * parent. State 有一个成员变量 State * parent。 This is used to traverse back to the beginning after finding the solution in order to get the solution moves.这用于在找到解决方案后遍历回到开始以获得解决方案的移动。

After expanding the first node, the priority queue looks normal, with the parent of all nodes being the root node, whose parent is NULL.展开第一个节点后,优先级队列看起来正常,所有节点的父节点都是根节点,其父节点为NULL。 After a second node, however, the nodes in my priority queue are all pointing to the node that was just expanded!然而,在第二个节点之后,我的优先级队列中的节点都指向刚刚扩展的节点! These should be pointing to their individual parents, and should not be tied together.这些应该指向他们各自的父母,而不应该绑在一起。 I can't seem to find where I'm going wrong here and any help would be appreciated.我似乎无法找到我在这里出错的地方,任何帮助将不胜感激。 Thanks!谢谢!

The problem is in Greedy::doGreedy and your usage of current .问题在于Greedy::doGreedy和您对current的使用。

The assignment current = greedyQueue.top();赋值current = greedyQueue.top(); creates a copy of the top object in the queue.创建队列中顶部对象的副本。 Later, when you call vector<State> childrenFound = current.expandNode();后来,当你调用vector<State> childrenFound = current.expandNode(); , all the returned states have parent pointers that refer to current . ,所有返回的状态都有指向current父指针。 On the next loop iteration, you make that assignment to current again, changing the parent pointed to by all those returned states.在下一次循环迭代中,您再次将该分配分配给current ,更改所有这些返回状态指向的父级。

There isn't an easy fix with your code.您的代码没有简单的修复方法。 You need to rethink how you store State objects so that the parent objects stay around and unmodified.您需要重新考虑如何存储State对象,以便父对象保持不变且不被修改。 Often this sort of thing is done with a stack or list, adding each node to the end and popping them off to move up to the parent.通常这种事情是通过堆栈或列表完成的,将每个节点添加到末尾并将它们弹出以向上移动到父节点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM