删除链表中间的节点

时间:2014-03-20 11:14:26

标签: c pointers linked-list

我写了一段使用链表的代码。我让用户输入几个数字然后要求用户输入他希望删除的数字的索引。我做了一些研究,发现我需要检查下一个节点是否是我要删除的节点,然后有2个临时指针指向当前节点和下一个节点(我想要删除的节点),然后将第一个临时指针的下一个节点分配给第二个临时指针的下一个节点,然后最后释放第二个临时指针。这是我的代码:

#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;
    }
}

因此,例如,如果我输入1 2 3 4 5 -1,链表将包含1 2 3 4 5.然后,如果我输入0表示要删除的索引,程序将打印出2 3 4 5.这无论我输入0还是1,都可以工作。但是,当我输入索引2及以上时,它会给我奇怪的输出,例如,如果我将链表设置为1 2 3 4 5,并输入索引2以通过权限删除它应该输出1 2 4 5,但它输出2 4 5,我不知道最新情况,请指出我正确的方向。

2 个答案:

答案 0 :(得分:2)

在deleteNode中,您使用实际的headpointer来遍历列表。当您循环浏览列表时,您移动实际的头部!您只应在删除第一个元素时修改(*ptrHead)

我建议您将*ptrHead复制到局部变量并使用局部变量遍历列表。

我已经突出显示了以// ***

开头的评论的重要行
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;
}

答案 1 :(得分:1)

找到修改后的deleteNode函数(如果我们试图删除的列表长度超过列表长度,也会处理边界条件)

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;

}