Linked list deletion and duplication - c++

In the code I copied newnode to the headnode and also to the temp node. But when I delete an instance of data, it seems to affect the other locations as well. When I freed newnode it also erases the content of head and temp .How is this happening?
Though I copied data initially, the data is freed. This is due to dereferencing? So what should I do if I want to have a copy list and want to manipulate this without affecting the original?
And I initially malloc'd the memory I want by malloc() but in later copy operations I see at codes they are not malloc()'ed rather just copied. And how is it still it working? Do my two questions have a relation?
#include <iostream>
#include <cstdlib>
using namespace std;
struct node{
int data;
struct node*next;
};
int main()
{
struct node*newnode=(struct node*)malloc(sizeof(struct node));
newnode->data=2;
newnode->next=NULL;
struct node*head=NULL;
head=newnode;
struct node*temp=newnode;
while(head!=NULL)
{
cout<<head->data;
head=head->next;
}
cout<<temp->data;
free(newnode);
free(head);
cout<<temp->data;
return 0;
}

With struct node *newnode=(struct node*)malloc(sizeof(struct node)); you allocate a piece of memory for a node once and then you assign the address of this memory to all other node pointers. So when you free this piece of memory, the node isn't available any more to any of the node pointers.
struct node *head=newnode; // head now points to *newnode
struct node *temp=newnode; // temp now also points to *newnode
...
free(newnode); // newnode, head and temp point to released memory now
free(head); // oops! head was released already by the previous statement
Note: this is the C explanation. In C++ the constructor of a class can do the memory allocation and a redefined assignment operator can create a new instance of the object (but I am not a C++ programmer).
The following function creates a copy of the list:
struct node *copylist(struct node *oldlist)
{
struct node *newhead, *list;
if (!oldlist) return(0);
list= newhead= malloc(sizeof(struct node));
*newhead= *oldlist;
while (oldlist->next) {
list->next= malloc(sizeof(struct node));
oldlist= oldlist->next;
list= list->next;
*list= *oldlist;
}
list->next= NULL;
return(newhead);
}

Related

linked list destructor with std::move c++

I'm learning data structures in C++;
I've written a destructor for a linked list as follows:
~List(){
Node* temporary = new Node;
Node* node = head;
while(node != nullptr){
temporary = node;
node = node->next;
delete temporary;
}
}
But then I realized that I can do:
~List(){
Node* node = head;
while(node != nullptr){
node = std::move(node->next);
}
}
Avoiding creating a temporary object, I tried it and worked fine, but I don't know if it is okay, I didn't find a destructor like this in any other place.
std::move doesn't do anything by it's own, it only cast something to rvalue.
How the rvalue is used is determined by the function that accept it, and assignment of raw pointer does nothing different than copy in that case.
But for example, if you're using std::unique_ptr, the operator=(unique_ptr&&) would delete the original data after assignment*.
so if you're using something like
#include <memory>
struct Node{
std::unique_ptr<Node> next;
// possibly move List destructor here
// i.e. destruct a Node would safely remove all sub-node non-recursively
};
struct List{
std::unique_ptr<Node> head;
// write destructor to prevent deep recursion
~List(){
while(head) head = std::move(head->next); // current head is deleted after assignment
}
};
then it would work
*btw, self-assignment is safe because it's actually effectively reset(r.release())
This code snippet
~List(){
Node* temporary = new Node;
Node* node = head;
while(node != nullptr){
temporary = node;
node = node->next;
delete temporary;
}
}
produces a memory leak due to this unneeded memory allocation
Node* temporary = new Node;
In this code snippet
~List(){
Node* node = head;
while(node != nullptr){
node = std::move(node->next);
}
}
neither memory is freed. Only the pointer node is reassigned until it will be equal to a null pointer. So there are again numerous memory leaks.
If you do not want to use an intermediate variable then the destructor can be written for example the following way
#include <functional>
//...
~List(){
while ( head ) delete std::exchange( head, head->next );
}
}

what's wrong with normal variable of node type?

