Hi I am trying to create a function that counts the number of nodes in the binary tree. I am getting an error that says mismatch of functions. I have gotten other errors and can't seem to get it to work. I know the idea just am having a hard time figuring this one out. Thank You! Edit - My error is mismatch of parameter list.
template<class T>
class BinaryTree
{
private:
struct TreeNode
{
T value;
TreeNode *left;
TreeNode *right;
};
TreeNode *root;
void insert(TreeNode *&, TreeNode *&);
void NodeNumber(TreeNode *&, int&); //My NodeNumber declaration
public:
BinaryTree()
{
root = nullptr;
}
void insertNode(T);
int NodeNum();
};
template <class T>
void BinaryTree<T>::insertNode(T item)
{
TreeNode *newNode = nullptr;
newNode = new TreeNode;
newNode->value = item;
newNode->left = newNode->right = nullptr;
insert(root, newNode);
}
template <class T>
void BinaryTree<T>::NodeNumber(TreeNode *&root, int&)
{
if (root = nullptr)
return;
else
root->right;
root->left;
count = count + 2;
}
template <class T>
int BinaryTree<T>::NodeNum()
{
int count = 0;
NodeNumber(root,count);
return count;
}
You have numerous mis-designs and errors in this class. I will focus on the outright errors. I don't know which of those mis-designs has been mandated by your professor and which are yours.
BinaryTree<T>::NodeNumber, as it is currently written, will crash every time. To figure out why, think carefully about exactly what this line does:
if (root = nullptr)
How does that line differ from these two?
root = nullptr;
if (root)
Secondly, what do the lines:
root->left;
and:
root->right;
do exactly? Why do you think they do that?
Lastly, when exactly should you be adding to count and why? Where is that true?
You didn't give a name to the 2nd parameter in this function, which I assume should be count.
// original
template <class T>
void BinaryTree<T>::NodeNumber(TreeNode *&root, int&)
{
if (root = nullptr)
return;
else
root->right;
root->left;
count = count + 2;
}
A few comments:
If you have a non-null root pointer, you want to visit both left and right child trees. It looks weird that right is in the "else" case, while left is not. I suggest getting rid of the "else" and just return if root is null, and otherwise process both left and right after the if.
You are not testing if the root pointer is null; you are setting it to null.
There is no reason to pass a reference to the root pointer
Your statements like "root->right" do not do anything. You want to recurse down the left child and recurse down the right child, so need to call NodeNumber again and pass your children as the root of these recursive calls, and also pass "count" down too.
Why do you increment by 2? Each node should only count as 1. (Its children will account for themselves as you recurse down them, so only add one for the node itself.)
I prefer to return the count rather than use an "out" parameter
Therefore, consider something like this:
template <class T>
int BinaryTree<T>::NodeNumber(TreeNode *root)
{
if (root == nullptr)
return 0;
int count = 1;
count += NodeNumber(root->right);
count += NodeNumber(root->left);
return count;
}
And of course, adjust the declaration and calls accordingly.
Related
I've been given a task to create a method of Binary Search Tree class to insert elements in the correct place in the tree. The declaration of this function is:
void BST::insert(int k)
{
}
Can someone explain why isn't a root node given as parameter ? How am i able to traverse the tree, when I do not have its root node ? Having a return type of void hints me to use the 'this' keyword
I've tried implementing the following:
void BST::insert(int k) {
while(this->root != NULL) {
if(k < this->root->value) {
this->root = this->root->leftChild;
} else {
this->root = this->root->rightChild;
}
}
this->root = new node(k);
}
This is additionnal OOP code:
struct node {
int value;
node* parent;
node* leftChild;
node* rightChild;
node (int);
int dessiner(ofstream&, int);
};
class BST {
public:
node* root;
BST();
void dessiner(string);
void swap(node*, node*);
void inserer(int);
};
EDIT: I added 2 pointers. tmp to traverse tree and P to keep track of tmp's parent node
node* tmp = this->root;
node* p = NULL;
while(tmp!=NULL) {
p = tmp;
if(k < tmp->value) {
tmp = tmp->leftChild;
} else {
tmp = tmp->rightChild;
}
}
tmp = new node(k);
tmp->parent = p;
Can someone explain why isn't a root node given as parameter ?
It is. BST::insert implicitly has a BST * parameter, named this. From there you can get at root. Note that you don't need this-> to refer to root, it is implicit in body of the member function.
Having a return type of void hints me to use the 'this' keyword
The return type has nothing to do with it.
Note that you will need to assign the new node to p's leftChild or rightChild, after insert finishes, nothing points to it.
When dealing with BSTs I usually write a public function like the one you have which calls a the private, recursive function with the root of the tree. You don't have access to the root of the tree from outside the class so it doesn't make sense for the public function to accept anything more than the element to insert.
void BST::insert(int k)
{
insert(k, root);
}
void BST::insert(int k, node* curr)
{
// logic to insert the new element
...
}
You can combine these functions with a default parameter so from outside the class you can call bst.insert(5) and curr will start out as the root of the tree.
void BST::insert(int k, node* curr = root)
{
// logic to insert the new element
...
}
I'm trying to build a function to insert into a binary search tree, but I'm having a hard time figuring out why it won't work. I understand fundamentally how the function is supposed to work, but based on the template I was given it seems as though I am to avoid creating a BST class but instead rely on the Node class and build the desired functions to work on that. Here's the given template:
#include <iostream>
#include <cstddef>
using std::cout;
using std::endl;
class Node {
int value;
public:
Node* left; // left child
Node* right; // right child
Node* p; // parent
Node(int data) {
value = data;
left = NULL;
right = NULL;
p = NULL;
}
~Node() {
}
int d() {
return value;
}
void print() {
std::cout << value << std::endl;
}
};
function insert(Node *insert_node, Node *tree_root){
//Your code here
}
The issue I'm having is when I implement the following code, where getValue is a simple getter method for Node:
int main(int argc, const char * argv[]) {
Node* root = NULL;
Node* a = new Node(2);
insert(a, root);
}
void insert(Node *insert_node, Node *tree_root){
if (tree_root == NULL)
tree_root = new Node(insert_node->getValue());
The code appears to compile and run without error, but if I run another check on root after this, it returns NULL. Any idea what I'm missing here? Why is it not replacing root with a new node equal to that of insert_node?
I also realize this doesn't appear to be the optimal way to implement a BST, but I am trying to work with the template given to me. Any advice would be appreciated.
As Joachim said your issue relates to difference between passing parameter by reference and by value.
In your code void insert(Node *insert_node, Node *tree_root) you pass Node* tree_root by value. Inside the function you change local copy of this pointer, so outer value is not changed.
To fix it you should pass Node* tree_root by reference. Parameter declaration can be Node*& tree_root (or Node** tree_root). E.g:
void insert(Node* insert_node, Node*& tree_root){
if (tree_root == NULL)
tree_root = new Node(insert_node->getValue());
This is my first time working with any kind of tree. I created a tnode class for my tree and now I'm trying to create the class for the tree itself. However I've gotten a couple errors I can't figure out.
#ifndef Tree_Ntree_h
#define Tree_Ntree_h
// SIZE reprsents the max number of children a node can have
#define SIZE 10
// SEPERATE will allow the program to distinguish when a subtree no longer has children
#define SEPERATOR '#'
#include <iostream>
#include <fstream>
template <typename T>
class tnode{
public:
T value;
tnode *child[SIZE];
tnode() {};
tnode<T> *addChild(T data){
tnode*temp = new tnode;
temp -> value = data;
for (int i=0; i<SIZE; i++)
temp -> child[i] = NULL;
return temp;
}
};
template <typename T>
class Ntree{
private:
tnode<T> *root;
T data;
std::string filename;
public:
Ntree(){ root= NULL;}
Ntree( T data){ *root = data;}
inline T getRoot(){return root;}
My errors are in the last three lines.
In the last line of my code (getRoot), this is the error:
No viable conversion from 'tnode > *' to
'std::__1::basic_string'
In the second to last line and the third to last line (*root = data) (root = NULL) this is the error:
No viable overloaded '='
I don't understand why it is necessary to overload the = operator in this situation.
root is a tnode<T> * and getRoot is returning a T object. The compiler doesn't know how to convert one to the other. You probably just want to return root->value
However, you haven't allocated any space for root and it might be NULL, so you need to determine what to do when it is NULL.
In this line:
Ntree( T data){ *root = data;}
This time you are assigning a T to a tnode<T>, which the compiler doesn't know how to do. You also haven't allocated any memory for root. Instead you probably want todo something like:
Ntree( T data){ root = new T; root->value = data;}
Or better still have a tnode constructor that takes a value.
I'm having a problem entirely deleting my AVL tree. I've figured out how to delete just a single node, but my destroyTree function doesn't seem to actually destroy every node recursively. What could I be doing wrong?
I have a struct nodeType<myType>
template <class myType>
struct nodeType {
myType keyValue;
int nodeHeight;
nodeType<myType> *left;
nodeType<myType> *right;
};
and I am attempted to delete all existing nodes with:
if(node != NULL) {
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
node = NULL;
but this does not seem to properly delete the nodes, when checking for the height it still gives me the height before the destroy was called although crashes when attempting to print. In the main function calling destroy tree I used a simple if statement
template <class myType>
void avlTree<myType>::destroyTree()
{
destroyTree(root);
if(root == NULL)
std::cout << "destroyed" << std::endl;
}
shows that root is NOT null (yes is not printed)
Look at this piece of code:
destroyTree(root);
if(root == NULL)
std::cout << "destroyed" << std::endl;
Probably your destroyTree function has this prototype:
void destroyTree(nodeType<myType> *node);
The problem is that node cant update the caller memory address, but only the contents that caller is pointing. This means that root will never be update, i.e., its contents cant be updated to NULL.
To do that, you need a prototype that is something like that:
void destroyTree(nodeType<myType> **node);
I'm guessing you're not taking node by reference, and therefore when you set the node to NULL you're actually setting a local copy of the node to null.
Won't work because root is taken by value - will have prior value after function call:
template <class myType>
void avlTree<myType>::destroyTree(nodeType<myType>* node) // note node taken by value here
{
if(node != NULL) {
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
node = NULL;
}
Will work because root is taken by reference - will be null after the function call:
template <class myType>
void avlTree<myType>::destroyTree(nodeType<myType>* &node) // note node taken by reference here
{
if(node != NULL) {
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
node = NULL;
}
I am making a tree of n children to store directories of computer. Now, concept is simply make a tree (that would not be a BT of course) and each node will have children as well. Consider the code below then I will explain the problem.
First Consider this:
C/users/DeadCoder/Movies/Batman.
Now In my main.cpp I have this all C, users, DeadCoder, Movies, Batman in a vector and then I send two pairs in insert Func. if root==NULL; it would just insert C. Next time C and users would go. It would find C and then insert users occordingly. Let's now see the code .
template <class T>
struct Node;
template <class T>
class tree
{
Node<T> *root;
public:
tree();
~tree();
int insert(T str, T str1);
Node<T> *getRoot();
Node<T> *search(T item, Node<T> *tempPtr);
};
template <class T>
struct Node{
T n;
Node<T> *sibling;
tree<T> children; // SEE my each node has children.
Node(T N){
this->n = N;
this->sibling = NULL;
}
};
// In .cpp FILE;
// Initilaizer
template <class T>
tree<T>::tree() // Constructor Initialization.
{
root=NULL;
}
// Insert Function.
template <class T>
int tree<T>::insert(T push, T find)
{
Node<T> *rPtr = root;
if (rPtr==NULL){
//ROOT is NULL. C needs to be inserted which is in find.
Node<T> *pusPtr = new Node<T>(find);
root = pushPtr;
root->sibling=NULL;
return 0;
}
else if(rPtr!=NULL){
Node<T> *pushPtr = new Node<T>(push);
Node<T> *temp2 = search(find, root);
Node<T> *temp = temp2->children.getRoot(); // say it LINE_40.
if (temp==NULL){
temp = pushPtr;
temp->sibling=NULL;
return 1;
}
// children are already present.
else if(temp!=NULL){
// You don't need to know code for this part.
}
}//if.
}
// Search Function.
template <class T>
Node<T> *tree<T>::search(T data, treeNode<T>* N)
{
if (N->n==data){ // where n represent directory.
return N; // data found.
}//if....
else{
Node<T> *child = N->children.getRoot();
// This is where i get Segmentation fault,
// because child is ==NULL; but you see in LINE_40 I did insert the child for C.
if(child!=NULL){ // say it line 80.
search(data, child);
}//if...
if(child->sibling!=NULL){
search(data, child->sibling);
}
}
}// search....
PROBLEM: C inserted. Users inserted. Now in search function at Line 80, it comes to find the child for C. and it should be Users as I have inserted it in LINE 40. BUT Instead it says child==NULL. I have been debugging for hours and I don't know why it says so. I hope Everybody gets the problem.
Now I really need to know why it is regarding C child to be NULL, It has to be users. Can anyOne see what is the problem???? HELP !!!!
Line 42 does nothing (I mean it has no side effect). It just puts a value in a temporary variable then leaves.
You probably want your temp to be a reference to the root. Something like: Node<T> *&temp =
Are you sure insert method actually inserted these elements?
It might be helpful to implement postconditions so to verify your methods actually fulfill their contract (design by contract).
This way you'll directly get what is wrong and debugging will be fast or unnecessary in some cases, since you'll get log messages saying "this method was supposed to do this but failed doing it", otherwise you'll look for hours where the problems comes from.