I have a very simple struct
struct Node{
Node* pNext;
int nValue;
};
and i am trying to always add to the pNext that is not null.
Node *head;
void add(int nValue){
if (!head)
{
Node *node = new Node;
node->nValue=nValue;
head = node;
}
else
{
add(head,nValue);
}
}
void add(Node *pNode, int nValue){
if (!(pNode->pNext))
{
Node *node = new Node;
node->nValue=nValue;
pNode->pNext = node;
}
else
{
add(pNode->pNext,nValue);
}
}
When I call add(10); the first time, it sets the head pointer to an instantiated node. but when I call the method again add(9); i get an "Access violation reading location 0xCDCDCDCD".
My question is, how can i check if the pNext node is assigned an address or not?
i tried using the == nullptr but to no avail.
You didn't initialize the pNext pointer, so it has probably some random value.
Try to use this declaration :
struct Node{
//Default constructor, which sets all values to something meaningful
Node():pNext(nullptr), nValue(0) {}
Node* pNext;
int nValue;
};
Change your code to:
Node *head;
void add(int nValue){
if (!head)
{
Node *node = new Node;
node->nValue=nValue;
**node->pNext =NULL;**
head = node;
}
else
{
add(head,nValue);
}
}
void add(Node *pNode, int nValue){
if (!(pNode->pNext))
{
Node *node = new Node;
node->nValue=nValue;
**node->pNext =NULL;**
pNode->pNext = node;
}
else
{
add(pNode->pNext,nValue);
}
}
You're forgetting both to set head to NULL to begin with, and to set pNext to NULL in your newly created nodes.
As opposed to e.g. Java, C++ doesn't automatically initialize variables to 0 (or the equivalent).
you need to initialize pNext properly by setting it to nullptr explicitly in node's constructor. 0xCDCDCDCD is always in indicator for accessing uninitialized memory.
Related
This question already has answers here:
Binary Search Tree Destructor
(6 answers)
Closed 2 years ago.
Please help me. I am stuck at this.
What am I trying to do: Binary search tree.
I am a C# developer and I learn C++ for about 2 weeks, therefore don't be so harsh with me and that's why pointers are still difficult for me.
I have a struct Node
struct Node
{
int Value;
Node* _LeftNode;
Node* _RightNode;
Node(int value)
: Value(value), _LeftNode(NULL), _RightNode(NULL)
{
}
};
and a Delete() function in BinarySearchTree.cpp
void BinarySearchТрее::Delete(Node* node)
{
if (node)
{
Delete(node->_LeftNode);
Delete(node->_RightNode);
delete(node);
node = NULL;
}
}
I want to delete the node and all of its child nodes.
When I first step in the recursion... For example:
I have two child nodes with values 10 and 19.
With recursion, I delete the nodes and set the pointers to NULL.
And here is the problem:
When I came out from the recursion the nodes are not NULL, but something strange.
And this is my problem. Why when I am in the recursion and I NULL the pointer everything is fine, but when I come out the pointer is something else.
As I talked in the comments, I think the thing is that how we can reset the pointer of the parent's(left or right child) of the initially passed node. (recursively deleting a node and its all children looks good.)
And I don't think it is possible in your current design. As Node does not contain a pointer to its parent, so there is no way to know who's the parent. node = NULL sets just the argument(local variable)'s value so it is pointless.
The C++ way would be to use std::unique_ptr.
struct Node
{
int Value;
std::unique_ptr<Node> LeftNode;
std::unique_ptr<Node> RightNode;
Node(int value)
: Value(value)
{
}
};
Then to destroy a node and all of its children, you'd call reset on the appropriate std::unique_ptr<Node>
I think what you actually want ist this:
struct Node
{
int Value;
Node* _LeftNode;
Node* _RightNode;
Node(int value)
: Value(value), _LeftNode(NULL), _RightNode(NULL)
{
}
~Node() {
delete _LeftNode;
delete _RightNode;
}
};
This way you are using the destructor to clean up recursivly.
delete nullptr is ok btw.
EDIT:
the unique_ptr<> usage in one of the other answers is probably the smarter way to do this.
Given:
struct Node
{
int data = 0;
struct Node * left = nullptr, * right = nullptr;
Node(int data) { this->data = data; }
};
This recursive function deletes a node & its childs (+ one comment):
void DeleteTree(struct Node* node) // A copy of the caller pointer
{
if (node)
{
DeleteTree(node->left); // Recur on left subtree
DeleteTree(node->right); // Recur on right subtree
delete node;
// node = nullptr; <-- This line is useless
}
}
To your wondering "but when I come out the pointer is something else":
There is no point in node = nullptr line, since when you call DeleteTree(my_node) function, node is a copy of my_mode, so when you set node = nullptr it has no effect on my_node that on exit from DeleteTree(my_node) points to a deleted, invalid object.
--
Possible solution:
#define DELETE_TREE(node) DeleteTree(node); node = nullptr; // Macro
int main()
{
struct Node* root = new Node(1);
root->left = new Node(2);
root->right = new Node(3);
root->left->left = new Node(4);
root->left->right = new Node(5);
DELETE_TREE(root->left); // root->left became nullptr
DELETE_TREE(root); // root became nullptr
return 0;
}
After DeleteTree function, the caller pointer points to an invalid object since its object already released. A possible solution is to define a DELETE_TREE Macro to "auto-nullify" the caller pointer after DeleteTree function.
--
Implementation with Modern C++ Smart Pointers:
#include <memory>
struct Node
{
int data = 0;
std::unique_ptr<Node> left, right;
Node(int data) { this->data = data; }
};
int main()
{
std::unique_ptr<Node> root;
root = std::make_unique<Node>(1);
root->left = std::make_unique<Node>(2);
root->right = std::make_unique<Node>(3);
root->left->left = std::make_unique<Node>(4);
root->left->right = std::make_unique<Node>(5);
root.reset();
return 0;
}
I am a beginner in C++, I was implementing simple linked list in C++. While I try to add a second element to list, the pointer for next element in the head is changing
int main()
{
LinkedList ll;
string test;
test="we";
ll.add("we");
ll.add("are");
cout << "ok working" << endl;
return 0;
}
class LinkedList
{
public:
LinkedList();
void add(string data);
protected:
private:
class node{
private:
string data;
public:
node *next;
node(string data,node *next);
node(string data);
node();
};
node *head;
};
LinkedList::LinkedList()
{
head=NULL;
cout<<"ok";
}
void LinkedList::add(string data){
if(!head){
node tmphead(data,NULL);
this->head=&tmphead;
}else{
node *temp;
temp=head;
while(temp->next){
temp=temp->next;
}
node newnode(data);
temp->next=&newnode;
}
}
LinkedList::node::node(string data,node *next){
LinkedList::node::data=data;
LinkedList::node::next=next;
cout<<"New node created with : "+data<< endl;
}
LinkedList::node::node(){
LinkedList::node::data="";
LinkedList::node::next=NULL;
//LinkedList::node::
//this->data="";
//this->next=NULL;
}
LinkedList::node::node(string data){
LinkedList::node::data=data;
LinkedList::node::next=NULL;
}
when adding "we", head-> next is 0x0. Once the control goes to the add function again for "are", the head->next is 0x3. It is getting changes automatically.
Any help is really appreciated.
The problem is you are building a dynamic structure without using dynamic memory. The lifetime of the variables tmphead and newnode is limited to the add() call, so their addresses become invalid on exit. Please review new and delete sections in some tutorial
You're assigning pointer to local variable to head. That's really bad.
if(!head){
node tmphead(data,NULL);
this->head=&tmphead;
} // After this bracket, tmphead was dealocated
When you do this kinda stuff, anything can happen since you're accessing memory that is not allocated to you any more.
Same here:
node newnode(data);
temp->next=&newnode;
// after function exits, `temp->next` points to deallocated memory
Instead, use new in both cases:
void LinkedList::add(string data){
if(!head){
this->head = new node(data, nullptr);
}else{
node* temp;
temp=head;
while(temp->next){
temp = temp->next;
}
temp->next = new node(data);
}
}
Also, remember to create some way to delete everything you created using new.
For example:
LinkedList::~LinkedList() {
delete head;
}
node::~node() {
// WARNING: this is recursive
// that's not bad but it's important to be aware of it
if(next != nullptr)
delete next;
}
You don't need to delete the string data - it's destructor is called automatically when node is deleted.
Code:
#include <iostream>
using namespace std;
class Node {
public:
Node *next;
int value;
Node(int value) {
this->next = nullptr;
this->value = value;
}
};
class LinkedList {
private:
Node *head;
Node *tail;
public:
LinkedList() {
this->head = nullptr;
this->tail = nullptr;
}
void addToEnd(int value) {
if(head == nullptr)
this->head = new Node(value);
else
this->tail->next = new Node(value);
this->tail = this->tail->next;
}
void print() {
for(Node *n = this->head; n != nullptr; n = n->next)
cout<<n->value<<" ";
cout<<endl;
}
};
int main() {
LinkedList *list = new LinkedList();
list->addToEnd(21);
list->addToEnd(25);
list->addToEnd(56);
list->addToEnd(24);
list->print();
return 0;
}
My problem is, when I am assigning an instance of Node to this->head, the program crashes. Is there different way of assigning an instance to a pointer that was initially nullptr?
This code structure works fine on Java, I came from Java, that is why I have difficulty on C++'s pointers.
EDIT
I pasted the right code now, I'm sure. Sorry.
Ok, I have solved the problem. So, the problem is not about allocating an object to a class member, but, the problem is accessing a nullptr member: this->tail.
I edited this method, and the program now runs the way I wanted.
void addToEnd(int value) {
Node *n = new Node(value);
if(head == nullptr)
this->head = n;
else
this->tail->next = n;
this->tail = n;
}
Thanks for your help people, this question is now SOLVED. :)
I don't know about "it crashes", but the following line is not valid:
this->head = Node(value);
head is a pointer-to-Node but you're trying to assign a Node to it. Even if this automatically took the address of the temporary you created on the RHS (which it doesn't), you'd have a pointer to a local variable that doesn't exist for very long.
You should be getting a compilation error for that.
You'd have to use new to create a new object dynamically — be sure to write code to free that memory later!
You're similarly messing up dynamic memory allocation in main, where you have a needless memory leak. LinkedList list; will do fine, there.
You need to allocate memory for your Node instances. The quickest way is to call new Node(value) wherever you call Node(value). However if I were you I'd consider using shared_ptr<Node> rather than plain pointers.
I am trying to create a function that adds a node to the end of a LinkedList. I know how to do it using loops, but my professor wants it done a certain way and I don't understand why it's not working. He practically gave us all the code for it..
This is the pseudo-code he gave us:
process append(data)
if (not the end)
next->append(data);
else
next=new Node();
next->data=data;
next->data = nullptr;
And this is what I came up with:
struct Node {
int data;
Node* next;
};
struct LinkedList {
Node* head;
LinkedList() {head = nullptr;}
void prepend(int data) {
if (head == nullptr) {
Node* tmp = new Node();
tmp->data=data;
tmp->next=nullptr;
}
else {
Node* tmp = new Node();
tmp->data=data;
tmp->next=head;
head=tmp;
}
}
void append(int data) {
Node* tmp = head;
if (tmp->next != nullptr) {
tmp=tmp->next->append(data);
}
else {
tmp->next = new Node();
tmp->next->data = data;
tmp->next->next = nullptr;
}
}
};
int main()
{
LinkedList LL = LinkedList();
LL.prepend(7);
LL.append(6);
std::cout << LL.head->data << std::endl;
}
My prepend (to add to the beginning of the LinkedList) works fine, but when I try this code, I get
main.cpp:48:20: error: 'struct Node' has no member named 'append'
tmp->next->append(data);
So I'm pretty sure that there's something wrong with saying next->append(data), which from what I understood, is supposed to be recursively calling back the append function until it reaches a nullpointer. I'm thinking maybe there's some sort of way to write it, but people in my class are telling me that the next->append(data) thing SHOULD work, so I guess I'm not exactly sure why this isn't doing anything. I tried instead writing the append function in the Node struct, but then it says that head wasn't declared in the scope and I really just don't know how to work with this. I'm also sort of new to classes/structs in C++ so I'm assuming it's something about that that I'm not understanding.
The class Node has not any method named append so you get that error message:
tmp->next->append(data);
^^^^^^^^^^^^^
struct Node {
int data;
Node* next;
};
To append a node to a linked-list, you don't need an append method within Node. Remove that. Correct the append process in LinkedList::append:
void append(int data) {
Node* tmp = head;
while (tmp->next)
tmp = tmp->next;
tmp->next = new Node();
tmp->next->data = data;
tmp->next->next = nullptr;
}
I did't test, but you need something like above code. At first, it tries to access to the end of list. Then it appends a node.
Recursive implementation:
void append(int data) {
append(data, head);
}
void append(int data, Node *node) {
if (node->next)
append(data, node->next);
else {
tmp->next = new Node();
tmp->next->data = data;
tmp->next->next = nullptr;
}
}
Your append method isn't defined on the Struct Node. Instead it's defined on the LinkedList class so you need to invoke it accordingly. You can redefine the append method to take a node as a parameter or add an append method to the Struct Node itself. Also there's no need to assign the result of append to tmp =
Your append method is void.
tmp->next is a Node, so to call append function, you must declare it in Node struct
Like this
struct Node
{
void append(int data)
{
if (next)
next->append(data);
else
{
next = new Node();
next->data = data;
next->next= nullptr;
}
}
int data;
Node* next;
};
it's clear from the pseudo code next->append(data); that append is meant to be a member of Node.
Here's how you might use Node::append from LinkedList::append
class LinkedList {
void append(int data) {
if (head == nullptr) {
head = new Node();
head->data=data;
head->next=nullptr;
}
else {
head->append(data);
}
}
}
The node structure does not contain any append method.
Moreover, you are splitting work that can be done in one methos to two methods, writing more code.
See my answer to another question here with working code I wrote
https://stackoverflow.com/a/37358192/6341507
As you can see, I solve all in method
AddItem(int i)
I start seeing that creating linked list i kindof har for many people here, so I will further edit my answer there to provide additional information.
Good luck!
How do you allocate memory for an link list when passing its reference instead of its pointer?
For example:
struct node {
string info;
node *next;
};
void add(node &aNode){
//if I use
node *newNode;
newNode = new node;
aNode.next = newNode; //aNode.next = newNode; doesn't work either
//allocating on heap seems to give segmentation error.
}
int main() {
node *aNode;
aNode = new node;
add (aNode);
}
Compiler error: error: invalid initialization of reference of type ‘node&’ from expr
alternatively if I use
int main() {
node aNode;
add (aNode);
add (aNode);
aNode.next->next->info = "abc";
string a = aNode.next->next->info;
}
This give segmentation fault.
So is it possible to allocate for an linked list just with its reference? (this is C++)
It should be
node * newNode = new node;
aNode.next = newNode
You have to take care of deletion manually, e.g. check if aNode.next isn't already occupied (and delete if it is).
Further, the add function signature should read:
void add(node & aNode) { ... }
By the way, the STL comes with a nice <forward_list> ;-)
It's hard to tell what you're actually asking, but going by the question title perhaps you have in mind a node structure like this:
struct Node {
Node & next;
/* payload data */
Node(Node & n) : next(n) /* ... */ { }
};
Such a node would store its successor "by reference"; but you would have to initialize it with an existing node! (There is no such thing as a "null" reference.) By the Poultry-Oval Impasse, you cannot do this.
Alright, while you continue to refuse to post your full code, here is my almost literal copy/paste of your code which works fine with me:
Update: I'm adding a feature to add a node at the end, which you might want.
#include <string>
struct node {
std::string info;
node *next;
node(std::string i = "") : info(i), next(NULL) { }
};
void add(node &aNode)
{
node *newNode;
newNode = new node;
aNode.next = newNode;
}
void add_at_end(node &aNode, std::string value = "")
{
node *newNode, *n = &aNode;
while (n->next) n = n->next; // move to the end
newNode = new node(value);
n->next = newNode;
}
int main()
{
node aNode, bNode;
add(aNode);
add_at_end(bNode, "Hello");
add_at_end(bNode, "World");
add_at_end(bNode, "!");
}
Compile with g++ -o prog prog.cpp -W -Wall -pedantic.
Finally, here's the STL way of achieving the same thing:
#include <forward_list>
#include <string>
int main() {
std::forward_list<std::string> bList;
bList.push_front("Hello");
bList.push_front("World");
bList.push_front("!");
}
In your second variant of main(), you are calling add(aNode) twice. But you're providing it the same parameter each time. So although you're creating two new node objects, one of them is lost forever (a memory leak). And aNode.next ends up pointing to the other one. aNode.next->next is not a valid pointer, hence the seg-fault when you try to access something through it.
Depending on what you want to achieve, you could try this:
node aNode;
add(aNode); // Basically does: aNode.next = new node;
add(*aNode.next); // Basically does: aNode.next->next = new node;
There are better ways of doing linked-lists, but this would at least avoid the seg-fault.
Try
int main() {
node *aNode;
aNode = new node;
add (*aNode);
}
You have to pass reference to object, not a pointer.
I checked your code and I didn't get segmentation fault when allocating on stack: http://ideone.com/gTRIG.
My proposition:
#include <string>
using namespace std;
struct node {
string info;
node *next;
node(string str): info(str), next(NULL) {}
~node() { if(next != NULL) delete next; }
node *add(string info){
node *newNode = new node(info);
return aNode.next = newNode;
}
};
int main(){
node rootNode("My rootnode");
node *nxt = rootNode.add("Next node");
nxt->add("Last node");
// No need to call delete, because destructor will clear heap
}