Binary search Tree Seg faults when doing a tree walk after removing its root

-1

I've been stepping through my functions using pieces of paper to see what happens when I try to remove the very first Node and then print it. Lets assume these are the elements already in the tree (depth, key, data). WARNING/// WALL OF TEXT AHEAD!

1, 09/17, Paul
0, 10/24, Jen

I then call my remove function to remove the tree's root (Jen) and everything seems to be okay. This is what the print function should have outputted:

print
0 9/17 Paul

However it instead segfaults and outputs:

print
0 p▒ p▒ ▒ ▒ ▒#a▒#a$▒#a$▒#ah▒ ... (goes on for a while)
      0 [main] BST 6176 exception::handle: Exception: STATUS_ACCESS_VIOLATION
354 [main] BST 6176 open_stackdumpfile: Dumping stack trace to BST.exe.stackdump

Using GDB I type in 'where' hoping to find what line the problem occurs at in my code and I get unworldly responses:

    Program received signal SIGSEGV, Segmentation fault.
0x611298c5 in memchr () from /usr/bin/cygwin1.dll
(gdb) where
#0  0x611298c5 in memchr () from /usr/bin/cygwin1.dll
#1  0x779d34e3 in OutputDebugStringA ()
   from /cygdrive/c/Windows/syswow64/KERNELBASE.dll
#2  0x40010006 in ?? ()
#3  0x00000000 in ?? ()
(gdb)

I was hoping It would tell me why it segfaults but I have no Idea where it could be. Ill put some source code below (note: the entire program works except for the removing part in some instances.) I had the program sometimes just abruptly end or terminate with Aborted(core dumped). And the tree walk always works I have inserted thousands of elements and it would always perfectly output them. Here are the classes below: Node.h

#ifndef NODE_H_INCLUDED
#define NODE_H_INCLUDED

#include <iostream>
#include <string>

using namespace std;

//class BST;
class Node
{
public:
    Node(string key, string data)
    {m_key = key; m_data = data;}
    ~Node(){
       delete m_left;
       delete m_right;
    }
    friend class BST;
private:
    string m_key;
    string m_data;
    Node *m_left;
    Node *m_right;
    Node *m_parent;
};


#endif // NODE_H_INCLUDED

BST.h

#ifndef BST_H_INCLUDED
#define BST_H_INCLUDED

#include <iostream>
#include <string>

using namespace std;
class Node;
class BST
{
public:
    BST()
    {m_root = NULL;}
    ~BST();
    void insert(string key, string data);

    void find(string key);
    Node* TREE_SEARCH(Node* ptr, string key);

    void remove(string key, string data);
    void TREE_DELETE(Node* ptr);
    void TRANSPLANT(Node* ptr, Node* ptr);
    Node* TREE_MINIMUM(Node* ptr);

    void print();
    void IN_ORDER_TREE_WALK(Node* ptr, int depth);
    //friend class Node;
private:
    Node* m_root;

};

#endif // BST_H_INCLUDED

Here is BST.cpp (note i did not include any functions that already work in my program in the post I am making. Also to make it easier to read I will just show the destructor and all the functions that are needed to delete a node.): BST.cpp

#include "BST.h"
#include "Node.h"
BST::~BST()
{
    delete m_root;
    m_root = NULL;
}
Node* BST::TREE_SEARCH(Node* ptr, string key)
{
    //if(ptr != NULL)
        //cout << "SEARCHING: " <<ptr->m_key<<", " << ptr->m_data << endl;
    if(ptr == NULL || ptr->m_key == key)
        return ptr;
    if(key < ptr->m_key)
        return TREE_SEARCH(ptr->m_left, key);
    else return TREE_SEARCH(ptr->m_right, key);
}
void BST::remove(string key, string data)
{
    //cout << "preparing to remove..." << endl;
    Node* ptr = m_root;
    //if(m_root)
    Node* tmp = TREE_SEARCH(ptr, key);
    while(tmp != NULL)
    {
        if(tmp->m_data == data)
        {
            cout << "DELETE: " << tmp->m_key << ", " << tmp->m_data << endl << endl;
            TREE_DELETE(tmp);
            //Node* del = tmp;
            //delete del;
            delete tmp;
            return;
            //tmp = NULL;
        }
        else
        {
            cout << "Iterating" << endl;
            tmp = tmp->m_right; //this is the issue
        }
    }
}
void BST::TREE_DELETE(Node* z)
{
    //cout << "Changing pointers" << endl;
    if(z->m_left == NULL)
        TRANSPLANT(z, z->m_right);
    else if(z->m_right == NULL)
        TRANSPLANT(z, z->m_left);
    else
    {
        Node* y = TREE_MINIMUM(z->m_right);
        if(y->m_parent != z)
        {
            TRANSPLANT(y, y->m_right);
            y->m_right = z->m_right;
            y->m_right->m_parent = y;
        }
        TRANSPLANT(z, y);
        y->m_left = z->m_left;
        if(y->m_left != NULL)// I added this
            y->m_left->m_parent = y;
    }


}
void BST::TRANSPLANT(Node* u, Node* v)
{
    //cout << "TRANSPLANT" << endl;
    if(u->m_parent == NULL)
    {
        m_root = v;
    }
    else if(u == u->m_parent->m_left)
    {
        u->m_parent->m_left = v;
    }
    else
    {
        u->m_parent->m_right = v;
    }
    if(v != NULL)
    {
        v->m_parent = u->m_parent;
    }
}

Node* BST::TREE_MINIMUM(Node* x)
{
    //cout << "GET MIN" << endl;
    //x = m_root;
    while(x->m_left != NULL)
        x = x->m_left;
    return x;
}

I'll explain to the best of my ability how all of these functions work. We start out in int main() where we will call remove(key, data) [we pass in both a key and data which will be put into a node in the tree]. Once in remove we will set a pointer to point to m_root and call the search function (which works perfectly, I tested it with a function that finds elements in the tree but doesn't delete them). This function will return a pointer to the element that we want to delete. Note: for this assignment (calendar assignment) There can be multiple things on each date (10/24) so I will have to transverse to the right until I find the data I am looking for (Jen). Once the Node is found containing the correct data and keys I will then call TREE_DELETE(tmp) whose job is to get all the pointers in the other nodes in the tree pointing in the right direction. In order to do this we will call TRANSPLANT (pass in 2 node pointers) to help with setting the nodes. I have stepped through these algorithms several times and I still cannot find out why the program terminates or seg faults when I try to delete some elements. FINAL NOTE (I got all of these algorithms out of my textbook, so they (in theory) should work perfectly.)

c++
algorithm
binary-search-tree
destructor
delete-operator
asked on Stack Overflow Nov 28, 2013 by user3040019 • edited Aug 27, 2015 by Brian Tompsett - 汤莱恩

1 Answer

0

The reason the print function would seg fault was because when i called delete on that certain pointer it would delete EVERYTHING underneath it. my solution was: [thanks again john]

void BST::remove(string key, string data)
{
    Node* ptr = m_root;
    Node* tmp = TREE_SEARCH(ptr, key);
    while(tmp != NULL)
    {
        if(tmp->m_data == data)
        {
            TREE_DELETE(tmp);
            tmp->m_parent = NULL;
            tmp->m_right = NULL;
            tmp->m_left = NULL;
            delete tmp;
            return;
        }
        else
        {
            tmp = tmp->m_right;
        }
    }
}
answered on Stack Overflow Nov 28, 2013 by user3040019

User contributions licensed under CC BY-SA 3.0