2015-10-14 59 views
0

我已经编写了代码,试图解决传教士和食人族的问题,并已实施Node以保存信息在Node::arrNode::parent。这些由函数bfs返回时,将使状态处于最短路径。指针的元素保存为乱码

bfs返回时,它具有正确的编号parents。但是,当我在Visual Studio调试器中检查Node last时,我注意到它的parents.arr包含垃圾,即arr[0]=-858993460。但Node last具有正确的arr(问题的最终状态{0,0,1,3,3,0})。这些信息如何丢失?

node.h

#pragma once 
#include <array> 
class Node { 
public: 
    std::array<int, 6> arr; 
    Node *parent; 
    Node(std::array<int, 6> arr, Node *parent = NULL); 
    Node(); 
}; 

node.cpp

#include "Node.h" 

Node::Node(std::array<int, 6> arr, Node *parent) : arr(arr), parent(parent) {}; 
Node::Node(): parent(NULL) {}; 

的main.cpp

void applyMoves(queue<Node> &q, Node current_node, array<int, 3> moves) { 
    array<int, 6> arr = current_node.arr; 
    array<int, 3> left, right; 
    // apply valid moves to arr 
    // copy the arr to left and right and check if the move applied are valid 
    // if valid and no duplicates in the queue do proceed to the next lines below 
    Node n = Node(arr, &current_node); 
    q.push(n); 

} 

Node bfs(queue<Node> &q, array<array<int, 3>, 5> moves) { 
    while (!q.empty()) { 
     Node current = q.front(); 
     q.pop(); 

     if (achievedGoal(current.arr) == 1) { 
      return current; 
     } 
     for (const auto& move : moves) { 
      applyMoves(q, current, move); 
     } 
    } 
    Node n; 
    return n; 
} 

int main() { 
    array<int, 6> init_state{ 3,3,1,0,0,0 }; 
    array<array<int, 3>, 5> moves{ { {1,0,1}, {0,1,1}, {1,1,1}, {2,0,1}, {0,2,1} } }; 
    Node n = Node(init_state); 
    queue<Node> q; 
    q.push(n); 
    Node last = bfs(q, moves); 
} 
+0

请**您的问题与[mcve]或[SSCCE(Short,Self Contained,Correct Example)](http://sscce.org) – NathanOliver

+1

您的默认'Node'构造函数不会初始化'父母'(可能与你遇到的问题无关)。 – crashmstr

+1

另外,'applyMoves'按值取'current_node',然后使用它的地址。 – crashmstr

回答

1

我相信这个问题是

void applyMoves(queue<Node> &q, Node current_node, array<int, 3> moves) { 
    array<int, 6> arr = current_node.arr; 
    array<int, 3> left, right; 
    // apply valid moves to arr 
    // copy the arr to left and right and check if the move applied are valid 
    // if valid and no duplicates in the queue do line 31 and 32 
    Node n = Node(arr, &current_node); 
    q.push(n); 

} 

这里current_node是一个副本,您正在存储它的地址。当函数结束时,副本被销毁,现在你有一个悬挂指针。你应该可以通过参考current_node来修复它。

编辑:

您还可以在

Node bfs(queue<Node> &q, array<array<int, 3>, 5> moves) { 
    while (!q.empty()) { 
     Node current = q.front(); 
     q.pop(); 

     if (achievedGoal(current.arr) == 1) { 
      return current; 
     } 
     for (const auto& move : moves) { 
      applyMoves(q, current, move); 
     } 
    } 
    Node n; 
    return n; 
} 

在这里,您创建current这是一个当地的物体自动检测此相同的行为,并复制队列的前面进去,然后你会得到pop()的排在队列之外。所以当你使用这个父节点时,一切都很好,直到你移动到while循环的下一个迭代。一旦你这样做,current就会被销毁,这意味着所有指向它的东西现在都在摇摆不定。然后循环开始并创建一个新的current。如果这个对象是在我认为是的示例地方创建的,那么您所做的所有节点都将其父节点指向这个新节点。

他们的方式,你目前这样做是行不通的。我不太清楚你应该如何改变它以获得正确的行为。

+0

我改变了'applyMoves'来接受'Node&current_node',并像这样调用applyMoves(q,current,move);'但是,当我检查'Node last'时似乎是父母指向父母的“水平”。 – user2348707

+0

@ user2348707我已经更新了我的答案。不太清楚在算法接缝断裂时如何解决问题。 – NathanOliver

+0

感谢您的回答!现在我对这个问题有了更好的理解。我很快就用python对这个原型进行了原型设计,并且在C++上尝试了我的手,尽管代码几乎完全相同,但它们表现得非常不同。我将不得不尝试另一种方式来获得正确的行为。 – user2348707

0

由于我不能评论别人发布的帖子,我会根据以前的答案和我自己的回答。是的,以下功能:

void applyMoves(queue<Node> &q, Node current_node, array<int, 3> moves) { 
    array<int, 6> arr = current_node.arr; 
    array<int, 3> left, right; 
    // apply valid moves to arr 
    // copy the arr to left and right and check if the move applied are valid 
    // if valid and no duplicates in the queue do line 31 and 32 
    Node n = Node(arr, &current_node); 
    q.push(n); 

} 

需要参照采取CURRENT_NODE,因为否则,你是存储地址,一个局部变量,执行超出函数范围,之后将被销毁。

但是,不仅如此,但在这里:

Node current = q.front(); 
    q.pop(); 

正在制作的第一个元素的副本在队列中,并将其保存到一个局部变量,当你将它传递到所描述的功能上面(即使它是通过引用完成的),您仍然遇到同样的问题,因为您正在存储局部变量的地址(不同函数的局部变量,但仍然是 - 同样的问题)。而且,根据所发布的逻辑,我不清楚,正确的解决方案是什么,但至少你有“为什么?”回答。

编辑:显然原来的海报打败了我与他的编辑答案。

+0

谢谢! “为什么”回答比没有好。至少我学到了一些东西。 – user2348707