reverend boltron

Senior member
Nov 18, 2004
945
0
76
I think you're missing some of the properties in your node object. I have a binary tree object that I made a while ago; over a year ago, but I haven't really touched OOP in a while, so I'm a bit hazy on it. All I remember is, "You have to be friends if you're going to use their private parts."

Maybe you should try to set up a binary tree object with a private node class inside of it? That way the functions of the node will be limited to the binary tree, and you won't expose the data inside the nodes to anyone else except the function.
 

Ken g6

Programming Moderator, Elite Member
Moderator
Dec 11, 1999
16,698
4,660
75
First, I have to say, what's with the hard-coding in the header file? It looks like your professor wants you to store the data in a text file, separate from the header file. This will be a whole lot easier once you know how to traverse, or "walk" a tree.

As far as source code for it, have you done a linked list yet? You can modify that code to make a tree without much difficulty. A tree is just like a linked list, but with two pointers out instead of one. (And no loops like a doubly-linked list, but that code would be even easier to modify.)

The next thing you absolutely have to know is how to do a "depth-first traversal" of the tree. Basically, at any node, recursively traverse the left, then traverse the right. This results in a path like you would see walking through the tree like a maze, making all right-hand turns. This is the way to initially create a tree, and to delete it. (There's also something called "breadth-first traversal", but that needs a stack data structure as well!)

Finally, you need to think about how to store your tree. Think about the kinds of data you need to store: questions and animals. I'll just "leaf" it at that. ;)
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
Questions like this really leave me wondering where to start. This is a fairly advanced programming problem, and your questions indicate you aren't familiar with the basic structure of a C++ program, how names behave in various scopes, and how compilation proceeds.

Let me address your second question first, since it is the most basic. It sounds like what your prof wants you to do is create a class that encapsulates the tree data structure and operations. A typical class would consist of a header file containing the declarations of the class and its members, and a .cpp file containing the definitions. Convention is to name them the same. Myclass.h contains the declaration, and is included in other .CPP modules that need to use the class. Myclass.cpp contains the definitions and is built and linked once.

C++ makes a strong distinction between a declaration, which introduces a name into scope during the compilation of a source module, and a definition which creates an actual named item in memory. For example:

Class A
{
public:
A();
~A();

private:
int m_A;
}

The above is a declaration. It lays out what the type 'A' looks like. The declaration introduces the names of two member functions, the constructor and destructor, and one member variable. Nothing in this text allocates any storage for anything, code or data.

In a separate .cpp file you would have...

#include A.h // pulls the declaration of A into the current compilation unit

A::A()
{
// do constructor stuff
}

A::~A()
{
// do destructor stuff
}

These are definitions for the member functions declared in A.h. When this source module is compiled memory will be reserved in a code segment for the assembled output of these two definitions. The member variable A::m_A doesn't exist anywhere yet, because no instance of this class has ever been created. There is code, but no data yet.

In another module...

#include A.h // pulls the declaration of A into the current compilation unit

A a;

int Foo()
{
A b;
}

Now after entry into Foo() we have two instances of A, meaning that storage has been allocated for a.m_A, and b.m_A. The instance a in this case has file scope, since it was declared and defined (some statements are both declarations and definitions, and this is one) outside the scope of any function. It will exist before we enter Foo(). The instance b has function scope, and will only exist after we enter Foo(), and will go away after we exit Foo(). This is called a local declaration, and such variables are allocated on the stack typically.

The way to think about compilation and scope and names is to remember that a C++ compiler compiles one source module at a time. This is called the compilation target, and is usually a .cpp file. The preprocessor first parses all the #include directives which do exactly that: include the full text of the named headers in the text to be compiled. This "virtual" compilation target, which consists of the base .cpp source file and all included headers, is called a compilation unit. Once the includes have been processed the compiler processes the unit from top to bottom. So for each target .cpp to be compiled, there must be #include directives, or file- or function-scope declarations, for every name the compiler encounters when processing the file. Once the full text has been processed the object code for that module is generated, the compiler exits, and everything that was known about that module during compilation is gone and forgotten. If you have another module that does all the things the first module did, then it will need to include all the same headers. Each target is compiled on its own.

Once all the targets are compiled into object code they are linked together, which is the process of ordering the object code into an executable file format, and fixing up any references that a module might have to other objects or memory addresses outside itself (external references). Examples of external references include any call from your source into an operating system function, or a reference to a file scope variable declared as extern in another module. Nearly all calls to class member functions are external references to the module the member functions were compiled in. This is why you only include the class header into other modules, and not the .cpp file. The names in the headers need to be in every unit that refers to them, but the class code need only be compiled once. The linker will fix up calls to the class implementation.

Lastly, I would expand on what Ken said. Before you start you should do some Googling around and read up on the basic purpose, structure, and operations of n-ary trees. Nearly every example you find will focus on binary trees as they are most common. Once you understand how a tree is built and functions, you can choose how to implement yours. You need to decide the basic structure first. Will the nodes be allocated on the heap as needed, with pointers to reference links, or will they be stuffed into a fixed size array, with indexes to reference links? Once you know the basic structure you want wrap it in a class. The constructor of the class will build the data structure of the tree and initialize it. The destructor will deallocate any allocated storage and clean up. You will then need member functions to operate on the data structure.

Here your choices are how abstract to be. You might provide an interface that consists solely of functions to traverse the tree and read node contents. Another class might implement the actual question/answer logic, and use an instance of the tree class. Or you might economize and just wrap the tree in a class that handles all the game logic and run it from main().

Good luck with it :).
 