whenever we are creating new node is it manadatory to make pointer to newnode first and allocate memory dynamically to it why can't we have normal variable of node class type !
so,what's wrong with normal variable of node type insted of having pointer to node type
CODE:
//creation of linked list
#include <iostream>
using namespace std;
class node{
public:
int data;
node* next;
};
class linked_list{
public:
node* head;
linked_list(){
head=NULL;
}
void add_node(int data);
void display_ll();
};
void linked_list :: add_node(int data){
node newnode; //HERE IN THIS LINE I KNOW IT SHOULD BE LIKE node* newnode;
if (head==NULL){ // AND DMA THAT NODE , WORKING FINE BUT WHAT'S WRONG WITH ACTUAL CODE
newnode.data=data;
newnode.next=NULL;
head=&newnode;
}
else{
node* temp=head;
newnode.data=data;
newnode.next=NULL;
while(temp->next!=NULL){
temp=temp->next;
}
temp->next=&newnode;
}
}
void linked_list :: display_ll(){
node* temp=head;
while (temp!=NULL)
{
cout<<temp->data<<" ";
temp=temp->next;
}
}
int main(){
linked_list ll;
ll.add_node(6);
ll.add_node(3);
ll.add_node(9);
ll.add_node(3);
ll.display_ll();
}
If you declare newnode as node newnode; within your method, then the object's memory is allocated on the stack, and its life time is local to the execution context of the method: when the function returns, that memory is freed.
That becomes a problem, because after the first call (ll.add_node(6)), head will reference that freed memory. Then ll.add_node(3) will allocate again memory, which could well be the same memory on the stack, and so you'll actually overwrite the first node's data, and temp->next=&newnode will make a bad reference. This will happen also with the other ll.add_node calls. The list is thus corrupted.
When you finally call ll.display_ll(), its temp will point to freed memory and so will temp->next, leading to undefined behaviour, unexpected output and potentially to an exception.
So, the rule is as follows:
If your function creates a reference to the object that will remain accessible after the function has returned, then you must allocate that memory dynamically (using a pointer). If on the other hand the object is only relevant during the execution of the function, and can be discarded when the function returns (without any reference to it), then it is not needed to use a pointer.

what is the asterisk in front of a variable used for in c++?

I am currently learning linked list and my prof sent us a code which is so hard to understand for me. I know that asterisk is used before the varaible to make it as a pointer but this one is infront of a variable.
Here is the code:
#include <iostream>
using namespace std;
struct Node {
int data;
struct Node *next;
};
struct Node *head = NULL;
void insert(int new_data) {
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = head;
head = new_node;
}
void display() {
struct Node* ptr;
ptr = head;
while (ptr != NULL) {
cout<< ptr->data <<" ";
ptr = ptr->next;
}
}
int main() {
insert(3);
insert(1);
insert(7);
insert(2);
insert(9);
cout<<"The linked list is: ";
display();
return 0;
}
This is the one that I am talking about:
void insert(int new_data) {
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = head;
head = new_node;
}
I dont know what is the purpose of the asterisk in here (struct Node*) malloc(sizeof(struct Node));\
and can someone tell me what is the purpose of malloc here malloc(sizeof(struct Node))
This asterisk is after the type name. It means "pointer to that type", in this case, pointer to struct Node.
Let's see this line of code as a whole: struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
Here, a variable new_node is declared, it has the type "pointer to struct Node". The function malloc allocates a piece of memory and returns a pointer to it. However, it doesn't know the type of the pointer, so it returns it as void* (pointer to something unknown).
That's why you need to cast it to the right type before assignment. (struct Node*) is a cast expression, it changes the type of the pointer to the "pointer to struct Node".
To sum up, this line of code allocates a piece of memory to store struct Node in it and saves its address in new_node variable.
But yes, as others have noted, it's not C++ code, it's C code.
In this case the "(struct Node*)" part means it is a struct pointer, in this case the Node struct, it means that it is pointing to the struct, in this case since it is a linked list, you'll have a bunch of this Node Structs all pointing to the "next" one until it reaches the head of the list which is
"struct Node *head = NULL; " then in this function
Then you use this function
void insert(int new_data) {
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = head;
head = new_node;
}
What it does is create a new Node and point it to the previous created Node, it would look something like this:
head<-Node1<-Node2<-Node3...
and can someone tell me what is the purpose of malloc here malloc(sizeof(struct Node))
Malloc here just tells the compiler to allocate the amount of memory the size of the struct called Node so that it doesn't use anymore or anyless then needed.
Also I think this is C not C++
https://www.programiz.com/cpp-programming/library-function/cstdlib/malloc
In the above code you posted, you are declaring data type of "struct Node" .
If you want to declare integer pointer you will do as below :
int *iPtr;
Similarly, here you are declaring pointer to data type struct Node, so it will be
struct Node *new_node;
I guess you got confused between data type and variable . Here "struct Node" is an user defined data type and "next", "head" and "new_node" are variable names.
And regarding malloc, malloc() is a function that will allocate memory in heap for the size of the data type you want and here you want to allocate memory for sizeof(struct Node) which is a size of one Linked list node.
And the malloc() function allocates sizeof(struct Node) bytes and returns a void pointer to the allocated memory and since malloc returns a void pointer (generic pointer) you have to typecast it to which ever data type you are allocating for.
Again I will give you simple example :
int *iPtr = (int *)malloc(sizeof(int));
Similarly, here for data type Struct Node it is done as below:
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));

