?
Solved

C++ General Tree, Part 2

Posted on 2009-07-15
21
Medium Priority
?
234 Views
Last Modified: 2012-05-07
Ok folks, this forum was a MAJOR help for me last time with regards to fully understanding what it is I was doing wrong and helping me get on the right path... ...I re-evaluated my code and came up with a different approach to my logic --- however, I'm running into errors...

1) error C2664: 'GenTreeNode::GenTreeNode(const GenTreeNode &)' : cannot convert parameter 1 from 'GenTreeNode *' to 'const GenTreeNode &'      -- LINE 73

2) error C2440: 'delete' : cannot convert from 'GenTreeNode' to 'void *'      -- LINE 77

3) error C2664: 'GenTreeNode::setTreeNode' : cannot convert parameter 1 from 'int *' to 'int'      -- LINE 81

4) error C2664: 'GenTreeNode::setChildren' : cannot convert parameter 2 from 'int' to 'int *'      -- LINE 82

help...
#ifndef GENERALTREE_h
#define GENERALTREE_h
 
#include <iostream>
#include <sstream>
#include <string>
 
using namespace std;
 
class GenTreeNode{
	public:
		int transactionID, totalNumChildren;
		GenTreeNode *childrenPtr;
 
		std::string toString(){
			std::ostringstream oss;
			oss<<transactionID;
 
			return oss.str();
		}
 
		void print(){
			cout<<toString()<<endl;
		}
 
		void printNode() {
			print();
			for(int i=0; i<totalNumChildren; i++){
				childrenPtr[i].printNode();
			}
		}
 
		GenTreeNode(): transactionID(0),totalNumChildren(0){
			childrenPtr = NULL;
		}
 
		GenTreeNode(int id, int cNo){
			transactionID = id;
			totalNumChildren = cNo;
			childrenPtr = new GenTreeNode[totalNumChildren];
		}
 
		void setTreeNode(int id, int cNo){
			transactionID = id;
			totalNumChildren = cNo;
			childrenPtr = new GenTreeNode[totalNumChildren];
		}
 
		~GenTreeNode(){
			if(childrenPtr != NULL){
				delete[] childrenPtr;
			}
		}
 
		void setChildren(int *tranID, int *cNos){
			for(int i=0; i<totalNumChildren; i++){
				childrenPtr[i].setTreeNode(tranID[i], cNos[i]);
			}
		}
 
		void deleeChild(GenTreeNode *ChildPtr){
			if(totalNumChildren){
				delete[] childrenPtr;
			}
		}
};
 
class GeneralTree{
	public:
		//initialize root
		GenTreeNode root;
 
		GeneralTree()   // ***** LINE 73 *****
			: root(new GenTreeNode()){}
 
		virtual ~GeneralTree(){
			delete root;   // ***** LINE 77 *****
		}
 
		void setChildren(int *tranIDs, int cNos){
			root.setTreeNode(tranIDs, cNos);   // ***** LINE 81 *****
			root.setChildren(tranID, cNos);   // ***** LINE 82 *****
		}
 
		void printTree() {
			root.printNode();
		}
};
#endif

Open in new window

0
Comment
Question by:didijc
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 6
  • 5
  • +1
21 Comments
 
LVL 31

Expert Comment

by:Zoppo
ID: 24858030
Hi didijc,

the first two errors occur since you treat 'root' as if it was a pointer although it isn't - to solve these declare 'root' as a pointer in line 71:
> GenTreeNode* root;

To use this 'root' later replace all occurances of 'root.' with 'root->'.

The other two errors are somehow unclear to me - sure is the function 'setTreeNode' expects an 'int' but you pass a 'int*' - the 4. error IMO occurs because 'tranID' is undefined, so the compiler treats it as an 'int', but 'setChildren' expects a 'int*'

ZOPPO
0
 
LVL 53

Accepted Solution

by:
Infinity08 earned 1000 total points
ID: 24858063
>> to solve these declare 'root' as a pointer in line 71:

There's no real need to allocate it dynamically, is there ? So, just don't use new or delete, and you're fine. The rest of the code can then stay as it is.


