Search code examples
c++c++17binary-tree

Is there any flaw in binary tree destructor algorithm


#include <bits/stdc++.h>
#define vi vector<int>

using namespace std;


class node{
    public:
        int data;
        node *left;
        node *right;

        node(){
            data = 0;
            left = right = nullptr;
        }

        node(int data){
            this->data = data;
            left = right = nullptr;
        }
};

class BT{
public:
    node *root{nullptr};
public:
    BT(){
        root = nullptr;
    }
    BT(const vi& v){
        // create a pair with initial state 0 and having root node in it
        stack<pair<node*,int> > st;
        root = new node(v[0]);
        pair<node*,int> p(root,0);
        st.push(p);

        int idx = 1;

        while(idx < v.size())
        {
            pair<node *,int> p = st.top();
            int state = p.second;
            int val = v[idx];

            if(state == 2)
            {
                st.pop();
                continue;
            }

            if(val == -1)
            {
                // will think for here
                // p.second++;
                st.top().second++;
                idx++;
                continue;
            }

            // Now the value is not -1 and state is not 2

            node *newNode = new node(val);

            if(state == 0)
            {
                st.top().first->left = newNode;
                // p.first->left = newNode;
            }else{
                st.top().first->right = newNode;
                // p.first->right = newNode;
            }

            st.top().second++;
            st.push(pair<node*,int>(newNode,0));
            idx++;

        }
    }

    friend ostream& operator<<(ostream& os,BT& b){
        b.printHelper(b.root,os);
        return os;
    }

    void printHelper(node *root,ostream& os){
        if(root == nullptr)
            return;

        if(root->left != nullptr)
            os << (root->left)->data;
        os <<  " <- " << root->data << " -> ";

        if(root->right != nullptr)
            os << root->right->data;
        os << endl;
        printHelper(root->left,os);
        printHelper(root->right,os);
    }


    void levelOrderLineWise(){
        queue<node*> mq;
        queue<node*> hq;

        mq.push(root);

        while(!mq.empty())
        {
            node *removed = mq.front();

            cout << removed->data << " ";

            mq.pop();

            if(removed->left != nullptr)
                hq.push(removed->left);
            if(removed->right != nullptr)
                hq.push(removed->right);

            if(mq.empty())
            {
                cout << endl;
                mq.swap(hq);
            }
        }
    }


};

void destruct(node *root)
{
    if(root == nullptr)
    {
        return;
    }
    if(root->left != nullptr)
    {
        destruct(root->left);
        root->left = nullptr;
    }
    if(root->right != nullptr)
    {
        destruct(root->right);
        root->right = nullptr;
    }
    
    delete root;
}

int main(){
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    /**
     *  Tree diagram
     *      50
     *     /  \
     *    25   75
     *   / \   / \ 
     *  12 37 62  87
     *      /  \
     *     30  70
     */
    vi v = {50,25,12,-1,-1,37,30,-1,-1,-1,75,62,-1,70,-1,-1,87,-1,-1};
    
    BT b(v);
//  b.levelOrderLineWise();
            
    destruct(b.root);
            
    if(b.root != nullptr)
    {
        cout << "root is still there" << endl;
    }else{
        cout << "tree destroyed" <<endl;
    }
    
    
    if(b.root->left != nullptr)
    {
        cout << "It is still there";
    }else{
        cout << "completed";
    }

    return 0;
}

INFO ABOUT CODE

This is the code for creating a binary tree,we have a class called node which has a data and two pointers to its children left & right.

The constructor takes a vector v and creates the tree using the elements of the vector in the preorder fashion.

Then I have a function levelOrderLineWise in the class BT which prints the tree in line wise fashion.

The function destruct is supposed to destroy the tree. The algorithm takes the root of the tree and destroys the left child(if it is not nullptr) and then makes left child of root equal to nullptr. Similarly, I have destroyed the right child(If it is present) and then made the right child of root equal to nullptr.

I get that this algorithm would not make the root of the tree nullptr but i expect it to make root->left and root->right equal to nullptr. But to my disappointment i am not getting the desired output.

Is there any flaw in my logic? If no,then why is it that i am getting the message It is still there?

Any help would be appreciated.

EDIT

Basically, I get what @john is saying, i should not have included the conditions if(root->left != nullptr) and if(root->right != nullptr).

so this would translate something like this

void destruct(node *root)
{
    if(root == nullptr)
        return;

    destruct(root->left);
    // root->left = nullptr;
    destruct(root->right);
    // root->right = nullptr;
    delete root;
}

But I still dont get why is there not a need for the conditions root->left = nullptr and root->right = nullptr

reason why i think so they are necessary

From what i know is that whenever you deallocate the memory pointed by a pointer you must also set that pointer to nullptr.


Solution

  • It could be a lot simpler

    void destruct(node *root)
    {
        if(root == nullptr)
            return;
        destruct(root->left);
        destruct(root->right);
        delete root;
    }
    

    does exactly the same as your code.

    root->left and root->right cannot have any defined value after delete root; so I'm not sure what you are expecting.