Node is null even though it has a value? - c++

I'm trying to make a binary search tree based on an array of integers.
I've created a function BST that takes an array and its size as a parameter. Now I'm calling another function makeBST on every item of the array that takes the root node and that value. It creates another node and attach it with the root node based on the value.
But the makeBST function is not recursing over itself and executing the NULL condition for every value of the array, even though root node is not null
#include<iostream>
#include<cmath>
using namespace std;
class Node {
public:
int data;
Node *left;
Node *right;
};
Node *newNode(int x){
Node *node = new Node();
node->data = x;
node->left=NULL;
node->right = NULL;
return node;
};
void makeBST(Node *node, int x){
if(node==NULL){
// keep getting executed even though root node has a value.
// here must be error.
cout << " NULL condition " << endl;
node = newNode(x);
return;
};
if((node->data) > x){
cout << "also working" << endl;
makeBST(node->left,x);
}else if((node->data) < x){
makeBST(node->right,x);
};
};
Node *BST(int arr[], int n){
Node *root = newNode(arr[0]);
for(int i=1; i<=n-1; i++){
cout << "loop" << i << endl;
makeBST(root,arr[i]);
};
return root;
};
int main(){
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int n=10;
Node *root = BST(arr,n);
return 0;
};
I know this is not the best way of creating Binary search tree. But I'm a beginner and this is what i could come up with.
Can anyone help?

currently, you are changing the local value for (*node) in the function without have any effect on the variable node passing to it. You should read about passing pointers as value vs. as reference.
If you want to change node you need to pass it as reference:
void makeBST(Node **node, int x) {
if(*node==NULL){
cout << " NULL condition " << endl;
node = &newNode(x);
return;
};
if((*node->data) > x){
cout << "also working" << endl;
makeBST(&(*node->left),x);
}else if((*node->data) < x){
makeBST(&(*node->right),x);
};
};
Make sure you pass the address of the node when calling makeBST.

Related

Using pointers with recursion

I want to have a node that will be able to point to another node through the function insert. However, I've messed up somehow so that the pointer p does not point to the next Node. I'm unsure of how to use my function in a way such that it will point to the recurred variable a.
This issue is occurring on a AVL tree assignment I've been working on. I've recreated the error in a simpler fashion in the below code.
#include <iostream>
using namespace std;
struct Node {
int data;
Node *next = NULL;
};
Node* insert(Node *a) {
cout << "inserter" << endl;
if (a != NULL) {
a->next = insert(a->next);
}
else {
cout << "inserting" << endl;
Node *a = new Node;
a->data = 10;
a->next = NULL;
}
return a;
}
int main() {
Node *p = new Node;
p->data = 5;
insert(p);
cout << "please" << endl;
cout << p->data << endl;
cout << p->next << endl;
cout << p->next->data << endl;
cout << "done" << endl;
return 0;
}
The output is:
inserter
inserter
inserting
please
5
000000
And then it crashes, as p->next is not pointing to anything. I don't know how I can get it to point to the recurrsed pointer a.
My main objective is to have a->next be changed without using a returning function, instead a void function that can change a->next using an & in the pass by reference. But I'm unsure how to incorporate the & into a pointer. This hasn't been working (Node *&a).
Your main reason for p->next being null is that the pointer you want to return is out of scope when you return it.
Outside of else {}, the new pointer you created is no longer valid.
else {
cout << "inserting" << endl;
a = new Node;
a->data = 10;
a->next = NULL;
}
Because of the Node* before a in your code, you are declaring a new Node pointer, instead of using the one that was passed to the function.
In your code, it doesn't seem like you are implementing a tree. It seems more like you are implementing a linked list.
Whatever. In the way you are doing, you can never track the starting node. You have to save it for traversing the tree/linked list.
struct node
{
int data;
node *next;
};
node *head, *tail;
void createnode(int value)
{
node *temp=new node;
temp->data=value;
temp->next=NULL;
if(head==NULL)
{
head=temp;
tail=temp;
temp=NULL;
}
else
{
tail->next=temp;
tail=temp;
}
}

Inserting a single element in a linked list gives a segmentation fault - C++

The below code intends to perform insertion of a single element in a linked list and then print it. Although, I am getting a segmentation fault while printing the value in main function. Could you please help me identify what is wrong with it ?
I have tried to print the value of data in the insert function and it works fine which means the creation of new node and assignment of the value to it is working fine.
#include<iostream>
using namespace std;
struct Node {
int data;
Node* next;
};
//insert a new node
Node* insertNode(int data,Node* head)
{
Node* cNode = head;
if (!head)
{
head = new Node;
head->data = data;
head->next = NULL;
}
else
{
while(cNode->next)
{
cNode = cNode->next;
}
cNode->next = new Node;
cNode->next->data = data;
cNode->next->next = NULL;
}
return head;
}
// print a list
void print(Node* head)
{
/*while(head->next)
{
cout << head->data << " ";
head = head->next;
}*/
cout << "printing data" << endl;
cout << "data : " << head->data;
}
int main()
{
cout << "inside main" << endl;
Node* aNode = NULL;
insertNode(2,aNode);
print(aNode);
return 0;
}
I expect the print function to print the value of data for the single node that I created .
Your head parameter in insertNode function should be a reference (or a pointer to pointer to Node). Beacause in the current form, it is an input parameter, but you need to be in-out parameter. It means that in the current code, your aNode variable is NULL and is always stays NULL.
I recommend this:
void insertNode(int data, Node &head)
Then you create an object in main this way: Node aNode;
It will allow you to update the existing variable directly and you don't need a return value. Also, this way it will be a little bit more C++like, your original code is more like a plain C code.
Or if you want to write it in plain C:
void insertNode(int data, Node **head)
Then you change the call from main: insertNode(2, &aNode);

