문제

The problem I am having is that my tree can only delete a node successfully ONE time only. When I try to have it delete more, it will crash with a segmentation fault (core dumped) error. I can't seem to pintpoint the exact place where it is faulting, but it SHOULD be something I am doing wrong with the memory allocation and deallocation, i just can't see it.

Here is my insert, remove, remove helper, and leaf (because it is called inside remove):

insert:

/*********************************************************
 Function: insert
 Arguments: const T &x (a T variable)
 Returns: void
 Notes: If the tree is empty, the function will set the node 
    as the root. Otherwise, it will look for the appropiate 
    place (in terms of a BST) to place it as long as its data 
    is not already existent inside the tree. 
*********************************************************/
template<class T> void binSTree<T>::insert(const T &x)
{
    BinTreeNode *newnode, *current, *parentOfCurrent; /* newnode will be the inserted node, current and parentOfCurrent will be traversing the while loop to find an appropiate space to insert */
    newnode = new BinTreeNode; /* allocates storage space */
    newnode->info = x; /* sets newnode's data equal to x */
    newnode->left = newnode->right = NULL; /* sets newnode's left and right children equal to NULL */

    if (root == NULL)   { /* if the tree is empty, it will place newnode on the root */
        root = newnode;
        cout << "added to root\n";
        return;         }
    current = root; /* sets current at the root */
    while(current != NULL)  { /* while current is not NULL, it will search for a place to insert the new node */
    parentOfCurrent = current; /* sets the parent equal to current */ 
        if(current->info == x) /* if the variable is found inside the tree, then it will error and exit */
        {
            cout << x << " already exists in tree. Duplicates not allowed!\n";
            return;
        }
        else if(current->info > x) /* otherwise, if the variable is less than the data on the tree currently, it will move left */ 
            current = current->left; 
        else                       /* otherwise, if the variable is greater than the data on the tree currently, it will move right */          current = current->right;
                            }
    /* the new node is placed where current would be in */ 
    if (parentOfCurrent->info > x) 
        parentOfCurrent->left = newnode;
    else
        parentOfCurrent->right = newnode;
}

remove and privRemove:

template <class T> bool binSTree<T>::remove(const T &x)
{
    BinTreeNode *current, *parentOfCurrent; /* current for tranversing the tree in the while loop and parentofCurrent to help */
    bool found = false; /* the booleans that is to be returned */
    if (root == NULL)   { /* Checks if the tree is empty, if it is, it returns found (false) and exits */
        return found;
                        }
    current = root; /* sets current equal to root */ 
    while(current != NULL) /* loops repeats until current is equal to NULL */
    {
        if(current->info == x)  { /* if the current data from the tree is equal tox, then it breaks the loop and sets found equal to true */
            found = true;
            break;
                                }
        else    { /* otherwise, it will search for the next place to go in the tree */
            parentOfCurrent = current; /* parentOfCurrent is set to current before current is set to one of its children */ 
            if(current->info > x) /* if x is less than the data on current, then it will move left */
                current = current->left;
            else   /* if x is greater than the data on current, then it will move right */
                current = current->right;
                }
    }
    if(found == true) { /* if it was found, it will pass current via the parent to the private remove function */ 
        if (current == root)
            privRemove(root);
        else if (parentOfCurrent->info > x) {  /* if current is to the left of the parent */
            found = leaf( parentOfCurrent->left );
            if(found == true)
                privRemove(parentOfCurrent->left);
                                            }
        else {  /* if current is to the right of the parent */
            found = leaf( parentOfCurrent->left );
            if(found == true)
                privRemove(parentOfCurrent->right);
             }
                      }
    return found;
}
/*********************************************************
 Function: privRemove
 Arguments: BinTreeNode* &node (the node that is to be deleted)
 Returns: void
 Notes: This private remove function will take in the node that 
    is provided by the public remove function, and, after ensuring
    that the node passed is not NULL, then it will delete it.
*********************************************************/
template <class T> void binSTree<T>::privRemove(BinTreeNode* &node) 
{
    BinTreeNode *temp; /* initializes temp in order to hold the information of node */ 
    if(root != NULL )  /* if the node is not NULL */
    {
        temp = node;
        delete node;
        node = temp;
    }
}

leaf:

/*********************************************************
 Function: leaf
 Arguments: BinTreeNode* node
 Returns: boolean
 Notes: This function will check if the node in the argument 
  is a leaf by checking if both of its children are NULL. If 
  they are, it returns true. Otherwise, it returns false. 
*********************************************************/
template <class T> bool binSTree<T>::leaf(BinTreeNode* node) const
{
    bool isLEaf = false; /* the boolean variable it is to return */ 
    if(node->left == NULL && node->right == NULL) /* checks if the node has no children */
        isLEaf = true;  /* if it does, it sets isLEaf equal to true */
    return isLEaf;  /* after going through the if statement, it returns the variable isLeaf */
}

It should be noted that my nodes are structs declared within the class header and that the variable root is declared as a protected variable in the form BinTreeNode* root; it is initialized as NULL inside the binSTree constructor. Also, I am only allowed to delete leaves.

도움이 되었습니까?

해결책

what it seems to me that you're doing wrong is inside privRemove method... Imagine you've tried to delete a node and privRemove gets called on that node.

with:

delete node;

you free the memory node points to.

then you reassign node to the value it had before with:

node=temp;

so it now points to the same location as before (inside and outside of your function because you passed it by reference).

Now on the next remove you will eventually come across that same node and test if it is NULL, but it is not since you gave it a value so it points to the memory it had before (node=temp), so the node points to somewhere in the memory that is not NULL so you'll think it's a legit node but it is not, it points to memory already freed. And when you call a method on it...bhumm!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top