DarkThinker

Platinum Member
Mar 17, 2007
2,822
0
0
Hey guys, I have updated my code, please take a look at the OP and give me some input please :)
Thank You.
 

KCfromNC

Senior member
Mar 17, 2007
208
0
76
From what I've seen and done before, you generally need two classes to make a tree. The first is a node class, which has a left and right pointer along with data, and has pretty basic operation - a constructor/destructor, maybe something to set and get the data, and that's about it. The next is a tree class, which has a pointer to the root node and allows operations on the tree itself, like insert, delete, search, traverse, and so on. As you have it now, every node has a root pointer, which doesn't make much sense since a tree only has 1 root.

As was pointed out previously, google is your friend here. The first few links I found for "c++ binary tree implementation" were exactly what you need.

Also, ifYes() as it is now shouldn't be part of the tree classes. It doesn't get or set any info about the nodes or structure of the tree, so it should be somewhere else.
 

jman19

Lifer
Nov 3, 2000
11,225
664
126
Originally posted by: Markbnj
Questions like this really leave me wondering where to start. This is a fairly advanced programming problem, and your questions indicate you aren't familiar with the basic structure of a C++ program, how names behave in various scopes, and how compilation proceeds.

Let me address your second question first, since it is the most basic. It sounds like what your prof wants you to do is create a class that encapsulates the tree data structure and operations. A typical class would consist of a header file containing the declarations of the class and its members, and a .cpp file containing the definitions. Convention is to name them the same. Myclass.h contains the declaration, and is included in other .CPP modules that need to use the class. Myclass.cpp contains the definitions and is built and linked once.

C++ makes a strong distinction between a declaration, which introduces a name into scope during the compilation of a source module, and a definition which creates an actual named item in memory. For example:

Class A
{
public:
A();
~A();

private:
int m_A;
}

The above is a declaration. It lays out what the type 'A' looks like. The declaration introduces the names of two member functions, the constructor and destructor, and one member variable. Nothing in this text allocates any storage for anything, code or data.

In a separate .cpp file you would have...

#include A.h // pulls the declaration of A into the current compilation unit

A::A()
{
// do constructor stuff
}

A::~A()
{
// do destructor stuff
}

These are definitions for the member functions declared in A.h. When this source module is compiled memory will be reserved in a code segment for the assembled output of these two definitions. The member variable A::m_A doesn't exist anywhere yet, because no instance of this class has ever been created. There is code, but no data yet.

In another module...

#include A.h // pulls the declaration of A into the current compilation unit

A a;

int Foo()
{
A b;
}

Now after entry into Foo() we have two instances of A, meaning that storage has been allocated for a.m_A, and b.m_A. The instance a in this case has file scope, since it was declared and defined (some statements are both declarations and definitions, and this is one) outside the scope of any function. It will exist before we enter Foo(). The instance b has function scope, and will only exist after we enter Foo(), and will go away after we exit Foo(). This is called a local declaration, and such variables are allocated on the stack typically.

The way to think about compilation and scope and names is to remember that a C++ compiler compiles one source module at a time. This is called the compilation target, and is usually a .cpp file. The preprocessor first parses all the #include directives which do exactly that: include the full text of the named headers in the text to be compiled. This "virtual" compilation target, which consists of the base .cpp source file and all included headers, is called a compilation unit. Once the includes have been processed the compiler processes the unit from top to bottom. So for each target .cpp to be compiled, there must be #include directives, or file- or function-scope declarations, for every name the compiler encounters when processing the file. Once the full text has been processed the object code for that module is generated, the compiler exits, and everything that was known about that module during compilation is gone and forgotten. If you have another module that does all the things the first module did, then it will need to include all the same headers. Each target is compiled on its own.

Once all the targets are compiled into object code they are linked together, which is the process of ordering the object code into an executable file format, and fixing up any references that a module might have to other objects or memory addresses outside itself (external references). Examples of external references include any call from your source into an operating system function, or a reference to a file scope variable declared as extern in another module. Nearly all calls to class member functions are external references to the module the member functions were compiled in. This is why you only include the class header into other modules, and not the .cpp file. The names in the headers need to be in every unit that refers to them, but the class code need only be compiled once. The linker will fix up calls to the class implementation.

Lastly, I would expand on what Ken said. Before you start you should do some Googling around and read up on the basic purpose, structure, and operations of n-ary trees. Nearly every example you find will focus on binary trees as they are most common. Once you understand how a tree is built and functions, you can choose how to implement yours. You need to decide the basic structure first. Will the nodes be allocated on the heap as needed, with pointers to reference links, or will they be stuffed into a fixed size array, with indexes to reference links? Once you know the basic structure you want wrap it in a class. The constructor of the class will build the data structure of the tree and initialize it. The destructor will deallocate any allocated storage and clean up. You will then need member functions to operate on the data structure.

Here your choices are how abstract to be. You might provide an interface that consists solely of functions to traverse the tree and read node contents. Another class might implement the actual question/answer logic, and use an instance of the tree class. Or you might economize and just wrap the tree in a class that handles all the game logic and run it from main().

Good luck with it :).

Just wanted to point out that this is an *excellent* post that describes some fundamental points newish C++ programmers should know!
 

DarkThinker

Platinum Member
Mar 17, 2007
2,822
0
0
Thanks for the info guys the project is about %85 complete feature wise, the info was sure helpful in refreshing my memory on what I have forgotten of C++ :)
Thanks