Binary Search Tree issue

Go To StackoverFlow.com

1

I am really stuck, I'm getting an error at "CTree.add(num);" saying 'CTree' is undeclared, which doesn't make sense because I initialized it in tree.h?

The program is supposed to prompt the user, the user enters a command (i.e. "add 3", only 0-9 integers) and then I want it to insert that number into the tree.

//File: tree.h

class CTree
{
private:
    CTree* m_pLeft;
    CTree* m_pRight;
    CTree* m_pRoot;
    int m_nData;

public:

    CTree();

    bool isEmpty() const { return m_pRoot; }
    bool search(int);
    void print_inorder();
    void inorder(CTree*);
    void Add(int);
    void remove(int);
    void height();
};

//File: CTree.cpp

#include <iostream>
#include <cstdlib>

using namespace std;

CTree::CTree()
{
 m_pRoot=NULL;
}

bool CTree::search(int x)
{
    if(x==m_nData) return true;
    if(x < m_nData){ //go left
       if(m_pLeft != NULL) //if possible
            return m_pLeft->search(x);
    }
    else //go right
       if(m_pRight != NULL) //ifpossible
            return m_pRight->search(x);
    return false;
}

void CTree::Add(int x)
{
CTree* t = new CTree;
CTree* parent;
t->m_nData = x;
t->m_pLeft = NULL;
t->m_pRight = NULL;
parent = NULL;

if(isEmpty()) m_pRoot = t;
else
{
     //insert leaf nodes
    CTree* leaf;
    leaf = m_pRoot;
     // find parent
    while(leaf)
    {
        parent = leaf;
        if(t->m_nData > leaf->m_nData)
            leaf = leaf->m_pRight;
        else
            leaf = leaf->m_pLeft;
    }

    if(t->m_nData < parent->m_nData)
       parent->m_pLeft = t;
    else
       parent->m_pRight = t;
}
}

void CTree::remove(int x)
{
bool found = false;
if(isEmpty())
{
    cout<< "Tree is empty!" <<endl;
    return;
}

CTree* current;
CTree* parent;
current = m_pRoot;

while(current != NULL)
{
     if(current->m_nData == x)
     {
        found = true;
        break;
     }
     else
     {
         parent = current;
         if(x > current->m_nData) current = current->m_pRight;
         else current = current->m_pLeft;
     }
}
if(!found)
{
    cout<< "Not found!" <<endl;
    return;
}

// Node with single child
if((current->m_pLeft == NULL && current->m_pRight != NULL)|| (current->m_pLeft != NULL&& current->m_pRight != NULL))
{
   if(current->m_pLeft == NULL && current->m_pRight != NULL)
   {
       if(parent->m_pLeft == current)
       {
         parent->m_pLeft = current->m_pRight;
         delete current;
       }
       else
       {
         parent->m_pRight = current->m_pRight;
         delete current;
       }
   }
   else // left child present, no right child
   {
      if(parent->m_pLeft == current)
       {
         parent->m_pLeft = current->m_pLeft;
         delete current;
       }
       else
       {
         parent->m_pRight = current->m_pLeft;
         delete current;
       }
   }
 return;
}

             //We're looking at a leaf node
             if( current->m_pLeft == NULL && current->m_pRight == NULL)
{
    if(parent->m_pLeft == current) parent->m_pLeft = NULL;
    else parent->m_pRight = NULL;
                             delete current;

//Node with 2 children
// replace node with smallest value in right subtree
if (current->m_pLeft != NULL && current->m_pRight != NULL)
{
    CTree* check;
    check = current->m_pRight;
    if((check->m_pLeft == NULL) && (check->m_pRight == NULL))
    {
        current = check;
        delete check;
        current->m_pRight = NULL;
    }
    else // right child has children
    {
        //if the node's right child has a left child
        // Move all the way down left to locate smallest element

        if((current->m_pRight)->m_pLeft != NULL)
        {
            CTree* lcurrent;
            CTree* lcurrent_parent;
            lcurrent_parent = current->m_pRight;
            lcurrent = (current->m_pRight)->m_pLeft;
            while(lcurrent->m_pLeft != NULL)
            {
               lcurrent_parent = lcurrent;
               lcurrent = lcurrent->m_pLeft;
            }
            current->m_nData = lcurrent->m_nData;
            delete lcurrent;
            lcurrent_parent->m_pLeft = NULL;
       }
       else
       {
           CTree* tmp;
           tmp = current->m_pRight;
           current->m_nData = tmp->m_nData;
           current->m_pRight = tmp->m_pRight;
           delete tmp;
       }

    }
             return;
}
}
}

void CTree::print_inorder()
{
 inorder(m_pRoot);
}

void CTree::inorder(CTree* x)
{
  if(x != NULL)
{
    if(x->m_pLeft) inorder(x->m_pLeft);
    cout<<" "<<x->m_nData<<" ";
    if(x->m_pRight) inorder(x->m_pRight);
}
else return;
}

//File: main.cpp

#include <iostream>
#include <cstdlib>
#include <sstream>
#include <locale>
#include <string>
#define PROMPT "bst> "

using namespace std;

int getNumber(string s)
{
    int num;

for(int i; i<=s.length();i++)
{
        if(isdigit(s[i]))
        {
              num= s[i]-48;
        }
}

return num;
} // getNumber

