【问题标题】:deleting a node in the middle of a linked list删除链表中间的一个节点
【发布时间】:2014-04-27 04:38:53
【问题描述】:

我写了一段使用链表的代码。我让用户输入几个数字,然后要求用户输入他希望删除的数字的索引。我做了一些研究,发现我需要检查下一个节点是否是我要删除的那个,然后有 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,我不知道发生了什么,请指出正确的方向。

【问题讨论】:

    标签: c pointers linked-list


    【解决方案1】:

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

    我建议你将*ptrHead复制到一个局部变量中,并使用该局部变量遍历列表。

    我已经用 // *** 开头的 cmets 突出显示了重要的行

    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 2 3 4 5 并且我删除元素 0,它将输出 2 3 4 5,然后如果我再次删除元素 0,它将输出 3 4 5
    • 我在答案中添加了修改后的deleteNode。它可以安全地移除任何元素。
    【解决方案2】:

    找到修改后的 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;
    

    }

    【讨论】:

    • 谢谢!我将尝试理解您的代码,因为我不熟悉使用双指针的概念。我不知道如果我使用临时指针存储链接列表会被修改 (*ptrHead)
    猜你喜欢
    • 2011-06-06
    • 1970-01-01
    • 2010-12-29
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多