简体   繁体   中英

Deleting two adjacent nodes in singly linked list

I am student (still a rookie) and I have a problem. I have to delete pair of nodes in singly linked list, whose sum equals k . For example, if the linked list is 13->4->5->4->3 and k=9 , then my function should convert the list to 13->3 (4+5=9, 5+4=9). This is my unfinished code:

typedef struct _node
{
    int value;
    struct _node* next;
}Node;

void remove(Node **list, int k)
{
    if(*list == NULL || (*list)->next == NULL)
       return;

    Node *prev = *list;
    Node *tmp = (*list)->next;

    while(tmp != NULL)
    {
        if(prev->value + tmp->value == k)
        {
             free(prev);
             prev = tmp->next;
             free(tmp);
             tmp = tmp->next->next;
        }
    }
}

I have an idea, but i don't know how to set conditions in while loop. Does anyone have idea how to rewrite this?

Right now you break linkage at the very first match: in your example, after you delete 4, 13's next still points to it and so is a dangling pointer. But it won't happen as you'll never move anywhere from 13 as you only iterate forward if you delete an element (which does not happen for the pair 13->4.)

The third thing you should take into account is you should actually mark elements for deletion otherwise you won't be able to delete the second 4 in your example.

First --> You are not moving ahead in the list, hence it will result into an infinite loop.

Second --> If the next node of tmp is NULL then tmp=tmp->next->next will give you segmentation fault.

Third --> When you are freeing the memory you are also breaking the linked list, hence pointToPrev pointer has been declared in the underlying code which will be pointing to the node one behind the prev pointer but in case of freeing in the memory, it will point to net node to tmp to hold the list.

better change the while loop to this:

 `  int indicator=0;
    Node *pointToPrev = *list;
    if(prev->value + tmp->value == k)
    {
         *list=temp->next;
         free(tmp);
         free(prev);
         indicator=2;
    }
    while((tmp != NULL)&&(indicator!=2))
    {
          if(prev->value + tmp->value == k)
          {
             free(prev);
             pointToPrev->next = tmp->next;
             free(tmp)
             break; //AS YOU DON'T NEED TO COMPLETE THE ENTIRE WHILE LOOP AS SUM HAS BEEN ALREADY FOUND
          }
          else //THIS WILL SAVE YOU FROM THE INFINITE LOOP 
          {   
             tmp = tmp->next;
             prev = prev->next;
             if(indicator==0)
             {
                  pointToPrev = *list;
                  indicator=1;
             }
             else
                  pointToPrev=pointToPrev->next;
          }
    }

This problem is complicated by the fact that you have two overlapping conditions controlling whether a given node should be removed: if the sum of its value with that of the previous node is the target value, or if the sum of its value with the next node is the target value. What is more, except when it is the last node, you will always need to compare the next node with the one following it, so either you must memorialize the value it carries or else you must avoid deleting it.

This problem can be addressed with an ordinary linked list traversal starting at the second node (or if there are fewer than two nodes, then nothing needs to be done). On each iteration

  • determine whether the sum of the node values for the current and previous nodes is equal to the target value
  • if so, or if that evaluation was true in the previous loop iteration, then delete the previous node

After the loop terminates, delete the last node if appropriate. You'll need to carry enough state from iteration to iteration to perform the deletions appropriately and to remember the result of the sum evaluation in the previous iteration, but overall it's not much more difficult than deleting individual nodes by value.

This approach is pretty simple, as it limits the number of cases that must be considered in each evaluation to two, it never requires looking further ahead in the list than the next node, and when it deletes a node, that node is always has the same relationship to the current node. The code for this is left as the exercise it is supposed to be.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM