2015-10-14 56 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