I am trying do a simple insert Node to last position of linked list. But I am running into trouble.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
struct Node
{
int data;
struct Node* next;
};
Node* Insert(Node* head, int data);
Node* print(Node* head);
void ReverseIterative();
Node* Insert(Node* head, int data)
{
Node* newNode;
newNode->data = data;
newNode->next = NULL;
if(head == NULL)
{
return newNode;
}
Node* curr=head;
while(curr->next!=NULL)
{
curr=curr->next;
}
curr->next = newNode;
return head;
}
Node* printList(Node* head)
{
while(head)
{
cout<<head->data;
head=head->next;
}
cout<<endl;
}
int main()
{
struct Node* head = NULL;
head = Insert(head, 2);
head = Insert(head, 4);
printList(head);
return 0;
}
I am not sure what im doing wrong. Please help~! I looked over my logic and everything should be correct. It might be the way I am creating a new node in the insert(). I think there is something wrong with my syntax, but i am not sure what it is. I really hate when this happens...
Thanks for your help
In your Insert function, you never allocate newNode.
Node* newNode;
You need to allocate it like so:
Node* newNode = new Node();
The program runs correctly after fixing this, and the output is:
24
http://ideone.com/16XL5W
EDIT:
Regarding your comment below, the following lines do not allocate anything:
Node* newNode;
struct Node* newNode;
They are simply declaring variables, because you have identified them as pointers (*). Pointers simply point to an object on the heap. In order to actually create an object on the heap, you need to use new Node().
The reason your program crashed is because you were trying to access memory from a pointer that hadn't been initialized.
You can use malloc if you want, but you're programming in C++, so as a general rule, never use malloc unless you actually need to.
If you are using a compliant compiler, use shared_ptrs, then you never have to worry about deleteing things that you new.
Aside from the Node* newNode allocation (uninitialized variable error), the following will throw a return value error:
Node* printList(Node* head)
{
while (head)
{
cout << head->data;
head = head->next;
}
cout << endl;
}
You have set Node* as the return type but this function has no return value. Because this function is printing out your list, it does not need to return anything. Change the return type to void.
Related
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.
template<typename T>
List<T>::~List()
{
while(head->next !=NULL){
delete head;
head = head->next;
}
head = NULL;
}
I want to delete all the nodes in the linked list, but I don' t know why the code fail.
Your code fails probably because it invokes undefined behaviour.
delete head;
head = head->next;
You cannot read the memory located where head points after having deleted head.
You should make a copy of head->next to reuse it:
const auto next = head->next;
delete head;
head = next;
I would go with the following solution. No invalid memory access, no memory leak, and it automatically assigns NULL to head before leaving the loop:
template<typename T>
List<T>::~List()
{
while (head)
{
Node<T> *next = head->next;
delete head;
head = next;
}
}
Please note that I made a guess with the node type and you have to replace it by whatever is present in your code.
This can help you in deleting every node of linked list.
List<T> *current = head;
while (current != NULL)
{
next = current->next;
delete current;
current = next;
}
It depends what type the head variable is. If it is the class, you can even use "recursive" deleting in "head" (I mean node) destructor. Something similar to:
Node::~Node(){
if(this->next != nullptr)
delete this->next;
delete this->content;
}
If the node is internal struct, you need temporary pointer to next node as mentioned above:
template<typename T>
List<T>::~List()
{
struct nodeType *temp;
while(head != nullptr){
temp = head->next;
delete head;
head = temp;
}
}
In this case, you don't need to explicitly set head to null, since it is done by the logic of while loop.
In your loop (in question) you don't remove *head node, I don't know if it is expected behavior.
Ad. comment above (I can't put it directly):
while(head->next!=NULL){ Node*next = head->next; delete head; head = next; } head = NULL;
is wrong. It doesn't delete last node on the list (especially if the list has only one object, it won't be 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
}