Function not writing nodes to tree when using recursion

I am a student who is making a tree structure in cpp for a project. The program is supposed to get a string from an input and enter it into a tree. The tree is organized by each node having the pointer to its next sibling (called sibling) and its first child (called child). However, when I try to make a function that recursively adds members to the tree, the function doesn't work. All of the neccisarry steps are completed, yet for some reason the nodes are not linked. Please take a look at my code, and thank you for reading.
#include <iostream>
#include <string>
struct node{
char data;
node *sibling = nullptr;
node *child = nullptr;
};
struct node* newNode(char data, unsigned int m)
{
if(m!=0) {
struct node *node = (struct node *) malloc(sizeof(struct node));
// std::cout << "node write" << std::endl;
node->data = data;
node->sibling = newNode(124,m-1);
node->child = newNode(124,m-1);
return (node);
}
}
char TreeOutput(node *n){
return *(char *)n;
}
void nodeAdd(node *currentNode, std::string str, int m ){
int n = str.length();
if(m<n){
if(TreeOutput(currentNode) == str[m]){
std::cout << m << "1..1" << std::endl;
nodeAdd(currentNode->child,str,m+1);
}
else if(TreeOutput(currentNode) == 124){
std::cout << m << "2..2" << std::endl;
currentNode = newNode(str[m],2);
nodeAdd(currentNode->child,str,m+1);
}
else{
std::cout << m << "3..3" << std::endl;
nodeAdd(currentNode->sibling,str,m+1);
}
}
}
int main() {
struct node *root = newNode('X',6);
std::cout << root->data << std::endl;
nodeAdd(root->child,"APE",0);
std::cout << root << std::endl;
return 0;
}
The reason they're not getting linked in this line:
currentNode = newNode(str[m],2);
Is because you're taking a node* to the function, then assigning the pointer inside the function a new value. So you change currentNode's value inside the function, but not in its parent. You need to take either a reference to the pointer or a double pointer for this to work correctly:
void nodeAdd(node*& currentNode, std::string str, int m )
It might make more sense if we remove the syntactic sugar for pointers. Imagine a pointer to node was written Ptr<node>, if we wrote:
void nodeAdd(Ptr<node> currentNode, std::string str, int m )
It's be obvious we're taking the pointer by value, so it now lives in a variable within the function. If we take it by reference, we can change its value outside the function:
void nodeAdd(Ptr<node>& currentNode, std::string str, int m )
Tangentially, you have char data in your node struct, I think you want a pointer there too (or an array).
In terms of general style, if you're trying to write C++, usually the contents of newNode would go in a constructor so you could just write new node(args...) to create a new instance. The TreeOutput function will work in this case because of the simple layout of node, but in general, casting to the first member of a struct doesn't have to work (in particular in the case of inheritance or virtual methods), so I'd at the very least access the member directly return node->data;

Binary Tree only adding to the the root

I'm writing a simple Binary Tree program in C++ and right now it only stores the most recent value entered at the root node eg. if I enter 10 into the tree then 9 into the tree, 9 just overwrites 10 as the root node so the tree only stores the value 9.
I've looked at multiple C++ Binary Tree solutions online and tried their version of implementing them yet I still get no success.
Here is my struct for a single node in the tree
struct TreeNode{
int value;
TreeNode *left;
TreeNode *right;
TreeNode(int value){
this -> value = value;
left = NULL;
right = NULL;
}
};
My class for the binary tree so far
class IntTree{
private :
TreeNode *root;
public :
IntTree();
TreeNode* getRoot();
void insertValue(TreeNode *root, int intValue);
TreeNode* searchTree(TreeNode *root, int intValue);
void inOrder(TreeNode *root);
void deleteValue(int intValue);
void deleteTree(TreeNode *root);
};
The Insert Method
void IntTree::insertValue(TreeNode *root, int intValue){
if(root == NULL){
root = new TreeNode(intValue);
}
else if(intValue == root->value){
cout << "Value already exists in the tree" << endl;
}
else if(intValue < root->value){
insertValue(root->left, intValue);
}
else{
insertValue(root->right, intValue);
}
}
And then this method is simply called in a menu like this
cout << "Enter Value to Insert : " << endl;
input = readInt();
theTree.insertValue(theTree.getRoot(), input);
The logic all seems fine to me, apart from that I've tried not using a constructor and just induvidually setting the variable, having two functions for inserting one with just the int parameter which so I don't have to use the getRoot() later on and a million other things which I've forgotten
The answer is simple, the pointer you are modifying is only a copy, so the copy is discarded at the end of the function and you have lost memory. You need to take a reference on the pointer to actually modify it (nothing else to modify):
void insertValue(TreeNode *& root, int intValue)
This should work:
New insertvalue function call will look as below
void insertValue(TreeNode **root, int intValue)
{
if(*root == NULL)
{
*root = newNode(intValue);
}
else if(intValue == (*root)->value)
{
cout << "Value already exists in the tree" << endl;
}
else if(intValue < (*root)->value)
{
insertValue(&(*(root))->left, intValue);
}
else
{
insertValue(&(*(root))->right, intValue);
}
}
int main()
{
//initial code
insertvalue(&root,value) //root is a single pointer variable.
//code for printing the tree
}
There are many less complex ways to implement the same. i have just modified your code.

