this is my first time asking here.
I was practicing linked list in C and I cannot figure out why my functions behave differently.
I make a linked list of ints 1-10 and delete the even numbers using delEven()
function.
delEven()
plays with the node P
, P=*node
, to make the changes, which work properly.
However, when I use the P=*node
to delete all elements in the list in delAll2
, the list is untouched. When I ran printList(P)
within the function delAll2
, the list is properly deleted.
When I use the input *node
instead of P
to delete all elements in delAll
, it is working properly.
I would like to understand why I was able to delete even elements in delEven
using P=*node
, when I was not in delAll2
.
Thanks,
code:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int dat;
struct node* next;
};
void printList (struct node* node)
{
if (node == NULL)
{
printf("empty\n");
return;
}
while (node->next!=NULL)
{
printf("-",node->dat);
node = node->next;
}
printf("-\n",node->dat);
}
void delEven(struct node** node)
{
struct node* P;
P = *node;
while (P->next != NULL)
{
if (P->next->dat%2==0)
{
P->next = P->next->next;
}
if(P->next->dat%2==0)
{
P->next = P->next->next;
}
P=P->next;
}
}
void delAll(struct node** node)
{
struct node* P;
P = *node;
while ((*node)->next != NULL)
{
*node = (*node)->next;
}
*node = (*node)->next;
}
void delAll2(struct node** node)
{
struct node* P;
P = *node;
while (P != NULL)
{
P = P->next;
}
}void main()
{
int i;
struct node* start;
struct node* Q;
struct node* P;
start = NULL;
for(i=1; i<=10;i )
{
Q=malloc(sizeof(struct node));
Q->dat = i;
Q->next = start;
start = Q;
}
printList(start);
printList(start);
delEven(&start);
printList(start);
delAll2(&start);
printList(start);
}
output when delAll2:
10 9 8 7 6 5 4 3 2 1
10 9 8 7 6 5 4 3 2 1
10 9 7 5 3 1
10 9 7 5 3 1
output when delAll:
10 9 8 7 6 5 4 3 2 1
10 9 8 7 6 5 4 3 2 1
10 9 7 5 3 1
empty
CodePudding user response:
When managing linked lists, you should avoid having multiple versions of code to do the same thing in multiple locations.
Make a single function to delete a node. I recommend one that looks like this:
void deleteNextNode(struct node **list, struct node *node_before);
// node_before is the node _before_ the node to delete
// node_before == NULL to delete the first node in the list
// *list is updated if necessary
Once you have that, you can rewrite your delEven()
as:
void delEven(struct node **list)
{
// Delete all even-valued nodes at the head of the list
while (*list && isEven(list->dat))
deleteNextNode(list, NULL);
if (!*list) return; // (it might have been the whole list)
// Find and delete even-valued nodes in the rest of the list
struct node *before = *list; // (list might be a single node at this point)
while (before->next)
// if the next node is even, delete it
if (isEven(before->next->dat))
deleteNextNode(list, before);
// else advance to the next “before” node
else
before = before->next;
}
Notice how we had to handle the (head of list) and (rest of list) cases separately?