Function not writing nodes to tree when using recursion - c++

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;

Related

How to access user-chosen struct variable C++

I am using a function to print out data from a linked list, the list Nodes have 2 variables which could be accessed, data or index. I want to add a parameter to the print() function that allows the user to call the variables name within the Node that they want to be outputted, I've heard of passing by reference and I'm pretty sure this is what I want to do but haven't found any resources that actually work for my code.
(simply I want to pass a variable name to a function).
here is my code:
struct Node {
int data;
int index;
Node *next;
}
Node *_current;
Node *_next;
Node *_head;
Node *_temp;
Node *_tail;
Node *_last;
// all this is handled correctly
void print(*variable name*) {
Node *n = _head;
while (n->next != nullptr) {
std::cout << n-> *variable name* << std::endl;
n = n->next;
}
}
p.s: variable name is not necessarily a pointer but just (literally) referring to the variable name parameter I want to add.
this code works if I swap out variable name to 'std::cout << n->data <<...' and runs without any other issues. (btw Whole code isn't provided just the parts needed to explain what I want to change)
any helpful information is greatly appreciated, Thank you in advance. :)
p.s: variable name is not necessarily a pointer
But it is a pointer. A member pointer, specifically:
void print(int Node::*member) {
Node *n = _head;
while (n->next != nullptr) {
std::cout << n->*member << std::endl;
n = n->next;
}
}
It would get invoked as either
print(&Node::data);
or
print(&Node::index);
You can pass in a string.
void print(const string& str) {
Node *n = _head;
if(str.compare("index")==0){
while (n->next != nullptr) {
std::cout << n->index << std::endl;
n = n->next;
}
}
else if(str.compare("data")==0){
while (n->next != nullptr) {
std::cout << n->data << std::endl;
n = n->next;
}
}
}

Linked list has different behaviour for similar pointer assignment

I am writing a code to delete a node from a linked list when only the pointer to the node is given and the head node is not given
/*
struct Node {
int data;
struct Node *next;
Node(int x) {
data = x;
next = NULL;
}
}*head;
*/
// This function should delete node from linked list. The function
// may assume that node exists in linked list and is not last node
// node: reference to the node which is to be deleted
void deleteNode(Node *node)
{
node=(node->next);
}
does not delete the present pointer in the list, but,
/*
struct Node {
int data;
struct Node *next;
Node(int x) {
data = x;
next = NULL;
}
}*head;
*/
// This function should delete node from linked list. The function
// may assume that node exists in linked list and is not last node
// node: reference to the node which is to be deleted
void deleteNode(Node *node)
{
*node=*(node->next);
}
Deletes the node from the linked list
Why? what is the difference between the approach?
let's take a simpler example with integers instead of nodes:
void Modify_1 (int *piVal, int *piNewVal)
{
//piVal has adresse of i passed as argument
// similar to node = (node->next);
piVal = piNewVal; // This change just the VALUE of the pointer passed as argument !
//piVal has adresse of j now
}
void Modify_2 (int *piVal)
{
// similar to *node=*(node->next);
*piVal = 0; // This change de content of pointer
}
int main ()
{
int i = 3;
int j = 5;
Modify_1 (&i, &j);
cout << i << endl; // This print 3 !
Modify_2 (&i);
cout << i << endl; // This print 0
return 0;
}
piVal is a pointer that contains i address VALUE. Exemple : 0x00bcfdb4
This address is passed as a value (0x00bcfdb4) if you want to function.
As long as you do not write *piVal, you are not going to change the pointed content but just the VALUE of the address.
If you want to change the pointer, you need an **int (in your case **node)
void Modify_3 (int **piVal, int *piNewVal)
{
*piVal = piNewVal; // this change de pointer adresse
}
int main ()
{
int x = 5;
int *pi = &x;
Modify_3 (&pi, &x);
cout << *pi << endl; // This print 5
}
Assigning to a (non-reference) argument of a function has no effect outside that function.
(The most important thing to learn about pointers is that there is nothing special about pointers.)
It's the same as how
void f(int x) { x = 1000; }
int main()
{
int x = 0;
f(x);
std::cout << x << std::endl;
}
will print 0, not 1000.
Thus, your first attempt does not modify anything and has no observable effect.
Your second attempt also has a problem - it copies the next node but doesn't delete it.
If your nodes are dynamically alloacted, and they usually are, this is a memory leak.
You need something like this:
void deleteNode(Node *node)
{
Node* old = node->next;
*node = *(node->next);
delete old;
}
It's a bit unconventional to modify a list by copying nodes, though, since it is very inefficent if the node's data is big.
Usually, you update the links in the list, but in order to do that you need to know what the previous node is.
To delete a node from a linked list when only the pointer to the node is given - that's possible only in doubly linked list or in indexed list. The nature of list itself says that you have to modify another node to remove one from existing chain.
In first case node contains pointer to previous node and cost is O(1), while with indexed list you have index (key) and access to mapping\indexing mechanism, cost of getting previous node depends on method used. For the last reason indexed lists are sometimes implemented as doubly-linked.

