#include <iostream>
using namespace std;
class Node
{
public:
Node(int N, Node *l, Node *r);
int value; // stored value
Node *left; // left node
Node *right; // right node
};
Node::Node(int N, Node *l, Node *r){
value = N;
left = l;
right = r;
}
void insert(Node *x){
if (x == nullptr) {
Node newNode(5, nullptr, nullptr);
*x = newNode;
}
}
int main(){
Node *root;
root = nullptr;
insert(root);
cout << root->value << endl;
return 0;
}
This is the beginning of a binary search tree. In the insert function, I am trying to change a nullptr to a pointer pointing to a Node object. When I run this c++ code, I get the error: "Segmentation fault: 11". After doing some research, I believe I need to (re)allocate memory. How can I allocate the memory inside of the insert function, if possible?
First up I presume
if (x == nullptr) {
Is a typo? Didn't you mean
if (x != nullptr) {
??
If it is null you shouldn't be going ahead and dereferencing it.
How you fix the crash really depends on how you want the interface to your BST to be.
You are passing in a nullptr and attempting to assign to it. This wont work. You can't assign to nothing.
So you could do something like.
#include <iostream>
using namespace std;
class Node
{
public:
Node(int N, Node *l, Node *r);
int value; // stored value
Node *left; // left node
Node *right; // right node
};
Node::Node(int N, Node *l, Node *r){
value = N;
left = l;
right = r;
}
void insert(Node *x){
if (x != nullptr) {
Node newNode(5, nullptr, nullptr);
*x = newNode;
}
}
int main(){
Node root(2, nullptr, nullptr);
insert(&root);
cout << root.value << endl;
return 0;
}
Here you have an initial object, allocated on the stack, which you can assign to in insert. If you use this method you are wasting some time doing the initial construction of root in function main, when you are always going to go and assign over it.
If you wanted to persist with heap allocation of the Node. Pass a pointer to pointer to insert e.g.
#include <iostream>
using namespace std;
class Node
{
public:
Node(int N, Node *l = nullptr, Node *r = nullptr);
int value; // stored value
Node *left; // left node
Node *right; // right node
};
Node::Node(int N, Node *l, Node *r)
: value(N), left(l), right(r)
{}
void insert(Node **x)
{
if (x != nullptr)
{
Node* n = new Node(5);
*x = n;
}
}
int main()
{
Node *root = nullptr;
insert(&root);
if(root)
{
cout << root->value << endl;
delete root;
}
return 0;
}
This lets insert manage the allocation of the node.
Have you tried to run valgrind? It's a good idea with these kind of errors (and even if you don't see them), it sometime detects error before the symptoms gets visible (the segmentation fault might be just a consequence of an earlier error - if it's not a normal debugger will stop where the segmentation fault occurs).
It points at the fault directly:
void insert(Node *x){
if (x == nullptr) {
Node newNode(5, nullptr, nullptr);
*x = newNode; <<<--- here
}
}
So you basically check if x is null and if it is you tries to dereference and write to the pointed object? That sounds really bad. You're supposed to do the opposite - check and if it's null you do not dereference the pointer.
Related
Try to make tree , have a some troubles, first it's print function - it's print not integers that i put, but print random numbers;
Another trouble its append child - its works only one times;
Will be happy if you will help me with this task.
And also give some good articles about linked lists, trees on c and c++;
#include <iostream>
#include <stdio.h>
using namespace std;
struct Node
{
void* m_pPayload;
Node* m_pParent;
Node* m_Children;
};
struct Person
{
int m_Id;
};
//typedef bool (*NodeComparator)(void* pValue, void* pPayload);
/*bool Comp(void* pValue, void* pPayload)
{
Person* pVal = (Person*)pValue;
Person* pPay = (Person*)pPayload;
if (pVal->m_Id == pPay->m_Id)
return true;
else
return false;
}
*/
Node* NewNode(void* pPayload)
{
Node* pNode = new Node;
pNode->m_pParent = nullptr;
pNode->m_Children = 0;
pNode->m_pPayload = pPayload;
return pNode;
}
Person* NewPerson(int id)
{
Person* p = new Person;
p->m_Id = id;
return p;
}
//Node* FindNode(Node* pParent, Node* m_pPayload, NodeComparator comparator);
void AppendChild(Node* pParent, Node* pNode)
{
if (pParent->m_Children == NULL)
pParent->m_Children = pNode;
}
void print(Node* head)
{
Node* current_node = head;
while (current_node != NULL)
{
printf("%d\n ", current_node->m_pPayload);
current_node = current_node->m_Children;
}
}
int main()
{
Node* T = new Node;
T = NewNode(NewPerson(5));
AppendChild(T, NewNode(NewPerson(11)));
AppendChild(T, NewNode(NewPerson(15)));
print(T);
}
printf("%d\n ", current_node->m_pPayload)
is incorrect. %d wants an integer and it's being given a pointer. The results will be unusual, and likely appear to be random garbage.
printf("%d\n ", ((Person*)current_node->m_pPayload)->m_Id);
^ ^
| Get id from Person
treat payload pointer as pointer to Person
will solve the immediate problem.
Your code actually seems to be pretty messed up with a lot of things going on, here sharing my own commented code from few years back, hope it helps
#include <bits/stdc++.h>
using namespace std;
// Single node representation
struct node {
int data;
node *left, *right;
};
// Declaring temp for refference and root to hold root node
node *root, *temp;
// This function only generates a node and return it to the calling function with data stored in it
node* generateNode(int data){
temp = new node();
temp->data = data;
temp->left = temp->right = NULL;
return temp;
}
// This function actually adds node to the tree
node* addNode(int data, node *ptr = root){
// If the node passed as ptr is NULL
if(ptr == NULL){
ptr = generateNode(data);
return ptr;
}
// Condition to check in which side the data will fit in the tree
else if(ptr->data < data)
//if its in right, calling this function recursively, with the right part of the tree as the root tree
ptr->right = addNode(data, ptr->right);
else
//In case the data fits in left
ptr->left = addNode(data, ptr->left);
//Note: if there is no data in left or roght depending on the data's valid position, this function will get called with NULL as second argument and then the first condition will get triggered
//returning the tree after appending the child
return ptr;
}
//Driver function
int main ()
{
int c, data;
for (;;){
cin >> c;
switch(c){
case 1:
cout << "enter data: ";
cin >> data;
//Updating root as the tree returned by the addNode function after adding a node
root = addNode(data);
break;
default:
exit(0);
break;
}
}
return 0;
}
Please find below a piece of code that should easily get you started. It compiles and it traverse the tree using recursion.
#include <iostream>
#include <vector>
#include <stdio.h>
using namespace std;
struct Node
{
int m_Id;
vector<Node*> m_Children;
Node(const int& id){
m_Id = id;
}
void AppendChild(Node* pNode) {
m_Children.push_back(pNode);
}
void Print() {
printf("%d\n ", m_Id);
}
};
void traverse(Node* head)
{
Node* current_node = head;
current_node->Print();
for(int i = 0; i<current_node->m_Children.size(); i++) {
traverse(current_node->m_Children[i]);
}
}
int main()
{
Node* T0 = new Node(0);
Node* T10 = new Node(10);
T10->AppendChild(new Node(20));
Node* T11 = new Node(11);
Node* T12 = new Node(12);
Node* T22 = new Node(22);
T22->AppendChild(new Node(33));
T12->AppendChild(T22);
T0->AppendChild(T10);
T0->AppendChild(T11);
T0->AppendChild(T12);
traverse(T0);
}
First for printing the node value
Talking about the current mistake that you had committed is in the above code is:
You have not mentioned its pointer to its child (specifically right or left). Due to which it is showing garbage value every time.
For e.g.: print( node->left);
Since you need to type caste it properly to show the data of data.
For e.g.: printf("%d\n ", ((Person*)current_node->m_pPayload)->m_Id);
There is a specific direction in which you want to print data. For trees, there are three directions in which you can print the data of the node and they are as follow:
Left order or Inorder traversal
Preorder traversal
Postorder traversal
This can give you better information about traversal.
Secondly for adding the node to a tree
This might help explain it better.
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;`
I am trying to implement a singly linked list.. I am executing the code on terminal and i get the Segmentation fault (core dumped). I dont understand why is it happening? I read the other answers for the same and unfortunately none of them helped..
Any help will be appreciated..Please explain where did it went wrong? Thanks!
//singly linked list
#include<iostream>
using namespace std;
class node
{
int data;
node *next;
public:
node() //constructor
{
data=0;
next=NULL;
}
void setdata(int x)
{
data=x;
}
void setnext(node *x)
{
next=x;
}
int getdata()
{
return data;
}
node* getnext()
{
return next;
}
};
class list
{
node *head;
public:
list() // constructor
{
head=NULL;
}
void firstnode(int x)
{
node *temp;
temp=new node;
temp->setdata(x);
temp->setnext(head);
head=temp;
}
void insertbeg(int x)
{
node *temp1;
temp1=new node; //Allocate memory to temp1
temp1->setdata(x); // set data in new node to be inserted
temp1->setnext(head); // new node points to previous first node
head=temp1; // head now points to temp1
}
void insertbet(int x,int y)
{
node *temp1;
node *temp2;
temp1=new node; // Allocate memory to temp1
temp2=new node; // Allocate memory to temp2
temp1=head; // point temp1 to head so both of them point to first node
for(int i=0;i<y;i++) // To reach the desired node where data is to be inserted
{
temp1->getnext(); // point to next of node pointed by temp
temp1=temp1->getnext(); // temp1 now contains address of node pointed by next
}
temp2->setdata(x);
temp2->setnext(temp1->getnext()); // insert new node in list
temp1->setnext(temp2); // points the y-1 node to new node
}
void insertend(int x)
{
node *temp1;
node *temp2;
temp1=new node;
temp2=new node;
temp1=head;
while(temp1!=0)
{
temp1=temp1->getnext();
}
temp2->setdata(x);
temp1->setnext(temp2);
temp2->setnext(NULL);
}
void print()
{
node *temp1;
temp1=new node;
temp1=head;
while(temp1!=0)
{
cout<<temp1->getdata()<<endl;;
temp1=temp1->getnext();
}
}
};
int main()
{
list l;
l.firstnode(4);
l.insertbeg(3);
l.insertbeg(4);
l.insertbeg(6);
l.insertend(45);
l.insertend(9);
l.insertbet(2,46);
l.print();
return 0;
}
edit:Sorry guys i am new to coding, i am trying to debug with little progress. I already read the question,the answer is too broad, i need something specific to solve the error.
That's why there are debug tools like gdb (just google for it ;) ).
This is the backtrace:
#0 0x00000000004009ba in node::setnext (this=0x0, x=0x614cc0) at a.cpp:25
#1 0x0000000000400c18 in list::insertend (this=0x7fffffffdf10, x=45) at a.cpp:109
#2 0x00000000004008df in main () at a.cpp:137
that means in line 137 there is a function call (l.insertend(45)), then in line 109, there is the next function call (temp1->setnext(temp2)) and the segfault occurs on line 25 (next = x). This is because the node is not initialised (temp1 is 0 in line 109).
Your while-loop is the problem, if you change is to something like this:
while (temp1->getnext() != 0)
temp1 = temp1->getnext();
This will solve your first issue, but you will get another segfault ;)
Try to solve it on your own with the tools provided. If you still need help, please leave a comment and I will post the answer.
I'm writing a piece of code to append a node to the end of a singly linked list, but it seems that it doesn't append anything at all. Can anybody give me some idea of what I'm doing wrong?
#include<iostream>
using namespace std;
struct Node{
int val;
Node* next;
Node(int v) : val(v), next(NULL) {}
};
void append(Node &head, int d){
Node n = head;
while(n.next != NULL){
n = *n.next;
}
Node end(d);
n.next = &end;
}
int main(){
Node head(0);
for(int i=1;i<5;i++){
append(head, i);
}
Node n = head;
while(n.next != NULL){ //print the linked list, result is 0
cout << n.val<<" ";
n = *n.next;
}
cout<<n.val<<endl;
return 0;
}
EDIT: I changed the append() method to append a dynamically-allocated node each time, but it still doesn't work.
void append(Node &head, int d){
Node n = head;
while(n.next != NULL){
n = *n.next;
}
Node* end = new Node(d);
n.next = end;
}
You append the local object Node end(d); to the end of the linked list. This object is destroyed upon exist from append and the last list element points to a non-existent object.
A few issues with this.
You make a copies in your append function here Node n = head; and here n = *n.next. You then then finally make a change to the copy rather than the original.
You are assigning Node end(d) on the stack. When append returns it goes out of scope and is deleted.
You can fix both with,
#include<iostream>
#include <memory>
using namespace std;
struct Node{
int val;
std::shared_ptr<Node> next;
Node(int v) : val(v), next(nullptr) {}
};
void append(Node &head, int d){
Node* n = &head;
while(n->next != nullptr){
n = n->next.get();
}
n->next = std::make_shared<Node>(d);
}
int main(){
Node head(0);
for(int i=1;i<5;i++){
append(head, i);
}
Node n = head;
while(n.next != nullptr){
cout << n.val<<" ";
n = *n.next;
}
cout<<n.val<<endl;
return 0;
}
For the edited Question:
You are copying the head to n, then modify n. At the end of your append function, n is destroyed, but head was never touched.
This is my first time working with trees. I wrote a c++ code, but it says Segmentation fault (core dumped) , As far as I searched, this error comes from accessing a memory location that may be NULL. I tried 'new' keyword as malloc() should be avoided in c++, But still I didn't get how to resolve this in my code.
# include<iostream>
using namespace std;
struct node
{
int data;
node *left;
node *right;
}*next;
int k=0;
void tree(int i,/*struct*/ node *next = new node)
{
++k; --i;
if (i==0)
return;
//next = new node;
next->data = k*k;
next->left = NULL;
next->right = NULL;
tree(i, next->left);
tree(i, next->right);
return ;
}
void display (node* next)
{
cout<<next->data<<" ";
if (next->left!=NULL)
{
display(next->left);
display(next->right);
}
}
int main()
{
int h;
cout<<"Enter the expected height of tree : ";
cin>>h;
node *root;
root = new node;
root->data=0;
root->left=NULL;
root->right=NULL;
tree(h, (root->left));
tree(h, (root->right));
cout<<root->data<<" ";
display(root->left);
display(root->right);
return 0;
}
There are serious problems with this code. In particular, here:
void display (node* next)
{
cout<<next->data<<" ";
if (next->left!=NULL)
{
...
}
}
You dereference next without ever checking to see whether it's null. And it will be null. That's enough to explain the error you see.
I say that it will be null because of this:
void tree(int i,/*struct*/ node *next = new node)
{
...
return ;
}
...
root->left=NULL;
...
tree(h, (root->left));
...
display(root->left);
The tree function takes its second argument by value-- that means that it does not change the value of root->left. You then call display with a null argument. I suspect that you think void tree(int i,/*struct*/ node *next = new node) means something other than what it actually means.
More fundamentally, you must review the two ways to pass an argument, by reference and by value.
More fundamentally still, you must start with a small, simple program and build up in small steps, rather than trying to write a big complex program all at once.
#include <iostream>
using namespace std;
struct node
{
int data;
struct node *left;
struct node *right;
};
void tree(int i, struct node **root, int k)
{
if (i < 1)
return;
*root = new struct node;
(*root)->data = k*k;
(*root)->left = NULL;
(*root)->right = NULL;
tree(i - 1, &((*root)->left), k + 1);
tree(i - 1, &((*root)->right), k + 1);
}
void display(struct node *root)
{
if (root == NULL)
return;
cout << root->data << " ";
if (root->left != NULL)
display(root->left);
if (root->right != NULL)
display(root->right);
}
int main()
{
struct node *root;
int h;
cout<<"Enter the expected height of tree : ";
cin>>h;
tree(h, &root, 0);
display(root);
return 0;
}
I think you should do some more read up on how pointers works: http://www.tutorialspoint.com/cprogramming/c_pointers.htm
When you where calling tree(h, root->left) you actually just send the pointers value "NULL" == 0x0. As you want to allocate memory for it you should send a reference to the pointer. Hence &root and &((*root)->left). In the display function you have to check for NULL values both for left and right.
The code above is only improved and doesn't handle any freeing of memory, to be able to do that, traverse the tree and use delete on all leafs and work you back to the root.