Can't insert a new node in the binary tree - c++

I believe my insertion function is right, but it looks like the new node is not being inserted in the tree. I could not figure out where is the mistake. I appreciate any help,thanks.
There is the declaration of node and tree:
class Node{
int key;
Node *right, *left;
}
class Tree{
public:
int init();
Node *root;
Node *insert(int key, Node *p);
};
there is the functions:
int Tree::init(){
this->root = NULL; return 1;
}
Node *Tree::insert(int key, Node *p){
if(p == NULL){
Node *novo = new Node();
novo->key = key;
novo->left = NULL;
novo->right = NULL;
p = novo;
}
else if(key < p->key){ p->left = insert(key, p->left); }
else if(key > p->key){ p->right = insert(key, p->right); }
else{ cout << "Error: key already exist" << endl; }
return p;
}
When I call the function in the main, it looks like it does not link the new node
int main() {
Tree dictionary;
cout << "enter the key"; cin >> key;
dictionary.insert(key, dictionary.root);
cout << dictionary.root->key;
}

In your insert() function, when the tree is empty or if you've reached the last node, you create a new node:
if(p == NULL){
Node *novo = new Node();
novo->key = key;
novo->left = NULL;
novo->right = NULL;
p = novo; // ouch !!!!
}
Unfortunately, the statement p=novo only updates the local parameter p of your function. Its value will vanish as soon as you return from the function. It will not update the pointer with which you've called your function. So the root of your tree remains NULL (or the left/right pointer of the last node).
To get the effect that you expect (i.e. your p assigment updates the root pointer or the pointer to left/right of the last node), you need to change the signature to:
Node *insert(int key, Node *& p); // p is passed by reference
This will pass the pointer p by reference. Modifying p will then have the effect of modifying the pointer you used to call the function, and will endure a lasting effect of the insertion.

Related

Pointer of struct changes

#include<stack>
#include<iostream>
class Tree{
private:
struct tree{
int val;
tree * lChild;
tree * rChild;
tree * Parent;
};
tree *root;
public:
Tree();
void insert(int x);
};
Tree::Tree(){
root = NULL;
std::cout<<"ROOT inside constructor : "<<root<<std::endl;
}
void Tree::insert(int x){
tree *wst;
wst->val = x;
wst->lChild = NULL;
wst->rChild = NULL;
tree *temp = root;
tree *p = NULL;
std::cout<<"ROOT inside insert : "<<root<<std::endl;
while(temp != NULL){
p = temp;
if(x < temp->val)
temp = temp->lChild;
else
temp = temp->rChild;
}
std::cout<<x<<std::endl;
wst->Parent = p;
if(p == NULL){
root = wst;
}
else{
if(x < p->val)
p->lChild = wst;
else
p->rChild = wst;
}
}
int main(){
Tree tree;
tree.insert(404);
}
I want to check if pointer root is equal to NULL, but it does not seems too work. It seems like the pointer changes from 0 to 0x4 when I am inside the method insert. How can I check if pointer of struct is equal NULL?
EDIT In the insert method if tree doesn't have any nodes it should not enter first while loop, as root should be equall NULL. And my problem is that it enters this loop anyway and crashes when it checks for temp childrens(that are still not defined).
What does wst point to?
tree *wst;
wst->val = x;
wst->lChild = NULL;
wst->rChild = NULL;
// [...]
wst->Parent = p;
Whoops! Your program has undefined behaviour. No wonder it crashes. :)
You probably need tree* wst = new tree(); there. Don't forget to delete your nodes in the Tree destructor, too!
And I'd advise against having a type Tree plus a type tree; perhaps call the latter Node instead?

LinkedList ADT pointer block

