2015-11-01 37 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