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).
Related
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.
struct Node {
int value;
Node* next;
~Node() {
delete next;
}
};
Node* deleteList(Node* p) {
if(p == nullptr) return nullptr;
Node* pNext = p->next;
delete p;
return deleteList(pNext);
}
the compiler said something about bad access.
I tried to set breakpoint to debug it. If the linked list is [3, 2, 1], it first delete the 3, then 2 and 1, and then jump back to 2, then encountered exception.
Can someone tell me what is the problem?
The destructor for the Node struct already calls delete on "next". Therefore, it goes to "next" and calls its destructor, and so on. All nodes following p in the linked list will then be deleted just by calling delete p; (where p is a Node*).
I recommend you get rid of the Node's destructor to prevent this chain destruction from occurring.
struct Node {
int value;
Node* next;
};
As a side note, while I don't know the rest of your code I don't see a reason as to why deleteList(Node* p) should return a Node* (as it will always be nullptr, no interesting results are returned).
void deleteList(Node* p)
{
if(p == nullptr) return;
Node* pNext = p->next;
delete p;
deleteList(pNext);
}
If the linked list is: [3, 2, 1], when you call deleteList, the following things happen:
p = 3, pNext = 2, 3 was deleted by delete p; Then the destructor was called, so delete next would delete 2 and 1 recursively.
then after delete p in deleteList function, deleteList(pNext) was called again, so this time: p = 2, pNext = 1, since 2 was already deleted in the previous step, it would corrupt when you call delete p again.
So please remove the delete next; in ~Node().
Actually I don't see reason why deleteList should be used, because it would always return nullptr and delete all the nodes. So why not remove the deleteList function, and keep the delete next; in ~Node(). You can delete the created Node object directly.
And of course the best way to do this task is: std::list.
I would wager a guess that you are experiencing delete being called multiple times on an instance that has already been deleted. When you call delete p;, p's destructor is getting called, and it is deleting the next node in the list. You then recursively call deleteList, passing it the node that was just deleted by p's destructor, making the pointer you are holding invalid.
What you need to do is determine whether the Node owns the Node that follows it in the list (that is, is it responsible for cleaning it up), or will some outside code take care of that. You cannot do both.
Edit:
As an aside, what you really want is not to have a recursive delete function, but rather a loop within your deleteList function. Something like ...
struct Node {
int value;
Node* next;
};
// Loop in the function; recursion not required, and no return value.
void delete_list(Node* n)
{
Node* tmp;
while (nullptr != n) {
tmp = n->next;
delete n;
n = tmp;
}
}
In this case, the Node instance does not own its sibling Node (Node.next), and takes no responsibility for deallocating it; that is up to the delete_list function.
Remove the line delete next; from the destructor of Node.
I think there may be two choices for you.
first, as R Sahu said, remove the delete next in destructor.
struct Node {
int value;
Node* next;
};
Node* deleteList(Node* p) {
if(p == nullptr) return nullptr;
Node* pNext = p->next;
delete p;
return deleteList(pNext);
}
second, just delete the head node of the link in deleteList, but not delete nodes recursively.
struct Node {
int value;
Node* next;
Node() : value(0), next(nullptr)
{}
~Node() {
if (next != nullptr)
{
delete next;
}
}
};
Node* deleteList(Node* p) {
if (p != nullptr)
{
delete p;
}
return nullptr; // in fact your code always return nullptr. so it just return nullptr here.
}
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!
I have a linked_list and currently my destructor is not working properly. Not entirely sure why.
Can somebody explain me how to solve this?
class linked_list {
private:
struct node
{
// String in this node
std::string data;
// Pointer to next node
struct node *next;
};
//First item in the list
struct node *first;
Here is my destructor
linked_list::~linked_list(void)
{
while (first)
{
delete first;
first = first->next;
}
}
The problem lies here:
delete first;
first = first->next;
When you delete first, but then try to access first->next. Cache first->next into a temp variable of type node*, then do delete first to fix this:
struct node* temp;
while (first != NULL)
{
temp = first->next;
delete first;
first = temp;
}
change to
linked_list::~linked_list(void)
{
struct node *next;
while (first != NULL)
{
next = first->next;
delete first;
first = next;
}
}
When you 'delete' first, you actually clear all the links from it. Now, if you try to access some other node using this, will not produce the required result.
First, you have to point that node with some other pointer, so that you still have some link which you can access later.
class List {
ListNode *head;
ListNode *prev;
};
class ListNode {
int data;
ListNode *next;
friend class List;
ListNode(int d, ListNode *n) : data(d), next(NULL) {}
void insertM(int d) {
ListNode *ptr, *temp, *curr;
ptr = head;
while (ptr->data < d) {
prev = ptr;
ptr = ptr->next;
} // end while
temp = prev->next;
curr = new ListNode(d, ptr);
curr->next = prev->next; // or temp->next
prev->next = curr;
;
}
};
List mylist;
In this function, I'm trying to add a node in the middle of linked list. Other functions add items to the back and front just fine. When I add in the middle of the list, my prev->next links to curr just fine, but curr->next points to NULL.
I have been trying to make this program work for past 1.5 hours. I'll appreciate your help. This is homework.
The general procedure you'll want to use is:
surf down the next pointers until you reach the node you want to insert after (call it A)
change your inserted node (B)'s next pointer to match that of A's next pointer
change A's next pointer to point to B
It looks from your code that you're trying to maintain a sorted list of integers. This being homework you probably won't get a code snippet, but from glancing at your code, I have to ask why you take a next parameter in your node constructor, but then set the next value to null. Without seeing the rest of your code I can't say for sure, but I'd change next(NULL) on line 9 to be next(n), and then remove the curr->next line near the bottom