Reputation: 11
I have created a Linked List in C. Now I want to delete node from any position for example the first node or last node or any nth node. I wrote a code that worked fine. But problem is that someone told me though it gave the correct output the code is wrong. Here is the code.
Deleting the First Node:
struct node {
int number;
struct node *next;
};
struct node *head = NULL;
struct node *tail = NULL;
void deletefirst(struct node *a) {
head = head->next;
free(a);
}
Now is using this code I got my desired output. The problem is that my friend told me that the head pointer is not passed by reference. *a holds a copy of. It's printing correctly because of head=head->next as head is declared globally. But free(a) doesn't delete the original node from head, it only frees the copy of a. So then he gave me his code
void deletefirst(struct node **a) {
struct node *temp = *a;
*a = (*a)->next;
free(temp);
}
According to him, here head is passed by reference so this code is able to free the original node from head. My question is, which is correct mine ,him or both? If he's really correct than how my another code with *a can delete the last node?
Deleting Last Node
void deletelast(struct node *a) {
while (a->next->next != NULL) {
a = a->next;
}
free(a->next);
a->next = NULL;
}
Here is my code to delete the last node. Is this also wrong according to him? I mean i pointing the *a to head so it must be correct. It will be better if you explain briefly. Another thing is that if my code is wrong with *a and he's correct that we need to pass by reference **a then when i created insert function *a they also worked find. I have some basic knowledge in pointer but not that advance level.
Here is my code to insert in the end (Here another structure was used not the above one)
void llinsertend(const char *a, const int *b) {
struct node *current = malloc(sizeof(struct node));
if (current == NULL) {
printf("Current creation failed.\n");
}
current->name = malloc(strlen(a) + 1);
if (current->name == NULL) {
printf("String allocation failed\n");
}
strcpy(current->name, a);
current->age = *b;
current->next = NULL;
if (linkeslist1head == NULL) {
linkeslist1head = current;
linkedlist1tail = current;
} else {
linkedlist1tail->next = current;
linkedlist1tail = current;
}
}
If in my delete function if *a can't modify my first original head linkedlist or delete the node then how in insert function how it's possible that *a is able to modify the original head function. I also used chatgpt, it told me in delete function I was wrong cause it holds a copy and can't delete original head node and my friends code was right. Please ignore edge cases like null pointer of empty list the code is not completed
Upvotes: 0
Views: 82
Reputation: 311078
The both functions deletefirst
yours and of your friend
void deletefirst(struct node *a) {
head = head->next;
free(a);
}
and
void deletefirst(struct node **a) {
struct node *temp = *a;
*a = (*a)->next;
free(temp);
}
just do not make sense are incorrect and can invoke undefined behavior.
Firstly if your function deals with the file scope variable head
used within the function when there is no sense to pass to the function any pointer to a node.
In the both functions there is no check whether a passed pointer or a pointer passed by reference are null pointers. So dereferencing a null pointer invokes undefined behavior. Also the functions do not update the pointer tail
used in the definition of the list if it is required.
If you are using file scope pointers head
and tail
then the function can look the following way
void deletefirst( void )
{
if ( head != NULL )
{
struct node *first = head;
head = head->next;
free( first );
if ( head == NULL ) tail = NULL;
}
}
As for the function of your friend then he needs also to pass to the function the pointer tail
also by reference and define the function similarly to the function shown above.
But this makes the code more complicated. It is much better to introduce one more structure that will contain within itself these pointers head
and tail
as its data members.
Your function deletelast
has the same problems as your function deletefirst
. It can be defined the following way
void deletelast( void )
{
if ( head != NULL )
{
if ( head->next == NULL )
{
deletefirst();
}
else
{
struct node *current = head;
while ( current->next->next != NULL )
{
current = current->next;
}
struct node *last = current->next;
current->next = last->next;
free( last );
tail = current;
}
}
}
But as I already have pointed to it is a bad idea to use global variables. And it would be much better to introduce an additional structure as I already have described and use objects of this structure in block scopes.
Upvotes: 0