I am implementing a number of LinkedList ADT's for my compsci class and I'm running into the same problem on every one. The code listed below is a binary tree ADT. The compiler gets lost when trying to input data into the new nodes. The code compiles without any errors, but the compiler does not return anything, I think it's stuck trying to find the pointer. I come from Java so I'm still working my way around pointers.
#include <iostream>
struct TreeNode {
//represents a single node in a binary tree of int data
int data; //immediate data
TreeNode *left; //left subtree
TreeNode *right; //right subtree
TreeNode(int in);
};
TreeNode::TreeNode(int in) {
data = in;
left = NULL;
right = NULL;
}
The compiler can't seem to find the pointer referenced in these two append functions.
void addLeft(TreeNode *root, int newData) {
TreeNode *new_node;
new_node->data = newData;
root->left = new_node;
}
void addRight(TreeNode *root, int newData) {
TreeNode *new_node;
new_node->data = newData;
root->right = new_node;
}
//counts nodes in binary tree from designated root point
int countNodes(TreeNode *root) {
if (!root) {
return 0; //empty tree
}
int count = 1;
count += countNodes(root->left); //adds left subtree nodes
count += countNodes(root->right); //adds right subtree countNodes
return count;
}
void preorderPrint(TreeNode *root) { //root first, then left, then right
if (root) {
std::cout << root->data << " ";
preorderPrint(root->left);
preorderPrint(root->right);
}
}
void postorderPrint(TreeNode *root) { //left first, then right, then root
if (root) {
postorderPrint(root->left);
postorderPrint(root->right);
std::cout << root->data << " ";
}
}
void inorderPrint(TreeNode *root) { //left first, then root, then right
if (root) {
inorderPrint(root->left);
std::cout << root->data << " ";
inorderPrint(root->right);
}
}
bool tree_contains(TreeNode *root, int item) {
if (!root) {
return false; //if the root doesn't exist, the tree doesn't exist
}
else if (root->data = item) {
return true; //item is found in the root node
}
else if (root->data > item) {
}
}
int main() {
TreeNode *root;
root->data = 5;
addLeft(root, 4);
addRight(root,9);
inorderPrint(root);
return 0;
}
Your root is not initialized. It currently has an undefined value. It should be:
TreeNode *root = new TreeNode(5);
... // Do whatever you want
// delete root and everything else.
A pointer is just a variable that holds an address of an object in memory. When you define a pointer like
int *foo;
you haven't initialized it, so its value is indeterminate. That means it doesn't hold a valid pointer value that could be used to access an object in memory. To make a pointer actually point to something, you have to assign it an address:
int bar;
inf *foo = &bar;
Now foo holds the address of bar and you can dereference foo to write to bar:
*foo = 42;
// bar is now 42
In your code
TreeNode *root;
root->data = 5;
You try to dereference (root->data is just syntactic sugar for (*root).data) a pointer root that hasn't been initialized with or assigned a valid pointer value.
Since you want to create a dynamic data structure that grows on demand, you want to allocate memory at runtime. You could do so using the new operator:
TreeNode *root = new TreeNode; // allocates an object of the type
// TreeNode
root->data = 5; // is now safe.
But since you provide a constructor for TreeNode that takes an int you can write:
TreeNode *root = new TreeNode{ 5 };
The same goes for many other locations in your code as well.
Please remember that dynamically allocated memory should be deallocated when it is no longer needed:
`delete root;`

List All Function still trying to retrieve a node I deleted from a binary search tree

