简体   繁体   中英

function not working multiple times?

This function is supposed to remove elements from a linked list. Currently it does the job however, with further testing I found out that I get a segmentation fault after using the function about 2-3 times. For example, lets say listA contains 1 2 3 4 4 5 , when I do remove listA 4 and then print the elements of listA , the output should be 1 2 3 5 , and it is. However when I use the remove function 1-2 more times on the list, it just stops working and I keep getting segmentation faults. I'm not sure why.. Any help will be appreciated!

  void mylist::remove(int z)
            {       
              Node *currP, *prevP;

              prevP = NULL;
              for (currP = head; 
                   currP != NULL;
                   prevP = currP, currP = currP->next) { 

                if (currP->key == z) {
                  if (prevP == NULL) {
                    head = currP->next;
                  } else{
                    prevP->next = currP->next;
                  }
                  delete currP;
                  currP=prevP;
                  numberofnodes--;
                }
              }
              return;
         }

You are not handling the case when first node form list is deleted, since prevP will be null. After deleting currP you are assigning currP=prevP; . In the next iteration when prevP = currP, currP = currP->next will be executed for next for-loop iteration, it will result segmentation fault.

You can use a while loop instead, like:

void mylist::remove(int z)
        {       
          Node *currP, *prevP, *temp;

          prevP = NULL;
          currP = head;
          while(currP != NULL){ 

            if (currP->key == z) {
              if (prevP == NULL) {
                head = currP->next;
              } else{
                prevP->next = currP->next;
              }
              temp = currP;
              currP = currP->next;
              delete temp;
              numberofnodes--;
            }
           else
           {
               prevP = currP;
               currP = currP->next;
           }
          }
          return;
     }

Consider what happens when you remove the first entry in the list: You set head = currP->next but you leave prevP as NULL . When the code gets to currP=prevP , currP becomes NULL , and then you will hit an error trying to access currP->next in the iteration. You will need to reorganize your loop to avoid this.

Your pointer management on moving to next iteration on a for-loop is incorrect. When currP is set to NULL on deleting the first item you will dereference NULL on the iteration increment step of the for-loop.

Honestly, a for-loop isn't the hottest idea for this algorithm in the first place, but if you really want to do this with minimal effort a pointer-to-pointer solution makes short work of this task:

void mylist::remove(int z)
{
    Node **pp = &head;
    while (*pp)
    {
        if ((*pp)->key != z)
        {
            pp = &(*pp)->next;
        }
        else
        {
            Node *victim = *pp;
            *pp = victim->next;
            delete victim;
            --numberofnodes;
        }
    }
}

How It Works

The pointer-to-pointer pp holds the address of the pointer we're interested in checking for a match. This initially holds the address of the head pointer.

Node **pp = &head;

With each non-match we move to the address of the current node's next pointer:

if ((*pp)->key != z)
{
    pp = &(*pp)->next;
}

but, when we discover a match the pointer value who's address is held in pp is saved to a temporary:

Node *victim = *pp;

then that pointer (which may be the head pointer if this is the first item in the list), is updated to its pointed-to-node's next pointer value.

*pp = victim->next;

Finally, the now-unlinked node is discarded.

delete victim;

Notes:

There is NO movement to next when we discard a match. We already moved there by loading *pp with the pointer value held in its own next pointer right before the deletion. Also, it is (hopefully obviously) critical that the head pointer be NULL if the list is empty, and the last node next pointer is NULL to terminate the list. Standard linked list stuff, I know, but it is important and therefore mentioned.

Best of luck.

consider you delete 1 in your list. prevP = NULL; then you delete currP and assigned it with prevP, witch is NULL. end of this loop. Then the it goes to the part of : prevP = currP, currP = currP->next; latter case the problem, because currP is NULL. You are accessing NULL->next.

delete currP; currP=prevP;

This is causing segmentation fault , at first iteration prevP is null so if is executed in case iteration prevP is not Null.

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