删除链表 C 尾部节点

Remove a node at the tail of a linked list C

我写了代码来删除链表尾部的节点。该代码在不同的测试用例中都能正常工作,但我认为我的代码有点麻烦。但是,我看不出我能做些什么?

node_t *remove_t (node_t *l){
if (l==NULL){
    return l;
}
else {
    node_t *curr=l;
    node_t *ret=l;
    if (curr->next==NULL){
        l=NULL;
        return l;
    }
    else {
        while (curr->next->next!=NULL){
            curr=curr->next;
        }
        curr->next=NULL;
        free(curr->next);
        return ret;
    }
}
}

我不确定您是否可以对逻辑进行很大更改 - 因为您对 3 种不同情况(空列表、包含 1 个项目的列表和包含 >1 个项目的列表)的处理方法是合理的。您可以格式化代码以便于阅读:类似于:

node_t *remove_t (node_t *l){
    // case 1: Empty list
    if (l==NULL){
        return l;
    } ;

    // case 2: List with one item. Return empty list.
    node_t *curr=l;
    if (curr->next==NULL){
        // Remember to free this element.
        free(curr) ;
        l=NULL;
        return l;
    } ;

    // case 3: list > one item
    // Move curr to last item
    while (curr->next->next!=NULL){
        curr=curr->next;
    }
    // Note order of free/null setting.
    free(curr->next);
    curr->next=NULL;

    return l;
}

如果你保留一个指向节点的指针到指针,然后迭代到列表的末尾并简单地释放最后一个指针并将其设置NULL,例如

/** delete last node */
void del_last_node (node_t **l)
{
    node_t **ppn = l;       /* pointer to pointer */
    node_t *pn = *l;        /* pointer to node */

    for (; pn->next; ppn = &pn->next, pn = pn->next) { } /* iterate to last */

    free (*ppn);           /* free node */
    *ppn = NULL;           /* set pointer NULL */
}

您似乎没有释放尾节点。

curr->next=NULL;
free(curr->next);

如果您已经将其设为 NULL,您将无法释放 curr->next。

我的实现:

void remove_tail(node_t *l) {
    if (l == NULL) return;
    if (l->next == NULL) {
        free(l);
        l = NULL;
        return;
    }
    node_t *prev = l;
    node_t *curr = l->next;
    while (curr->next != NULL) {
        prev = curr;
        curr = curr->next;
    }
    prev->next = NULL;
    free(curr);
}