>> 3) error C2664: 'GenTreeNode::setTreeNode' : cannot convert parameter 1 from 'int *' to 'int'      -- LINE 81
>> 
>> 4) error C2664: 'GenTreeNode::setChildren' : cannot convert parameter 2 from 'int' to 'int *'      -- LINE 82

These are simply because you don't pass the expected type.
GenTreeNode::setTreeNode takes two ints as parameter, but you pass it an int* and an int.
GenTreeNode::setChildren takes two int*'s as parameter, but you pass it an int* and and int.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24858069
>> the 4. error IMO occurs because 'tranID' is undefined

I think it's declared elsewhere, because otherwise the compiler would have complained about it.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24858201
>>>> There's no real need to allocate it dynamically, is there ?

If the tree could go empty we have no root. Hence, it should be a pointer which could be set to NULL.

>>>> void setChildren(int *tranIDs, int cNos){


The setChildren is obsolote with the new approach. You should/can add each child node individually.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24858954
>> If the tree could go empty we have no root. Hence, it should be a pointer which could be set to NULL.

The current code doesn't support such a thing, especially since the root node is allocated as soon as the tree is created (in the default constructor). But for a more conforming tree implementation, you're of course right ;)
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24859627
>>>> But for a more conforming tree implementation
Yes, I recently was in a thread which has *empty* nodes. It actually doesn't work very well ;-)

@didjic

It is better when the default constructor sets the root to NULL (rather than creating an empty root).

Then, you have an empty tree what you could populate by a member function like

   bool GeneralTree::isempty() { return root == NULL; }

The first insert or add function would create a new node and in case root == NULL it would assign this new node to the root (instead of adding a new child to some parent node).
0
 

Author Comment

by:didijc
ID: 24862693
Why does root have to be a pointer?  Why can't I declare root as a regular variable of GenTreeNode?

If root is always the first node within my tree why not declare it right away -- in my the scenario that I am creating my root will never be empty...which is why I decided not to make it a pointer... ...
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24862896
>> in my the scenario that I am creating my root will never be empty...which is why I decided not to make it a pointer... ...

And that's fine, as long as you know the limitations ;) See here : http:#24858063
0
 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 1000 total points
ID: 24864032
>>>> Why does root have to be a pointer?  Why can't I declare root as a regular variable of GenTreeNode?

You can, but the pointer is the normal design.

Note, you were using pointers in the GenTreeNode to point to next sibling node and first child node. Any node in the tree has a parent node beside of the root. If you think of the tree instance as the parent of the root you have a consistent model where pointers were used to point to the next nodes and where a NULL pointer means that there is no child respectively sibling

TREE
   ->  ROOT
            |
            v
        CHILD_1        ->         CHILD_2       ->     CHILD_3
            |
            v
        GRAND_CHILD_1 ...

If you use an instance of the root in the tree as member, it means that the tree always has a root, i. e. either the tree is never empty (A) or the root can be a *empty* node which neither has a data member nor does it have any children or siblings (B)

With (B) the root member is some kind of a dummy as it neither has data nor pointers to child and sibling. That is a logical flaw with the current model as we don't have a property of GenTreeNode which tells us that it is empty. We would need to add a bool member 'isempty' to being able to handle it. Or we must have some data value which tells us that the root node was empty. Or we need to add an item  counter in the tree so that we *know* that the root is empty (since the counter is 0). Or we have a root node which generally doesn't count but is only the anchor node. All these ways out are bad design (maybe beside of the anchor node). It is not good if we add members which handle only one special node. And it is not good to have special data values what would be a limitation for the tree without need.

That's why the normal solution is to have a pointer member for root in the tree. If this pointer is NULL the tree is empty. If not it has at least one element which is the element stored with the root node.

0
 

Author Comment

by:didijc
ID: 24864238
itsmeandnobodyelse / Infinity08 -- I completely understand what the each of you are saying...however, in my grand scheme, the ROOT/ tree will never be empty...