bool process(const string& s, CTree* aTree)
{
    bool mustquit=false;
    int num;
    istringstream iss(s);

do
{
    string sub;
    iss >> sub; //               
    if(sub=="add" || sub=="insert")
    {
        num=getNumber(s);
        cout<<num<<endl;
        aTree->Add(num);
    }
    else if(sub=="delete" || sub=="remove")
    {
        num=getNumber(s);
        cout<<num<<endl;
    }
    else if(sub=="search" || sub=="find")
    {
         num=getNumber(s);
         cout<<num<<endl;
    }
    else if(sub=="height")
    {
         //do stuff
    }
    else if (sub=="quit") 
        return mustquit;
    //else cout<<"INPUT ERROR"<<endl;    
 }  while (iss);     




 return mustquit;
 }// process


int main(){ 

string input="";
CTree *myTree;
myTree = new CTree();

bool finished=false;
int i;


    cout<<PROMPT;
    while(!finished)
    {
            if(input!="")cout<<PROMPT;
            getline(cin,input);
            finished=process(input, myTree);
            delete myTree;
    }//while

return 0;
}
2012-04-05 00:49
by conman
you never actually create an instance of CTree you are just declaring the name of the variable in your header file, not instantiating one - Hunter McMillen 2012-04-05 00:53


5

add is a non-static member function, which means you can only call it on an instance of CTree. e.g.

CTree myTree;
myTree.add(num);
2012-04-05 00:52
by Oliver Charlesworth
This didn't work for me unfortunately. I see what you mean though. Now I'm getting the error at initializing "CTree myTree;" - conman 2012-04-05 01:26


1

You are aware that you need an instance of the class CTree to actually use it? You wrote the entire thing under the assumption that you're operating on an instance of a class. An actual tree, rather than a blueprint for it.

As the answer before me said, it's not a static function or class-level. A non-static method needs to be invoked on an instance so that a silent pointer this can be set to something meaningful, ie. the actual instance you're working with - in this case adding a node.

ADDENDUM

(everything below works without modifying your code, just an explicit answer to your question, to make it compile. From a "working standpoint", this program is far from complete. Some pieces don't even make sense, many variables are left unused or uninitialized (and then used). Let me elaborate further below.)

What you need to do is this add this in your main where the old process() call occured:

CTree myTree; // you could also add (), even though it's a default constructor
finished=process(input, myTree);

And modify the function process' argument list to include a reference to your tree which you wish to operate on. This is just one of the possibilities, you can also take a pointer etc. But a reference is cleaner:

bool process(const string& s, CTree& aTree)

Also, pay attention to compiler warnings. Good practice is to take care of all of them. And remember, this makes it compile, not work. It seems unfinished and rough around the edges.

And remember the difference between a class (an idea) and an instance (a manifestation of that idea). The technical details are not important right now, just make sure you have an instance to work with, as your class design intends. It seems to me that you don't have a grasp around how computer software works, how data and instructions that operate on it connect, especially from a viewpoint of memory. It's not enough for the computer to know what you want to do, it needs to know on what do you want the operations performed (which variables or objects or what-have-you). You can copy by value and return, do it in the main function, pass a reference or a pointer with an address so it can know where in memory is your object/instance located etc. If you're just experimenting, you could create a global instance. A lot of options.

Redeclaring everything doesn't carry over the changes that happen previously (since stuff goes out of scope). Nor does it make sense to call non-static member methods on the class level - and not even properly.

Hope it helps and happy coding. Keep at it, nothing worth doing is simple.

2012-04-05 01:14
by NoName
I'm not following, an instance meaning I need to create a pointer to each element of the tree? I thought I did that in "tree.h" in the CTree class under private - conman 2012-04-05 01:31
You've defined a class. A class can be thought of as the blueprint on top of which objects are made. You now need an instance, like Mr. Charlesworth's example showed. But you also need to keep an active reference to it, so you can operate on it. The this pointer is a silent argument to every non-static function of the class which is then placed in every change of member data like mintVar to this->mintVar. That way, it makes sense and operates on the right memory offset (or, the right object/instance). Check the edit on my answer which makes your code compile - NoName 2012-04-05 02:59
sigh I'm just making the switch from C to C++ so I apologize for the brevity of my programming. I edited the code and it compiles. So thank you very much for that alone. But I'm still getting run time error - conman 2012-04-06 22:35


0

I think they are getting a little too technical for your level of experience. YourCTree class code creates what a CTree class is and how it behaves (a blueprint) but you actually have to tell your code to construct one and then have a way to reference it.

You can declare a stack variable instance like this:

CTree myTree;  

This allocates the memory for your class and calls the constructor on entry into the function. You would then work with it by referencing the functions from the instance name using dot notation.

myTree.Add(4);

Or you can declare a pointer to a CTree and create a dynamic instance using the new operator

CTree *myTree;

myTree = new CTree();

Then you reference the tree using pointer notation:

myTree->Add(4);

if you do it that way you will need to delete the memory you allocated

delete myTree;

So in summary, a class definition of the kind you show here describes a class, but does not create one (allocate memory and setup pointers to the method code). This allows you to have many trees if your code logic requires them;

CTree directoryTree;
CTree fileTree;
CTree indexTree;

These would each have their own data ...

Good luck,

2012-04-05 03:14
by Jeff D.
sigh I'm just making the switch from C to C++ so I apologize for the brevity of my programming. I edited the code and it compiles. So thank you very much for that alone. But I'm still getting run time errors - conman 2012-04-05 06:34
Ads