C++ linked list , stack ( sort of )

#include <iostream>
using namespace std;
struct Node
{
int item; // storage for the node's item
Node* next; // pointer to the next node
};
/**************
use reference
**************/
void addNode(Node*& head, int data , int& count)
{
Node * q; // new node
q = new Node; // allocate memory for the new mode
q->item = data; // inserting data for the new node
q->next = head; // point to previous node ?? how would i do that? ( am i doing it correctly?)
count++; // keep track of number of node
head = q;
}
int main()
{
int a, count = 0;
int data;
char callen;
Node *head = NULL;
do
{
cout << "please enter the data for the next node" << endl;
cin >> data;
addNode(head, data, count);
cout << "do you wish to enter another node? (enter true or false)" << endl;
cin >> callen;
}while( callen != 'n' );
// assuming this is the print function
while(head != NULL)
{
cout << "output" << head->item << endl;
head = head->next; //next element
}
system("pause");
return 0;
}
I tried adding a new element in the list how would i move the head around like a LIFO memory (stack) so the last element is on the very top..
Any help would be appreciated ! The pointers and the nodes are messing with my brain lately ....
In the do-while loop try this
addNode(data, count, head);
instead of
addNode( data, count );
Also, change the signature of addNode as follows:
void addNode( int data , int& count , Node*& head)
The code shouldn't compile because you are using the variable head in addNode but head is local to main.
You could use std::stack for LIFO.
int main()
{
int a, count=0;
int data;
bool repeat;
stl::stack<int> lifo;
// assuming it is an empty list at the beginning and crating a new node below
cout << "enter some data" << endl;
cin >> a ;
lifo.push(a);
do
{
cout << "please enter the data for the next node" <<endl;
cin >> data;
lifo.push(data);
cout << "do you wish to enter another node? (enter true or false)" << endl;
cin >> repeat;
}
while (repeat == true);
// assuming this is the print function
while(!lifo.empty()) {
cout << lifo.pop() << endl;
}
system("pause");
return 0;
}
Sounds like you're trying to learn a bit about link lists. Awesome!
Anyway, I'm not going to give you the exact answer, but I'll give you some pointers in pseudo code, in particular for your addNode member function:
Node* addNode(Node* head, int data, int& count)
{
create a new node
let it point to head
return the pointer to the new node for it to become the new head node
}
int main()
{
// code...
head = addNode(head, data, count);
// more code...
}
As a visual:
head
\/
node A->node B->node C
new node->?
new node
\/
node A->node B->node C
The way you're doing it, by implementing your addNode function as a push operation, already moves the head around, so the head will always point to the last element you added.
Therefore, to implement a function to delete the last element added, you just need to write a simple pop operation: copy the address of the head, make the second element the new head, and release the memory at the copied address:
Node* oldHead = head;
head = head->next;
delete oldHead;
return head;
You could try the following modified code.
#include <iostream>
using namespace std;
struct Node
{
int item; // storage for the node's item
Node* next; // pointer to the next node
};
/**************
use reference
**************/
void addNode(Node*& head, int data , int& count)
{
Node * q; // new node
q = new Node; // allocate memory for the new mode
q->item = data; // inserting data for the new node
q->next = head; // point to previous node ?? how would i do that? ( am i doing it correctly?)
count++; // keep track of number of node
head = q;
}
int main()
{
int a, count = 0;
int data;
bool repeat;
Node *head = NULL;
// assuming it is an empty list at the beginning and crating a new node below
Node *temp;
temp = new Node ;
cout << "enter some data" << endl;
cin >> a ;
temp->item = a;
temp->next = head;
head = temp;
//^^ assuming thats creating the first node ^^
do
{
cout << "please enter the data for the next node" << endl;
cin >> data;
addNode(head, data, count);
cout << "do you wish to enter another node? (enter true or false)" << endl;
cin >> repeat;
}
while (repeat == true);
// assuming this is the print function
temp = head;
while(temp != NULL)
{
cout << "output" << temp->item << endl;
temp = temp->next; //next element
}
return 0;
}