2015-11-01 117 views
1

t.PreorderTraversal(t, &t.getRoot());該錯誤正在接受「節點」類型的臨時對象的地址。 Root是一個Node類對象。函數PreoderTraversal將Node對象作爲一個點,所以我給出Node對象的地址併發生錯誤。這不是正確的做法嗎?以「節點」類型的臨時對象的地址爲例

class NodeList; 

class Node { 
private: 
    Node* parent; 
    int elem; 
    NodeList* children; 
    Node *next; 
    Node *prev; 

}; 

class NodeList { 
public: 
    NodeList(); 
    void addNodeAtRank(int, int); 
private: 
    Node* header; 
    Node* tailer; 
}; 

class Tree { 
private: 
    int n; 
    Node root; 
public: 
    Tree(); 
    void addNode(Tree &t, int, int, int); 
    void PreorderTraversal(const Tree& t, Node* p); 
    void PostorderTraversal(const Tree& t, Node* p); 
    void printXYofNode(const Tree& t, int nodeNumber); 
    Node getRoot(); 
    Node* getNodeByElem(Node& n, int); 
}; 

Node::Node() { 

    children = nullptr; 
    parent = nullptr; 
    elem = 0; 
    next = nullptr; 
    prev = nullptr; 

} 

NodeList::NodeList() { 

    header = new Node(); 
    tailer = new Node(); 

    header->next = tailer; 
    tailer->prev = header; 
} 

void NodeList::addNodeAtRank(int rank, int e) { 

    Node *v = new Node(); 
    v->elem = e; 

    int count = 1; 
    Node *NodeAtRank = header->next; 

    while (count != rank) { 
     NodeAtRank = NodeAtRank->next; 
     count++; 
    } 

    v->next = NodeAtRank; 
    v->prev = NodeAtRank->prev; 
    NodeAtRank->prev = v; 
    NodeAtRank->prev->next = v; 

} 

bool NodeList::empty() const { 
    return header->next == tailer; 
} 

Tree::Tree() { 

    n = 0; 
    //root = Node(); 
} 

void Tree::addNode(Tree& t, int NodeElement, int ParentNode, int SiblingOrder) { 

    //Node *treeNode = new Node(); 

    if (t.empty() && ParentNode == -1 && SiblingOrder == -1) { 
     t.root = Node(); 
     t.root.elem = NodeElement; 
     t.root.children = new NodeList(); 
    } else { 

     Node* nodeParent = t.getNodeByElem(t.root, ParentNode); 

     NodeList *childrenNodelist = nodeParent->children; 
     childrenNodelist->addNodeAtRank(SiblingOrder, NodeElement); 

     nodeParent->children = childrenNodelist; 
    } 

    n++; 
} 

Node* Tree::getNodeByElem(Node& root, int nodeElem) { 

    if (root.elem == nodeElem) 
     return &root; 
    else { 
     NodeList *rootChildren = root.children; 

     Node *head = rootChildren->header; 

     while (head->next != rootChildren->tailer) { 

      if (!head->next->isExternal()) 
       return getNodeByElem(*(head->next), nodeElem); 
      else { 
       if (head->next->elem == nodeElem) 
        return head->next; 

       head = head->next; 
      } 
     } 

     return new Node(); 
    } 
} 

void Tree::PreorderTraversal(const Tree& t, Node* p) { 

    cout << p->elem; 
    NodeList *mychildren = p->children; 
    Node *traversal = mychildren->header->next; 

    while (traversal != mychildren->tailer) { 
     cout << " "; 
     PreorderTraversal(t, traversal->next); 
     traversal = traversal->next; 
    } 

} 

void Tree::PostorderTraversal(const Tree& t, Node* p) { 

    NodeList *mychildren = p->children; 
    Node *traversal = mychildren->header->next; 

    while (traversal != mychildren->tailer) { 
     PreorderTraversal(t, traversal); 
     traversal = traversal->next; 
    } 
    cout << p->elem; 
} 

bool Tree::empty() const { 
    return n == 0; 
} 

int Tree::size() const { 
    return n; 
} 

Node Tree::getRoot() { 
    return root; 
} 

int main(int argc, const char * argv[]) { 

    char Type = NULL; 
    int nodeNumber = 0; 
    int nodeParent = 0; 
    int nodeOrderInSibling = 0; 

    Tree t = Tree(); 
    cin >> Type; 
    while (Type != 'Q') { 
     if (Type == 'I') { 
      cin >> nodeNumber >> nodeParent >> nodeOrderInSibling; 
      t.addNode(t, nodeNumber, nodeParent, nodeOrderInSibling); 
     } else if (Type == 'P') { 
      t.PreorderTraversal(t, &t.getRoot()); 
     } else if (Type == 'T') { 
      t.PostorderTraversal(t, &t.getRoot()); 
     } else if (Type == 'C') { 
      cin >> nodeNumber; 
      t.printXYofNode(t, nodeNumber); 
     } else { 
      cout << "Wrong input type!!!" << endl; 
     } 

     cin >> Type; 
    } 

    return 0; 
} 
+0

考慮縮進你的代碼好一點,現在很難閱讀。 –

+0

你遍歷函數的原型很奇怪。爲什麼你將Tree對象的const引用作爲參數?這要求您在呼叫期間指定對象*兩次*。 't.PreorderTraversal(t,&t.getRoot()); t.PostorderTraversal(t,&t.getRoot());' 「this」是C++中的一個隱式參數,所以我認爲這會更有意義或者省略Tree參數(因爲它不是必需的),或者聲明功能與靜態一樣。 – tweej

回答

0

編譯器錯誤是完全正確的。你取臨時地址(這是違反標準的)。 Tree :: getRoot()返回一個副本的類節點,所以& t.getRoot()是臨時地址。我認爲你的意思是從getRoot()返回一個指針。其語法是:

Node * getRoot(); 
1

這個函數返回一個複製Node對象是Tree

Node getRoot(); 

所以在這行你得到這個對象的地址成員之後會被丟棄。

t.PreorderTraversal(t, &t.getRoot()); 

您留下的指針稱爲懸空指針,因爲它沒有指向有效的對象。

考慮修改getRoot這樣

Node* Tree::getRoot() { 
    return &root; 
} 

當然,你必須確保在您使用該指針

0

更改Root對象不出去範圍:

Node Tree::getRoot() { 
    return root; 
} 

至:

Node& Tree::getRoot() { 
    return root; 
} 

否則&t.getRoot() - 正在返回的臨時對象的地址是 未定義的行爲 非法。

+0

+ 1用於指導他在這種情況下代替指針,而是-1,因爲它不是未定義的行爲。這是非法的。 – tweej

+0

@tweej固定,謝謝指出 – marcinj