mib1413456
mib1413456

Reputation: 337

deleting a node in the middle of a linked list

I have written a piece of code that uses linked lists. I get the user to enter a couple of numbers and then ask the user to enter the index of the digit he wishes to delete. I did some research and found out that i need to check whether the next node is the one I want to delete, then have 2 temp pointers point to the current node and the next node(which is the one i want to delete), then assign the next node of the first temp pointer to the next node of the second temp pointer then finally free the second temp pointer. Here is my code:

#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
    int item;
    struct node *next;
}ListNode;

void print(ListNode *head);
int deleteNode(ListNode **ptrHead, int index);

int main()
{
    int n;
    int remove;
    ListNode *head = NULL;
    ListNode *temp = NULL;
    printf("Enter a value: ");
    scanf("%d", &n);
    while (n != -1)
    {
        if (head == NULL)
        {
            head = malloc(sizeof(ListNode));
            temp = head;
        }
        else
        {
            temp->next = malloc(sizeof(ListNode));
            temp = temp->next;
        }
        temp->item = n;
        temp->next = NULL;
        printf("Enter a value: ");
        scanf("%d", &n);
    }

    printf("Enter index to remove: ");
    scanf("%i", &remove);

    while (remove != -1)
    {
        deleteNode(&head, remove);
        print(head);
        printf("Enter index to remove: ");
        scanf("%i", &remove);
    }
    while (head != NULL)
    {
        temp = head;
        head = head->next;
        free(temp);
    }
    head = NULL;
    return 0;
}
int deleteNode(ListNode **ptrHead, int index)
{
    int count = 0;
    ListNode* temp1 = NULL;
    ListNode* temp2 = NULL;
    while (count <= index)
    {
        if (index == 0)
        {
            temp2 = (*ptrHead)->next;
            free((*ptrHead));
            (*ptrHead) = temp2;
            return 0;
            break;
        }
        if (count+1 == index)//checking for the node ahead
        {
            temp1 = (*ptrHead);
            temp2 = (*ptrHead)->next;//the one to free
            temp1->next = temp2->next;
            free(temp2);
            return 0;
            break;
        }
        (*ptrHead) = (*ptrHead)->next;
        count++;
    }
    return -1;
}
void print(ListNode *head){
    if (head == NULL)
    {
        return;
    }
    while (head != NULL)
    {
        printf("%i\n", head->item);
        head = head->next;
    }
}

So for example if i enter 1 2 3 4 5 -1, the linked list will contain 1 2 3 4 5. Then if i enter 0 for the index to remove, the program will print out 2 3 4 5. This works whether I enter 0 or 1. However, when I enter the indexes 2 and above, it gives me weird outputs like for example if I set the linked list as 1 2 3 4 5, and enter the index 2 to remove, by rights it should output 1 2 4 5, but instead it outputs 2 4 5, I have no idea whats going on, please point me in the right direction.

Upvotes: 0

Views: 610

Answers (2)

Klas Lindb&#228;ck
Klas Lindb&#228;ck

Reputation: 33273

In deleteNode you use the actual headpointer to traverse the list. As you loop through the list you move the actual head! You should only modify (*ptrHead) when you delete the first element.

I suggest that you copy *ptrHead to a local variable and use the local variable to traverse the list.

I've highlighted the important lines with comments starting with // ***

int deleteNode(ListNode **ptrHead, int index)
{
    int count = 0;
    ListNode* temp1 = NULL;
    ListNode* temp2 = NULL;
    ListNode* traverse = *ptrHead;   // *** make a copy that we can use to traverse the list
    while (count <= index)
    {
        if (index == 0)
        {
            temp2 = (*ptrHead)->next;
            free((*ptrHead));
            (*ptrHead) = temp2;  // *** Keep this line as it is to correctly handle deletion of index 0.
            return 0;
            break;
        }
        if (count+1 == index)//checking for the node ahead
        {
            temp1 = traverse;                           // *** Use local copy of pointer
            temp2 = traverse->next;//the one to free    // *** Use local copy of pointer
            temp1->next = temp2->next;
            free(temp2);
            return 0;
            break;
        }
        traverse = traverse->next;                         // *** Use local copy of pointer
        count++;
    }
    return -1;
}

Upvotes: 2

M Thotiger
M Thotiger

Reputation: 344

Find the modified deleteNode function (handles boundary conditions also , if we are trying to delete an index which is more then the list length)

int deleteNode(ListNode **ptrHead, int index)

{

int count = 0;
ListNode* temp1 = NULL;
ListNode* temp2 = NULL;

temp1 = (*ptrHead);

while((temp1 != NULL) && (count <= index))
{
    if (index == 0)
    {
        temp2 = temp1->next;
        free(temp1);
        (*ptrHead) = temp2;
        return 0;
    }
    if ((count+1 == index) && (temp1->next != NULL))
    {
        ListNode*temp = NULL;

        temp = temp1->next;
        temp2 = temp->next;
        temp1->next = temp2;
        free(temp);
        return 0;
    }

    temp1 = temp1->next;
    count++;
}

return -1;

}

Upvotes: 1

Related Questions