About Create NODE using cpp

Hi every body i have some question:
struct NODE{
TYPEDATA data;
NODE *link;
};
NODE* CreateNODE(TYPEDATA n){ //1
struct NODE *node = new NODE; //2
if(node){
node->data=n;
node->link=NULL;
}
return node;
}
1.why i must have * after NODE for CreateNODE
2.why must use new NODE
thank you
By using new, you dynamically allocate memory for a node. New returns a pointer to the allocated memory. You indicate that a variable is a pointer by using * . Since you want to return that new node, you need to return not a NODE, but a pointer to NODE, thus effectively the return type becomes NODE* . If you don't know how pointers or dynamic memory work, I suggest you look at these links:
pointers
dynamic memory

Pointer initialization

Sorry if this question has been asked before. On my search through SO I didn't find one that asked what I wanted to know.
Basically, when I have this:
typedef struct node
{
int data;
node *node;
} *head;
and do node *newItem = new node;
I am under the impression that I am declaring and reserving space, but not defining, a pointer to struct node, is that correct?
So when I do
newItem->data = 100 and newItem->next = 0
I get confused. newItem = 0would declare what exactly? Both data and next? The object as a whole?
I'm especially confused when I use typedef. Which part is the macro? I assume node because that's how I call it, but why do I need it?
Finally, what happens when I do:
node *temp;
temp = new node;
temp = head->next;
head->next = newItem;
newItem->next = temp;
I mean, head->next is a pointer pointing to object newItem, so I assume not to newItem.data or next themselves. So how can I use an uninitialized pointer that I described above safely like here? is head now not pointing to an uninitialized pointer?
I am under the impression that I am
declaring and reserving space, but not
defining, a pointer to struct node, is
that correct?
No. You are declaring a pointer, allocating space on the stack for the pointer, and dynamically allocating storage for a node to it it.
Don't confuse yourself by writing stuff like this:
typedef struct node
{
int data;
node * next;
} *head;
The way to write the struct in C++ is:
struct node
{
int data;
node * next;
};
You can now create a pointer:
node * pnode;
which allocates storage for the pointer.
and you can dynamically allocate storage for a node, and make the pointer point to it:
pnode = new node;
or do it all in one:
node * pnode = new node;
Now when you say:
pnode->data = 10;
you are not allocating anything. You are assigning 10 to the member called data of the node instance pointed to by pnode. Of course, if you had given your node a constructor (which you should normally do), you could do it all in one:
struct node
{
int data;
node * next;
node( int n, node * np ) : data( n ), next( np ) {}
};
node * pnode = new node( 10, 0 );
When you define your struct as you did and call new like you did, what you're doing is:
allocate a new struct node on the heap.
allocate space on the stack for newItem and set its value to the address of the new struct you allocated.
You didn't set any values to any of the members of the new struct. If you want that to happen whenever you create a new instance of the struct, you need to define a constructor.
typedef struct node
{
int data;
node *node;
} *head;
This declares node as a struct and defines head as a synonym for node*, so head is a type and not an object.
This makes this illegal: temp = head->next; because -> is not something that you can apply to a type.
new node dynamically allocates a node object and returns a pointer to it. node *newItem = new node; assigns this pointer to newItem. Note, though, that newItem->node (node here is a pointer object and not the type node) is not initialized so is neither null nor points to a valid node object.
This is also illegal because node has no next member.
newItem->next = temp;
I suggest that you choose a naming convention that means that you keep your types and your variables separate. It is somewhat confusing.
node *newItem = new node;
You create:
a new node on the heap (which in your case contains uninitialized values because you omitted the ()
a pointer on the stack, which points to this new node.
newItem->data = 100
simply sets the data member of the newly allocated node to 100.