I have these functions to remove a node from my binary search tree:
bool collection::removeFromTree(const char name[])
{
for (treeNode * curr = root; curr;)
{
int8_t result = strcmp(name, curr->item->getName());
if (result == 0)
{
deleteNode(curr);
return true;
}
else if (result < 0)
curr = curr->left;
else if (result > 0)
curr = curr->right;
}
return false;
}
void collection::deleteNode(treeNode *& goneNode)
{
//if it's a leaf
if (!goneNode->left && !goneNode->right)
{
delete goneNode; //node's destructor gets invoked
goneNode = nullptr;
}
//if it has right child
else if (!goneNode->left)
{
goneNode = goneNode->right;
}
//if it has left child
else if (!goneNode->right)
{
goneNode = goneNode->left;
}
//if it has both children
else
{
treeNode * prev = nullptr;
treeNode * curr = goneNode->right;
while (curr->left)
{
prev = curr;
curr = curr->left;
}
//prev points to the copy over data
delete goneNode->item;
if (!prev)
{
goneNode->item = curr->item;
goneNode->right = curr->right;
curr->item = nullptr;
}
else
{
goneNode->item = curr->item;
curr->item = nullptr;
prev->left = curr->right;
}
}
}
This runs fine, but when I try to list all the elements in my tree after deleting a node (with these functions):
void collection::displayByName() const
{
std::cout << std::endl
<< "========================================" << std::endl;
//display the tree inorder
listAll(root);
}
void collection::listAll(const treeNode * const & root) const
{
if (root)
{
std::cout << *(root->item) << std::endl
<< "========================================" << std::endl;
listAll(root->left);
listAll(root->right);
}
}
I receive this error:
And when I quit the program after deleting a node (invoking these destructors):
collection::~collection()
{
delete root;
}
collection::treeNode::~treeNode()
{
delete left;
delete right;
}
I recieve this error:
Any suggestions would be greatly appreciated because I see no reason for my listAll() function to be calling nodes that I've already deleted.
By the way, this is my struct for my treeNode:
struct treeNode
{
treeNode();
treeNode(vendor *& item);
~treeNode();
vendor * item;
treeNode *left, *right;
};
treeNode * root; //the bst
hashNode ** table; //the hash table
uint8_t capacity;
uint8_t size;
const static uint8_t INIT_CAP = 20;
When you need to remove a node from a singly linked list or a tree, I find using a pointer to pointer is handy. Namely, if we have a treeNode** ptr;, then *ptr is the pointer to our node. So, if ptr = &root, then *ptr = nullptr sets root to nullptr.
I removed the deleteNode function and threw its logic in the removeFromTree function.
bool collection::removeFromTree(const char name[])
{
treeNode** ptr = &root;
Instead of being a pointer to treeNode, ptr will point to a treeNode* inside the tree structure. This way, we can modify the pointer that led us to the current node. The lines marked //same as before have the same logic you were using, just possibly modified to account for the fact ptr has another level of dereferencing to do.
int result; //same as before
while (*ptr) //While we haven't hit a dead end
{
result = strcmp(name, (*ptr)->item->getName()); //same as before
if (result < 0) //same as before
ptr = &((*ptr)->left); //same as before
else if (result > 0) //same as before
ptr = &((*ptr)->right); //same as before
else //begin deleteNode() logic
{
if ((*ptr)->left && (*ptr)->right) //two children
{
Here, we use pointers to member because the alternative was a conditional operator on every line. If a node has two children, we need to find either the rightmost node on the left side, or the leftmost node on the right side. That's the node we can replace the current node with.
treeNode* treeNode::*dir = some_condition ? &treeNode::right : &treeNode::left; //pointer to treeNode member of type treeNode*
treeNode* treeNode::*ndir = some_condition ? &treeNode::left : &treeNode::right; //pointer to treeNode member of type treeNode*
dir now either points to left or right, which is the direction we are searching the tree for. ndir is the opposite direction. So, if we want the rightmost node on the left side, (*ptr)->*dir == (*ptr)->left and (*ptr->*ndir == (*ptr)->right. If we want the leftmost right node, it would be reversed. This is just a more complicated way to do less work, really. It shouldn't be hard to remove. some_condition is just either true or false. true means the left side of the tree (from the current node) loses a node, and false means the right side does.
treeNode** replacement = &((*ptr)->*ndir); //the node to replace the current one with
while ((*replacement)->*dir) //While we aren't at the edge
replacement = &((*replacement)->*dir);
This loops until *replacement is the node we need to replace *ptr with.
treeNode* rep_branch = (*replacement)->*ndir; //If the replacement node had a child, this is now it
(*replacement)->left = (*ptr)->left; //Copy current to replacement
(*replacement)->right = (*ptr)->right; //Copy current to replacement
(*ptr)->left = nullptr; //null out current in case of destructor
(*ptr)->right = nullptr; //null out current in case of destructor
Now, the replacement node is pointing to the node-to-be-deleted's children, and our soon to be expired node has no children anymore. Now, it's safe to delete the unwanted node. If the node class had a destructor to delete its children, the left and right pointers were set to nullptr just in case.
delete *ptr; //delete unwanted node
*ptr = *replacement; //replacement node has taken the unwanted node's place in the tree
*replacement = rep_branch; //The replacement's child takes its own place
}
This completes the tree's structure. Wherever the unwanted node was, the replacement node has taken its place. And because the replacement node was required to be an edge node, it had at most one child. We just replace it with the child.
else if ((*ptr)->left) //one child on left
{
treeNode* current = *ptr;
*ptr = (*ptr)->left; //replace current with left
current->left = nullptr; //null out for safety
delete current;
}
else if ((*ptr)->right) //one child on right
{
treeNode* current = *ptr;
*ptr = (*ptr)->right; //replace current with right
current->right = nullptr; //null out for safety
delete current;
}
else //no children
{
delete *ptr;
*ptr = nullptr;
}
return true; //yay it's over
}
}
return false; //never found it
}
The rest is fairly straightforward, just replacing easier nodes and returning. Hopefully this gives you some ideas about how to approach problems like this, and the occasional uses of some of these structures. This is what I meant about using treeNode** over treeNode* for operations like this.

"lvalue required as left operand of assignment" error writing a linked list

I am currently learning some C++ for a course I am taking in school. I have basic understanding of lvalues and rvalues, but I am unable to determine why I am receiving a compiler error.
I am creating a singly linked list and need to be able to reverse it. As per my assignment I have two classes. The first is the node and just holds an int as well as a pointer.
class Node {
int data;
Node *next;
public:
//Constructor
Node(int d) {
data = d;
next = NULL;}
//Set to next Node
void SetNext(Node *nextOne) {
next = nextOne;}
//Returns data value
int Data(){return data;}
//Returns next Node
Node *Next() {return next;}
};
Then I have a linked list class that has a header pointer and then a number of functions for adding, printing etc. the list.
class LinkedList {
Node *head;
public:
//Constructor
LinkedList(){head = NULL;}
void AddNode(int d) {
//Create a new Node
Node *newNode = new Node(d);
//Create a temporary pointer
Node *temp = head;
//If there are already nodes in the list
if(temp != NULL) {
//Parse through to the end of the list
while(temp->Next() != NULL) {
temp = temp->Next();}
//Point the last Node in the list to the new Node
temp->SetNext(newNode);
}
//If adding as the first Node
else{
head = newNode;}
}
void PrintList() {
//Temporary pointer
Node *temp = head;
//If there are no nodes in the list
if(temp == NULL) {
std::cout << "The list is empty" << std::endl;}
//If there is only one node in the list
if(temp->Next() == NULL) {
std::cout << temp->Data() << std::endl;}
//Parse through the list and print
else {
do {
std::cout << temp->Data();
temp = temp->Next();
}
while(temp != NULL);
}
}
//Returns the number of nodes in the list
int CountList() {
//Temporary pointer
Node *temp = head;
//Counter variable
int counter = 0;
//If the list is empty
if(temp == NULL) {
return counter;}
//Parse through Nodes counting them
else {
do {counter++;
temp = temp->Next();
}
while(temp != NULL);
}
return counter;
}
//Reverses the list
Node *ReverseList() {
//Initially set to NULL then tracks the new head
Node *marker = NULL;
//Tracks the next one in the list
Node *nextOne;
//Sets the first Node to NULL and then sets the last Node to point to
//the first one and rotates through the list pointing the last to the
//first
while(head != NULL) {
nextOne = head->Next();
head->Next() = marker;
marker = head;
head = nextOne;
}
//Setting the head back to the start again
head = marker;
}
};
One of those functions is supposed to reverse the list. The line "head->Next() = marker;" in the ReverseList function is causing a "lvalue required as left operand of assignment" error when compiling.
Any insight as to why this is occurring and how I can correct the problem?
Thank you in advance!
The return from the call to Next() is an rvalue. As you are in a class function, you don't need to call the Next function to get at the private next pointer, you can just use it directly.
head->next = marker;
Your Next() function returns a pointer, and you then do this:
head->Next() = marker;
You're changing the pointer to marker and not what it's pointing at. To solve this you need to dereference that pointer:
*head->Next() = marker;
your signature for next is:
Node *Next() {return next;}
This makes a copy of next pointer at return and hence it is treated as r-value and not l-value.
One way of overcoming this would be to use a pointer-to-pointer:.
Node **Next() {return &next;}
And then use it as:
int main()
{
Node* marker=new Node(89);
Node* nod=new Node(9);
*(nod->Next())= marker;
cout<<(nod->next)->data<<endl;
cout << "Hello World" << endl;
return 0;
}
This makes it more complicated to use.

BST Insert C++ Help

typedef struct treeNode {
treeNode* left;
treeNode* right;
int data;
treeNode(int d) {
data = d;
left = NULL;
right = NULL;
}
}treeNode;
void insert(treeNode *root, int data) {
if (root == NULL) {
cout << &root;
root = new treeNode(data);
}
else if (data < root->data) {
insert(root->left, data);
}
else {
insert(root->right, data);
}
}
void inorderTraversal(treeNode* root) {
if (root == NULL)
return;
inorderTraversal(root->left);
cout<<root->data;
inorderTraversal(root->right);
}
int main() {
treeNode *root = new treeNode(1);
cout << &root << endl;
insert(root, 2);
inorderTraversal(root);
return 0;
}
So I'm pretty tired, but I was whipping some practice questions up for interview prep and for some reason this BST insert is not printing out that any node was added to the tree. Its probably something im glossing over with the pointers, but I can't figure it out. any ideas?
void insert(treeNode *root, int data) {
if (root == NULL) {
cout << &root;
root = new treeNode(data);
}
This change to root is lost as soon as the function ends, it does not modify the root passed as argument but its own copy of it.
Take note that when u insert the node, use pointer to pointer (pointer alone is not enough):
So, here is the fixed code:
void insert(treeNode **root, int data) {
if (*root == NULL) {
cout << root;
*root = new treeNode(data);
}
else if (data < (*root)->data) {
insert(&(*root)->left, data);
}
else {
insert(&(*root)->right, data);
}
}
And in main:
int main() {
treeNode *root = new treeNode(1);
cout << &root << endl;
insert(&root, 2);
inorderTraversal(root);
return 0;
}
Your logic is correct!
The only issue is that when you create a local variable, even if it is a pointer, its scope is local to the function. In your main:
...
insert(root, 2);
...
function call sends a copy of the root which is a pointer to treeNode (not the address of root). Please note that
void insert(treeNode *root, int data)
gets a treeNode pointer as an argument (not the address of the pointer). Attention: This function call may look like "call by pointer" (or reference) but it is actually "call by value". The root you define in the main function and the root inside the insert method have different addresses in the stack (memory) since they are different variables. The former is in main function stack in the memory while the latter is in insert method. Therefore once the function call insert finishes executing, its stack is emptied including the local variable root. For more details on memory refer to: stacks/heaps.
Of course the data in the memory that you allocated using:
*root = new treeNode(data);
still stays in the heap but you have lost the reference to (address of) it once you are out of the insert function.
The solution is either passing the address of original root to the function and modifying it (as K-ballo and dip has suggested) OR returning the modified local root from the function. For the first approach please refer to the code written by dip in his/her answer.
I personally prefer returning the modified root from the function since I find it more convenient especially when implementing other common BST algorithms. Here is your function with a slight modification of your original code:
treeNode* insert(treeNode *root, int data) {
if (root == NULL) {
root = new treeNode(data);
}
else if (data < root->data) {
root->left=insert(root->left, data);
}
else {
root->right=insert(root->right, data);
}
return treeNode;
}
The function call in main will be:
int main() {
treeNode *root = new treeNode(1);
cout << &root << endl;
root = insert(root, 2);
inorderTraversal(root);
return 0;
}
Hope that helps!
After a while seeing some complicated methods of dealing with the Binary tree i wrote a simple program that can create, insert and search a node i hope it will be usefull
/*-----------------------Tree.h-----------------------*/
#include <iostream>
#include <queue>
struct Node
{
int data;
Node * left;
Node * right;
};
// create a node with input data and return the reference of the node just created
Node* CreateNode(int data);
// insert a node with input data based on the root node as origin
void InsertNode (Node* root, int data);
// search a node with specific data based on the root node as origin
Node* SearchNode(Node* root, int data);
here we define the node structure and the functions mentioned above
/*----------------------Tree.cpp--------------*/
#include "Tree.h"
Node* CreateNode(int _data)
{
Node* node = new Node();
node->data=_data;
node->left=nullptr;
node->right=nullptr;
return node;
}
void InsertNode(Node* root, int _data)
{
// create the node to insert
Node* nodeToInsert = CreateNode(_data);
// we use a queue to go through the tree
std::queue<Node*> q;
q.push(root);
while(!q.empty())
{
Node* temp = q.front();
q.pop();
//left check
if(temp->left==nullptr)
{
temp->left=nodeToInsert;
return;
}
else
{
q.push(temp->left);
}
//right check
if(temp->right==nullptr)
{
temp->right=nodeToInsert;
return;
}
else
{
q.push(temp->right);
}
}
}
Node* SearchNode(Node* root, int _data)
{
if(root==nullptr)
return nullptr;
std::queue<Node*> q;
Node* nodeToFound = nullptr;
q.push(root);
while(!q.empty())
{
Node* temp = q.front();
q.pop();
if(temp->data==_data) nodeToFound = temp;
if(temp->left!=nullptr) q.push(temp->left);
if(temp->right!=nullptr) q.push(temp->right);
}
return nodeToFound;
}
int main()
{
// Node * root = CreateNode(1);
// root->left = CreateNode(2);
// root->left->left = CreateNode(3);
// root->left->left->right = CreateNode(5);
// root->right = CreateNode(4);
// Node * node = new Node();
// node = SearchNode(root,3);
// std::cout<<node->right->data<<std::endl;
return 0;
}