8 << * this will never be an "empty" / NULL value *
|
8,1------------------ 8,2 ----------------- 8,3 ----------------- ... ----------------- 8,n
                                |
                                |
                                8,2,1 ----------------- 8,2,2 ----------------- 8,2,3 ... ----------------- 8,2,n
                                                                                                     |
                                                                                                     |
                                                                                                     8,2,3,4 ----------------- 8,2,3,4
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24864248
As I said, that's perfectly fine ;) Did you get it to work ?
0
 

Author Comment

by:didijc
ID: 24864268
I'm making a couple of adjustments as we speak... :) as soon as I'm done I'll share it with you...
0
 

Author Comment

by:didijc
ID: 24864333
Ok so here's my fix * based on talking with itsmeandnobodyelse & Infinity08 * -- damn you guys are good, I only hope to be as good eventually...
#ifndef GENERALTREE_h
#define GENERALTREE_h
 
#include <iostream>
#include <sstream>
#include <string>
 
using namespace std;
 
class GenTreeNode{
	public:
		int transactionID, totalNumChildren;
		GenTreeNode *childrenPtr;
 
		std::string toString(){
			std::ostringstream oss;
			oss<<transactionID;
 
			return oss.str();
		}
 
		void print(){
			cout<<toString()<<endl;
		}
 
		void printNode() {
			print();
			for(int i=0; i<totalNumChildren; i++){
				childrenPtr[i].printNode();
			}
		}
 
		GenTreeNode(): transactionID(0),totalNumChildren(0){
			childrenPtr = NULL;
		}
 
		GenTreeNode(int id, int cNo){
			transactionID = id;
			totalNumChildren = cNo;
			childrenPtr = new GenTreeNode[totalNumChildren];
		}
 
		void setTreeNode(int id, int cNo){
			transactionID = id;
			totalNumChildren = cNo;
			childrenPtr = new GenTreeNode[totalNumChildren];
		}
 
		~GenTreeNode(){
			if(childrenPtr != NULL){
				delete[] childrenPtr;
			}
		}
 
		void setChildren(int *tranID, int *cNos){
			for(int i=0; i<totalNumChildren; i++){
				childrenPtr[i].setTreeNode(tranID[i], cNos[i]);
			}
		}
 
		void deleeChild(GenTreeNode *ChildPtr){
			if(totalNumChildren){
				delete[] childrenPtr;
			}
		}
};
 
class GeneralTree{
	public:
		//initialize root
		GenTreeNode root;
 
		GeneralTree(){}
 
		virtual ~GeneralTree(){}
 
		void setChildren(int *tranIDs, int *cNos){
			root.setTreeNode(*tranIDs, *cNos);
			root.setChildren(tranIDs, cNos);
		}
 
		void printTree() {
			root.printNode();
		}
};
#endif

Open in new window

0
 

Author Comment

by:didijc
ID: 24864360
Now - let's put it all together and see how everything flows...

* fingers crossed *
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24867473
Let us know if you need further assistance :)
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24867563
>>>> void deleeChild(GenTreeNode *ChildPtr){
It probably should mean deleteChild and as it deletes all children you better name it deleteChildren.

Moreover the childrenPointer must be set to NULL after delete and the totalNumChildren to 0, or the next traversal will crash.
0
 

Author Comment

by:didijc
ID: 24868051
>>>> Moreover the childrenPointer must be set to NULL after delete and the totalNumChildren to 0, or the next traversal will crash

Doesn't the constructor take care of that...

[code]
GenTreeNode(): transactionID(0),totalNumChildren(0){
     childrenPtr = NULL;
}
[/code]
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 25331988
>>>> Doesn't the constructor take care of that...
The constructor is a first-time (one time) initialitation. It couldn't help when child nodes were deleted.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 25332208
Based on the author's post http:#24864333, I'd say the question has been resolved.

I suggest a PAQ for http:#24858063 (Infinity08) and http:#24864032 (itsmeandnobodyelse), based on the names mentioned by the author in his post.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
Suggested Courses
Course of the Month11 days, 9 hours left to enroll

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question