Home > database >  Linked List behaving differently
Linked List behaving differently

Time:02-02

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?

  •  Tags:  
  • c
  • Related