在向量中存储二叉树 - 复制constr问题?

时间:2016-10-17 23:26:46

标签: c++ tree

我的代码遇到了node = 0xddddddddd问题。我相信我已经将它缩小到三个规则的问题而没有复制构造函数。我确实尝试创建一个复制构造函数,但我不确定我是否正确实现它。本质上,我正在创建节点,将它们存储在二叉树对象中,我将其存储在向量中。我是否需要一直创建一个复制构造函数?

Environment.cpp

void Environment::evolve() {
    std::cout << "> evolving function" << std::endl;
    std::vector<Tree> popvec;

    // Generate initial pop trees and store in vector
    std::cout << "> generating initial population" << std::endl;
    for (int i = 0; i <= Popsize-1; i++) {
        Tree membertree(Maxdepth);
        //popvec.push_back(membertree);
        popvec.emplace_back(membertree);
    } // <- A deconstructor is being called here that is causing the error
      // If I understand right it is destructing the copy from putting it
      // into the vector

Tree.cpp

// Constructor
Tree::Tree() {
    root = NULL;
    fitness = rand();
    depth = 0;

}

// Overload constructor
Tree::Tree(int maxdepth) {
    root = NULL;
    fitness = rand();
    depth = 0;
    while (TreeDepth(root) < maxdepth) {
        addNode(root);
    }

}

// Copy constructor
Tree::Tree(const Tree &obj, int maxdepth) {
    root = NULL;
    fitness = obj.fitness;
    depth = 0;
    while (TreeDepth(root) < maxdepth) {
        addNode(root);
    }
}

// Destructor
Tree::~Tree() {
    freeNode(root);
    root = NULL;
}

// Post traversal node deletion
void Tree::freeNode(Node* node) {
    if (node != NULL) {
        freeNode(node->left); // This is where the error pops up
        freeNode(node->right);
        delete node;
    }
}

// Adds a node to the tree
void Tree::addNode(Node* node) {
    if (root == NULL) {
        Node* temp = new Node();
        root = temp;
    }
    else if (node->left == NULL) {
        Node* temp = new Node();
        node->left = temp;
    }
    else if (node->right == NULL) {
        Node* temp = new Node();
        node->right = temp;
    }
    else if (node->left != NULL) {
        addNode(node->left);
    }
    else if (node->right != NULL) {
        addNode(node->right);
    }
}

编辑:有人要求树深度

int Tree::TreeDepth(Node* node) {
    if (node == NULL) {
        return 0;
    }
    int nLeft = TreeDepth(node->left);
    int nRight = TreeDepth(node->right);
    return (nLeft > nRight) ? (nLeft + 1) : (nRight + 1);
}

Node.cpp

Node::Node() {
    functiontype = 0;
    left = NULL;
    right = NULL;
    up = NULL;
}

// Do I need a copy constructor here as well?

Node::~Node() {

}

编辑:我似乎已经对此有所了解但是现在它似乎在尝试随机化向量时进一步失误

// Copy constructor
Tree::Tree(const Tree& obj) {
    fitness = obj.fitness;
    depth = obj.depth;
    if(obj.root == NULL){
        root = NULL;
    }
    else {
        copyTree(this->root, obj.root);
    }
}

void Tree::copyTree(Node * thisRoot, Node * sourceRoot) {
    if (sourceRoot == NULL)
    {
        thisRoot = NULL;
    }
    else
    {
        thisRoot = new Node;
        thisRoot->left = sourceRoot->left;
        thisRoot->right = sourceRoot->right;
        copyTree(thisRoot->left, sourceRoot->left);
        copyTree(thisRoot->right, sourceRoot->right);
    }
}

1 个答案:

答案 0 :(得分:0)

如果您使用:

popvec.emplace_back(Maxdepth);

而不是:

popvec.emplace_back(membertree);

然后,不应该调用复制构造函数。试着这样做。

修改

我没有太多时间,抱歉。

复制构造函数的正确函数签名为:

Tree::Tree(const Tree &obj)

实际上,你标记为复制构造函数的东西可能甚至都没有被调用。

您能提供TreeDepth所做的代码吗?

如果还有其他问题,请告诉我。

修改

我之前提供的功能没有用,我没有彻底检查,抱歉。

我测试了你的程序,我可以填充Tree s的向量。我所做的是将copyTree更改为:

void Tree::copyTree(Node *& thisRoot, Node * sourceRoot)
{
    if (sourceRoot == nullptr)
    {
        thisRoot = nullptr;
    }
    else
    {
        thisRoot = new Node;
        thisRoot->left = sourceRoot->left;
        thisRoot->right = sourceRoot->right;
        copyTree(thisRoot->left, sourceRoot->left);
        copyTree(thisRoot->right, sourceRoot->right);
    }
}

我所做的只是将thisRoot参数更改为Node*&。以前,更改thisRoot并未更改root,它只使指针本地指针指向新创建的节点。

我不知道fitnessdepth做了什么,但目前它们似乎毫无用处。