Node is null even though it has a value?

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.

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);

I Am Having Issues with Passing Struct Pointers

I am issues with a homework assignment. We are working on binary trees and whenever I try to pass my head node to my insert() function the node is not being changed. This has lead me to believe that I am somehow not passing by reference, I just can't figure out where the mistake is, however. Thank you for any help in advance.
/*Linked List
**Code inspired by Linked List by Daniel Ross
**Code written by Collin Bardini
**Assignment 6
*/
#include <iostream>
using namespace std;
//Our node
struct node {
int data;
node* left; //lower
node* right; //greater
};
//function declarations
void insert(node * head, int);
void print_preorder(node * root);
void print_postorder(node * root);
void print_inorder(node * root);
int search(int data, node * root);
//main for testing the access functions
void main(void)
{
node* headA = 0;
node* headB = 0;
const size_t as = 7;
const size_t bs = 100;
int a[as] = {1,5,4,6,7,2,3};
int b[bs] = {118,119,158,166,163,123,108,116,117,184,165,137,141,111,138,122,109,194,143,183,178,173,139,
126,170,190,140,188,120,195,113,104,193,181,185,198,103,182,136,115,191,144,145,155,153,151,
112,129,199,135,146,157,176,159,196,121,105,131,154,107,110,175,187,134,132,179,133,102,172,
106,177,171,156,168,161,149,124,189,167,174,147,148,197,160,130,164,152,142,162,150,186,169,
127,114,192,180,101,125,128,100 };
for (int i = 0; i < as; i++)
insert(headA, a[i]);
for (int i = 0; i < bs; i++)
insert(headB, b[i]);
print_preorder(headA);
cout << "search 196: " << search(196, headB) << endl <<
"search 137: " << search(137, headB) << endl <<
"search 102: " << search(102, headB) << endl <<
"search 190: " << search(190, headB) << endl;
}
// creates a new node and inserts it in the correct location in the tree
void insert(node * head, int d)
{
//make a new node
node *p = new node;
p->right = 0;
p->left = 0;
p->data = d;
if (head == 0) //list is empty
head = p;
else //append to tail end
{
node* c1 = head;
node* c2 = head;
while (c1)
{
if (d > c1->data)
{
c2 = c1;
c1 = c1->right;
}
else
{
c2 = c1;
c1 = c1->left;
}
}
if (d > c2->data)
c2->right = p;
else
c2->left = p;
}
}
Short answer: see my answer to this identical question and use double pointers in the insert() function.
Regarding the "pass-by-reference" part of the question, well it depends on what exactly you mean by these words. You are passing the node by reference, true, but you're passing the pointer to the node by value. Remember that pointer is just another variable holding a non-negative integer value (overly simplified, but still true).
Long answer: the modifying functions should use either double pointers or references to pointers. The reason is that, in a function definition like void insert(node * head, int d) { /*...*/ }, the pointer itself is passed by value. That is, a temporary copy of the original pointer is created, and modified inside the function. The actual pointer remains unchanged. I.e., in these lines:
// definition
if (head == 0) //list is empty
head = p;
// client code
for (int i = 0; i < as; i++)
insert(headA, a[i]);
The temporary local variable head is modified, not the headA variable that you pass to the function. See the linked question where I posted a schematics of what happens with the pointer values in this situation.
You can change to e.g. double pointers like so:
void insert(node ** head, int d) {
// snip...
if (*head == 0) //list is empty
*head = p;
Or pass the pointer by reference.
Note: for read-only functions, such as print...(), you don't need to use a double pointer or any other pass-by-reference mechanism.