简体   繁体   中英

C++ Tree pointer issues

I have an issue with binary search tree pointers and cannot determine the cause. I have a function in which I take two trees and exchange two subtrees of the trees at predetermined positions. This is the code that makes said exchange.

opNode* tmp = new opNode();
opNode* tmp2 = new opNode();
tmp = this->clone();
tmp2 = secondParentNode->clone();
this->operation = tmp2->operation;
this->val = tmp2->val;
this->lChild = tmp2->lChild;
this->rChild = tmp2->rChild;
secondParentNode = tmp;

At this point I have already determined the position of each subtree to be exchanged. The "this" pointer represents the first exchange point and secondParentNode is an opNode pointer that represents the second.

There are two issues here:

The first is that the exchange can create a situation in which a node has only one child. I have been unsuccessful in identifying how this is happening.

Second, and perhaps a relevant bit of information, once this->lChild is set to tmp2->lChild and this->rChild = tmp2->rChild, I had inserted a check as to whether secondParentNode->lChild or secondParentNode->rChild were null. This causes a segfault at least somewhat consistently.

Is the clone(deep copy) function not working? If so, why not? Any thoughts about what could be causing these issues would be appreciated.

opNode is my node class:

struct opNode
{
    string operation;
    double val;
    opNode* lChild;
    opNode* rChild;
    opNode* clone();
};

and the relevant clone function:

opNode* opNode::clone()
{
    if(this != nullptr)
    {
        opNode* n = new opNode();
        n->val = val;
        n->operation = operation;
        n->rChild = rChild->clone();
        n->lChild = lChild->clone();
        return n;
    }
    return nullptr;
}

EDIT* As requested, the exchange function. randPoint1 and randPoint2 are determined by taking a uniform distribution :

uniform_int_distribution<int> dist(0, mate[k].root->count(0) - 1);

Where mate[k] is a root tree pointer and count is defined as:

int opNode::count(int c)
{
    if(this != nullptr)
    {
        c++;
        if(lChild != nullptr)
            c += lChild->count(0);
        if(rChild != nullptr)
            c += rChild->count(0);
        return c;
    }
    return 0;
}

The exchange function:

void opNode::recombination(opNode*& secondParentNode, int& randPoint1, int& randPoint2, bool& done)
{
    if(done)
        return;
    if(secondParentNode != nullptr && !done)
    {
        if(randPoint2 > 0 && secondParentNode->lChild != nullptr)
        {
            randPoint2--;
            recombination(secondParentNode->lChild, randPoint1, randPoint2, done);
        }

        if(randPoint2 > 0 && secondParentNode->rChild != nullptr)
        {
            randPoint2--;
            recombination(secondParentNode->rChild, randPoint1, randPoint2, done);
        }
    }
    if(this != nullptr && randPoint2 == 0 && !done)
    {
        if(randPoint1 > 0 && lChild != nullptr)
        {
            randPoint1--;
            lChild->recombination(secondParentNode, randPoint1, randPoint2, done);
        }
        if(randPoint1 > 0 && rChild != nullptr)
        {
            randPoint1--;
            rChild->recombination(secondParentNode, randPoint1, randPoint2, done);
        }
    }
    if(this != nullptr && secondParentNode != nullptr && randPoint1 == 0 && randPoint2 == 0 && !done)
    {
        opNode* tmp = new opNode();
        opNode* tmp2 = new opNode();
        tmp = this->clone();
        tmp2 = secondParentNode->clone();
        this->operation = tmp2->operation;
        this->val = tmp2->val;
        this->lChild = tmp2->lChild;
        this->rChild = tmp2->rChild;
        secondParentNode = tmp;
    }
}

If rChild or lChild are nullptr , then the calls rChild->clone(); or lChild->clone() will cause segmentation fault.

We can rewrite the function as:

void opNode::clone(opNode* n)
{
    if (n)
    {
        n->val = val;
        n->operation = operation;
        if (rChild)
        {
            if (n->rChild)
            {
                 // release all right children.
            }
            n->rChild = new opNode;
            clone(n->rChild);
        }

        if (lChild)
        {
            if (n->lChild)
            {
                 // release all left children nodes.
            }
            n->lChild = new opNode;
            clone(n->lChild);
        }
    }
}

The code of exchange can be simplified as following:

opNode* tmp = new opNode;
clone(tmp);
secondParentNode->clone(this);
tmp->clone(secondParentNode);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM