i wrote the following code to delete the nodes at the beginning and at the end of a doubly linked list....but the execution of these functions stopped in between and the program was aborted......
struct nodeb
{
int value;
nodeb *next;
nodeb *pre; //pre of first node and next of last node point to null...
nodeb(int a,nodeb *ptr1=0, nodeb *ptr2=0):value(a), next(ptr1), pre(ptr2)
{}
};
class doublelist
{
private:
nodeb *head1,*head2;
public:
doublelist():head1(0),head2(0)
{cout<<"double list created"<<endl;}
void deletebeg()//delete beginning node
{
if(head1->next==0)
{
nodeb *ptr=head1;
head1=head2=0;
delete ptr;
}
else
{
nodeb *ptr=head1->next;
nodeb *ptr1=head1;
ptr->pre=0;
head1=ptr;
delete ptr1;
}
}
void deleteend()//delete end node
{
nodeb *ptr=head1;
nodeb *ptr1;
while(ptr->next!=0)
{
ptr1=ptr;
ptr=ptr->next;
}
delete ptr;
ptr1->next=0;
}
}; //class ends here
int main()
{
doublelist list1;
nodeb node(8);
nodeb node1(7);
nodeb node2(9);
nodeb node3(4);
list1.insertbeg(node);
list1.insertbeg(node1);
list1.insertafter(node3,1);
list1.insertend(node2); //insertbeg,insertafter and insertend are three functions i defined to attach nodes at the beginning,at a particular location and at the end of the list
list1.deletebeg();
}
can anyone please tell me the problem??this is the link to the three functions for insertions
Now I can see all the code the problem is very simple. Your deletebeg function is deleting the beginning node with delete, but you didn't allocate the node with new. You should only delete memory if you created it using new.
Normally when people write linked list classes they allocate the nodes inside the list methods using new. Then they can safely delete the nodes inside the methods. You are doing the deletes but you are not using new. So you need to rewrite your main function like this
int main()
{
doublelist list1;
list1.insertbeg(8); // add 8 to beginning of list
list1.insertbeg(7); // add 7 to beginning of list
list1.insertafter(4,1); // add 4 after first item of list
list1.insertend(9); // add 9 to end of list
list1.deletebeg();
}
Then you need to rewrite your methods like this
void insertbeg(int value)//insert beginning
{
nodeb* a = new nodeb(value); // allocate node inside of method using new
if(head1==0)
{
head1=a;
head2=a;
a->next=0;
a->pre=0;
}
else
{
nodeb *ptr=head1;
ptr->pre=a;
a->pre=0;
a->next=ptr;
head1=a;
}
}
I've only shown insertbeg, you need to change all your insert methods in the same way.
I'm not promising that's the only problem, but make this change and you'll be on the right way. If you have more problems then post again, but remember post complete code. It's the only way you'll get help with problems like this.
I'm a little baffled by this code excerpt, but I'll assume this is the entire excerpt for this...
The functions deletebeg and deleteend aren't declared anywhere in the class definition, only after it. Normally, it would look something like:
class List{
void aFunction(List * argument);
};
void List::aFunction(List * argument){
do something
};
But all that aside, do not make your own linked list, it is much faster and will make your life easier using std::list<int> (replacing int with whatever data type you are making a list for).
There are lots of reasons for this, but the main one is that you only don't have to write it, but you don't have to debug it either. The linked list implementation you created, for instance, uses a recursive function to delete itself (when a function calls itself, it's recursive). If the linked list is very large, this can cause a stack overflow, caused by calling too many functions within functions. It's things like this that are a nightmare to track down and find, and distract you from the real reason you are programming. That is assuming that reason isn't making a linked list. :P
While it isn't usual to see functions declared outside a class in C++, it isn't impossible. But that would mean that head1 is a global variable somewhere that isn't shown.
You left out the part of that is actually calling deletebeg and deleteend so it is hard to tell exactly what is happening. Perhaps you are making use of a pointer after it has been deleted.
Also, while NULL is usually zero, there is no guarantee that is the case for your compiler. You should be using NULL instead of zero.
My guess is that you called deleteend with a node that for whatever reason had head1==0, then ptr1 was never initialized, and the program crashed on the last line of deleteend when you tried to dereference the uninitialized pointer.
Further to the comments on my previous answer
This code is wrong
void insertbeg(int value)//insert beginning
{
nodeb a(value); // create node on the stack
if(head1==0)
{
head1=&a;
head2=&a;
a.next=0;
a.pre=0;
}
else
{
nodeb *ptr=head1;
ptr->pre=&a;
a.pre=0;
a.next=ptr;
head1=&a;
}
}
The code above would have the problem you described, when you said 'head1 and head2 will point nowhere'. But this code is completely different
void insertbeg(int value)//insert beginning
{
nodeb* a = new nodeb(value); // allocate node inside of method using new
if(head1==0)
{
head1=a;
head2=a;
a->next=0;
a->pre=0;
}
else
{
nodeb *ptr=head1;
ptr->pre=a;
a->pre=0;
a->next=ptr;
head1=a;
}
}
It's different because it uses new to create the objects. When you use new the objects don't get destroyed when you exit the function. That's what new means. But when you do use new you also have to use delete when you have finished with the nodes.
Related
I wrote a singly linked list implementation using a struct. It is not part of an outer class that manages the operations on the list. Instead all of the operations are handled directly with the Nodes.
I understand that if the struct definition was part of a class, say ListManager, calling the destructor on a ListManager instance would just require one to iterate through the linked list managed by the class and delete each Node.
However, since this linked list is not part of an outer class and manages all of the operations itself I am a bit confused as to how to write the destructor.
Version 1 works well, its a recursive call that goes through the list and frees and memory associated with each Node.
Version 2 caused an infinite loop. I don't understand why, as this is one way that I would implement the destructor for a container class that manages the Node linked list.
Version 3 works well but is too verbose.
I ran all three versions using valgrind and python tutor to check for leaks and other issues.
Any help explaining why Version 2 does not work and why it is incorrect to implement the destructor in such a way is appreciated!
Struct Linked List
#include <iostream>
#include <string>
using namespace std;
struct Node
{
int id;
Node* next;
Node(int newId = 0, Node* newNext = NULL)
: id(newId), next(newNext) { }
};
Destructor Version 1
~Node()
{
if (next != NULL)
delete next;
}
Destructor Version 2
~Node()
{
Node* lead = this;
Node* follow = this;
while (follow != NULL)
{
lead = lead->next;
delete follow;
follow = lead;
}
}
Destructor Version 3
~Node()
{
Node* lead = this;
Node* follow = this;
if (follow != NULL)
{
lead = lead->next;
delete follow;
follow = lead;
}
}
Main
int main()
{
Node* head = NULL;
head = new Node(23, head);
head = new Node(54, head);
head = new Node(81, head);
head = new Node(92, head);
delete head;
return 0;
}
In version 2, you have written a loop that clears up the entire list in one destructor call by looping through the list and deleting every element. However, what happens is not that you have just one destructor call. Every time an element is deleted, that calls the destructor again.
So in the end, the delete follow translates to delete this (because follow = this;) for the first invocation. This then causes the destructor of the first node to be called again, causing the endless loop.
The following nodes would be destroyed multiple times, leading to undefined behavior, but it's not even getting there because of that infinite loop.
You only need each Node to delete (at most) one other Node, to eventually delete all the nodes. You re-assigning of local pointers does not affect the structure of the list.
Both 2 and 3 are delete this, which is suspicious at the best of times, plus some irrelevant ceremony, in the destructor. They are both undefined behaviour, deleting the same object (at least) twice.
Your first attempt is close.
Instead of confusing yourself with copying around pointer values, just use an owning pointer type, like std::unique_ptr.
struct Node
{
int id;
std::unique_ptr<Node> next;
Node(int id = 0, std::unique_ptr<Node> next = {})
: id(id), next(std::move(next)) { }
// correct destructor is implicit
};
I have been working with this C++ program for a while, and I have figured what exactly is happening, but I haven't figured out how to fix it exactly. Here is what I have set up:
struct entry {
string foo;
string bar;
string num;
};
struct node {
entry input;
node* left;
node* right;
};
node* home = new node;
This code takes place in a separate header file that is included in a main cpp file, which has the following:
home->input.foo="John";
home->input.bar="Doe";
home->input.name="1234";
printAll(home);
This is were the error pops up, trying to pass home through the function printAll in the header file:
void printAll(node* start){
if(start==NULL) return;
printAll(start->left);
cout << start->input.foo;
printall(start->right);
}
The error that Visual Studio gives me is 0xCDCDCDCD on start. I understand it's not home that is causing the issue, it's start, but I don't understand how to correct this error. I read around and I can assume that start has been thrown into heap memory but it is unintalized. I didn't think this was possible. And I also can guess that C++ doesn't know what start is and how to use it, how would I correct this?
You haven't initialized left or right. In debug builds, Visual Studio will set uninitialized memory to 0xCDCDCDCD. This is obviously not equal to NULL, so your comparison returns false.
As noted in the other answer, the error you are getting may be because you haven't initialized the left and right node as NULL. However you have another error and that is you have created an infinite loop in your printAll.
Your printAll function will first move to the left-most node and print it. After that it will move one node to the right, and, before prints it anything, it'll move to the left again.
The proper way of printing all the nodes is to put list of nodes within a class that keeps track of the first and last node.
Class LList {
node * startNode;
void printAll(){
if (startNode == NULL)
return;
node * currNode = startNode;
// print all the nodes moving left to right
_printAll(currNode);
}
void _printAll(currNode){
// print currNode and recursively go to next by calling
// _printAll(currNode->right)
}
}
Additional things to note
Of course, you'll want to make printAll public and the rest of the
above private.
You'll also need a function to add a node to the list. Look up linked lists attributes and methods to see what else you'll need.
It's better to avoid structs and use objects in place of them
I'm trying to pass in a head node to a function that recursively deletes everything from the LLL. But I'm not very good with classes. I've got one class for the LLL data called Node, and another called NodeList which manages all of the nodes.
The problem is that I can't access the private fields and I don't know how to get them in there. Because I don't want them public like a struct.
C++ Having trouble with syntax, so a class can pass data to other classes I've checked this link which said to make sure to have in the NodeList class Node * head, but I already have that.
C++ passing private data to other private functions in a class And I checked this one, but it was way over my head for the little C++ I know. Also I think this was just a pass by refrence issue.
This isn't the whole thing by the way, just the classes and the one function.
class NodeList
{
public:
NodeList();
~NodeList();
//this should delete the whole list
void delList(NodeList * head);
private:
//head
NodeList * head;
};
//this is the nodestructkindathing
class Node
{
public:
Node();
~Node();
private:
//next pointer
Node * next;
int data;
};
void NodeList::delList(NodeList * head)
{
if (!head)
return;
delList(head->next);
delete head;
}
NOTE: I changed delList and Node * head in the class to become NodeList * head and now I only recieve one error.
error: ‘class NodeList’ has no member named ‘next’
As suggested by Some programmer dude, make NodeList a friend of Node. When class A declares class B to be a friend, B can see and interact with the private members of A. Note that the reverse is not true. friendship is one way. A cannot see the private members of B unless B declares A to be a friend.
This one change will solve all of the problems asked in the question.
The rest of this code dump is to make writing a linked list a little easier for you. Linked lists are best considered a rite of passage for programmers. You'll find you rarely use them in real life programming, but they serve as a notorious weeder of CS students. Practically no one gets them right the first time or two. They require a moderate amount of care and attention to book keeping. Pen and paper step-by-step drawings of the list and the interactions you wish to perform on the list are highly recommended to help visualize and debug a linked list.
You may also find delving into pointers to pointers extremely helpful. For example, see the Alternative Using Pointer To Pointer section of this linked answer.
Comments embedded where needed.
#include <iostream>
class Node
{
friend class NodeList; // NodeList, and no one else, can now see the private
// members of Node
public:
// Node must be given a value and it not given a next, it's automatically NULL
// this makes it almost impossible to not point link at something useful,
// eliminating the most common of the trivial linked list bugs
Node(int value, Node * link = nullptr);
~Node(); //if it doesn't do anything. Get rid of it. See the Rule of Zero
private:
//next pointer
Node * next;
int data;
};
class NodeList
{
public:
NodeList();
~NodeList();
//this should delete the whole list
void delList(Node * head);
private:
//head
Node * head;
};
Node::Node(int value, Node * link) : next(link), data(value)
{
// test code
std::cout << "Node data = " << data << " next = " << next << '\n';
}
Node::~Node()
{
// test code
std::cout << "~Node data = " << data << '\n';
}
NodeList::NodeList()
{
// test code to give delList something to delete
head = new Node(1,new Node(2,new Node(3)));
}
NodeList::~NodeList()
{
delList(head);
}
//this is the nodestructkindathing
void NodeList::delList(Node * head) // watch out! Parameter head shadows member head!
{
// Warning: This function is recursive and a potential stack-killer if given a
// long list. Prefer iteration here unless given a reason to do otherwise
// and guarantees on maximum list length
if (!head)
return;
delList(head->next);
delete head;
}
int main()
{
NodeList test;
}
Expected output:
Node data = 3 next = 0
Node data = 2 next = 0x2ec6cc0
Node data = 1 next = 0x2ec6ce0
~Node data = 3
~Node data = 2
~Node data = 1
A discussion of the Rules of Three, Five and Zero. Understanding these rules is a must if you want a stable linked list or to program non-trivial systems in C++.
Documentation on friend.
I have two classes: "node" and "poly". The node objects are linked together to form a linked list. The poly object holds a pointer to the first node. I am trying to deallocate the memory for the entire "poly". I want to delete the poly - then within the poly destructor call a function (something like "freePoly") that will help me iterate through the entire linked list of node objects - deleting all nodes.
Here is the class definition:
class Node
{
private:
double coeff;
int exponent;
Node *next;
public:
Node(double c, int e, Node *nodeobjectPtr)
{
coeff = c;
exponent = e;
next = nodeobjectPtr;
}
~Node()
{
printf("Node Destroyed");
//???
}
class poly
{
private:
Node *start;
public:
poly(Node *head) /*constructor function*/
{
start = head;
}
~poly() /*destructor*/
{
//???
}
void freePoly();
};
void poly::freePoly()
{
//???
}
I've tried a lot of things, but essentially I get stuck where I'm only deleting the first node object. Then I've lost the pointer to the other nodes... and leak memory because I can't access them anymore for deletion.
You can avoid a lot of problems and work by using a std::vector instead of a Do-It-Yourself linked list. Unless this is for learning.
That said, do
~poly() /*destructor*/
{
while( start != 0 )
{
node* p_doomed = start;
start = start->next;
delete p_doomed;
}
}
There are also many other ways to do this, but the above is a pattern that can help you figure out how to do similar things.
If you want to keep your code as is, then your freePoly should look like this:
while(start)
{
Node *ptr = start;
start = start->getNext();
delete ptr;
}
Notice what this code does: first it makes a copy of the pointer to the current head - i.e. the first Node, then it makes head point to the next object and only then calls delete for the old head pointer.
Of course, this design isn't ideal: you are programming using a C++ compiler and you have some classes and some member functions but you aren't really using C++ effectively:
Not only does language provides you with wonderful tools such as std::list or std::vector so that you don't have to reinvent the wheel and things like std::unique_ptr so that pointers know when it's safe to delete themselves.
It also provides you with powerful abstract concepts to model the bahavior of objects.
I suggest that you take a step back and rethink your code. Key questions to ask are: how can I write less code here? What facilities of C++ can I leverage here? What are these objects I have and what does each object do?
I understand that this may be a homework exercise and you have to implement things a certain way, but don't let that stop you from learning.
You could try this:
private:
void auxDestroy(Node* p);
void Node::auxDestroy(Node* p){
if (p!=0) {
if (p->next != 0) {
auxDestroy(p->next);
}
else {
delete p;
}
}
}
Then in the destroy method you could call this auxDestroy(this->next);
~Node(){
auxDestroy(this->next);
}
And in poly destructor:
~poly(){
delete this->start;
}
Which of these is a more correct way to store the first object in a linked list?
Or could someone please point out the advantages/disadvantages of each. Thanks.
class Node
{
int var;
Node *next;
static Node *first;
Node()
{
if (first == NULL)
{
first = this;
next = NULL;
}
else
//next code here
}
}
}
Node* Node::first = NULL;
new Node();
-- OR --
class Node
{
int var;
Node *next;
Node()
{
//next code here
}
}
Node* first = new Node();
The latter is definitely preferable. By making the first node pointer a static class member, you are basically saying that there will only be a single linked list in your whole program.
The second example lets you create several lists.
The first example has the definite drawback of only being able to create a single linked list in your entire program, so I wouldn't do that.
The second works fine, but doesn't shield the user of the class from how the linked list works. It would be better to add a second class, for example named LinkedList, that stores the 'first' pointer and performs list management.
Even better, you could use std::list instead.
It's most usual to have a separate List class and a separate Node class. Node is usually very simple. List holds a pointer to the first Node and implements the various list operations (add, remove, find and so on).
Something like the following
class List
{
public:
List()
{
first = new Node();
}
void insert(int val);
void remove(int val);
// ... and so on
~List()
{
// ... clean up
}
private:
struct Node
{
int val;
Node* next;
Node(int val_ = 0, Node* next_ = 0)
: val(val_), next(next_)
{}
};
Node* first;
};
Note that you can place Node outside List if you want to, but this usually doesn't make much sense.
Presumably you may have more than one list? In which case, the static option is a non-starter.
You definitely don't want the "first" to be a static. This implies there's only one linked list in your entire program. static means that every Node in every linked list in your entire program has the same beginning.
That being said you want your Node to have the fewest responsibilities-- It make sense for it to store its value and be able to get to the next Node. It adds complexity to add the job of1 maintaining the "first" pointer. For example what happens when you insert a new element at the beginning? Then you'd have to update everyone's "first" pointer. Given the two choices above I'd chose the second choice.
I would furthermore add a third choice. Add a "linked list" wrapper that gave you easy access to "first", "last" and allow you to easily insert into and iterate through the list. Something like:
class LinkedList
{
Node* First;
Node* Last;
public:
Node* GetFirst() {return First;}
Node* GetLast() {return Last;}
// insert after "where"
void Insert(Node* where, Node* newNode);
...
}
Not uselessly limiting your code to a single list instance is one very good argument for code variant 2.
However, just from superficially looking at the two examples, the sheer number of lines of code also gives a good indication that variant 2 has merits over variant 1 by being significantly shorter.