Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从C中的链表中删除最后两个元素_C_List_Singly Linked List - Fatal编程技术网

从C中的链表中删除最后两个元素

从C中的链表中删除最后两个元素,c,list,singly-linked-list,C,List,Singly Linked List,我有一段代码,它从链表中删除最后一个元素。我必须做哪些更改才能删除链表的最后两个元素 void deletesEnd() { struct node *temp, *last; temp = head; last = temp; while (temp != NULL && temp->next != NULL) { last = temp; temp = temp->next; }

我有一段代码,它从链表中删除最后一个元素。我必须做哪些更改才能删除链表的最后两个元素

void deletesEnd() {
    struct node *temp, *last;

    temp = head;
    last = temp;

    while (temp != NULL && temp->next != NULL) {
        last = temp;
        temp = temp->next;
    }

    if (last == temp) {
        free(temp);
        head = NULL;
    } else {
        free(last->next);
        last->next = NULL;
    }
}

下面是一个演示程序,演示如何同时删除最后两个节点。实际上,该函数与您的函数类似,只是它不仅检查
next
节点,而且还检查
next->next
节点

#include <stdio.h>
#include <stdlib.h>

struct node
{
    int value;
    struct node *next;
} *head;

void push( int value )
{
    struct node *tmp = malloc( sizeof( struct node ) );
    tmp->value = value;
    tmp->next  = head;

    head = tmp;
}

void display()
{
    for ( struct node *current = head; current; current = current->next )
    {
        printf( "%d ", current->value );
    }
}

void deleteLastTwo()
{
    struct node *current = head;
    struct node *prev = head;

    if ( current && current->next )
    {
        while ( current->next->next )
        {
            prev = current;
            current = current->next;
        }
    }

    if ( current )
    {
        if ( current->next )
        {
            free( current->next );
        }

        if ( prev == current )
        {
            head = NULL;
        }
        else
        {
            prev->next = NULL;
        }

        free( current );
    }
}

int main(void) 
{
    const int N = 11;

    for ( int i = N; i != 0; i-- ) push( i - 1 );

    display();
    printf( "\n" );

    while ( head )
    {
        deleteLastTwo();
        display();
        printf( "\n" );
    }

    return 0;
}

请注意,将head节点声明为全局变量不是一个好主意。如果它可以像局部变量一样声明,则效果更好。在这种情况下,您需要重写列表中的方法,因为在大多数情况下,当前方法无法正常工作。

此逻辑将删除单链接列表中的最后2个节点

void deletesEnd()
{
    struct node *temp, *last;

    temp = head;
    last = temp;

    while (temp->next->next != NULL)
    {
        last = temp->next;
        if(last->next->next!=NULL)
                temp = temp->next;
        else
                break;
    }

        struct node *ptr=last->next;
        last->next=ptr->next;
        free(ptr);

        temp->next=last->next;
        free(last);
}

为了娱乐和教育:简单的递归版本

  • 函数返回:=下面的节点数
    us
  • 在递归返回后,我们可以决定是否太接近尾部
  • 然后离开我们
  • 因为我们将一个指针传递给指针,所以对于大小为2或更小的列表也应该有效


要删除列表的最后两个元素,最简单的解决方案是调用
deletesEnd()
两次。请注意,
deletesEnd()
应将
head
作为参数并返回新值。您可以通过发出嵌套调用来删除最后2个:

struct node *deletesEnd(struct node *head) {
    struct node *temp, *last;

    last = temp = head;
    while (temp && temp->next != NULL) {
        last = temp;
        temp = temp->next;
    }
    if (last == head) {
        free(head);
        head = NULL;
    } else {
        free(last->next);
        last->next = NULL;
    }
    return head;
}
删除最后一个元素:
head=deletesEnd(head)

删除最后2个元素:
head=deletesEnd(deletesEnd(head))

设计的简单性不仅弥补了两次枚举列表的开销

如果您绝对想要一个特定的功能,您可以通过以下方式扩展您的方法:

struct node *deleteLast2Nodes(struct node *head) {
    struct node *temp, *last;

    last = temp = head;
    while (temp && temp->next != NULL && temp->next->next != NULL) {
        last = temp;
        temp = temp->next;
    }
    if (last == head) {
        if (head) {
            free(head->next);
        }
        free(head);
        head = NULL;
    } else {
        free(last->next->next);
        free(last->next);
        last->next = NULL;
    }
    return head;
}

不要编写专门删除最后一个元素的函数。编写一个泛型删除函数,然后以这样一种方式编写此函数:它将使用适当的节点调用泛型删除。还要注意的是,
head=NULL
没有任何作用,因为
head
不再使用。注意你的风格,尽可能漂亮地键入代码。我不知道为了工作我必须做什么更改,我只想解释一下我必须添加的内容,以便删除最后两个,我还不习惯链表=/找到一张纸,在上面画你的列表。然后尝试手动删除一个节点,你会突然明白为什么你的函数不起作用。@iharob保持head=NULL不是更明智吗??如果你不这样做,头将包含一个指向某事物的指针,该事物是免费的,你以后就不会检查你是否已经有了一个有效的头。还是我错了?如果我确实受伤了,请纠正我,有什么问题吗?为什么不直接调用两次
deletesEnd
(ofc。这要求
deletesEnd
删除一项是正确的)?不进行尾部优化的列表递归迭代将是在不分配大量本地数据或递归锚失败的情况下获得堆栈溢出的方法之一。提供一个递归的解决方案是很好的,但是缺点应该提到。这段代码会在一个空列表上崩溃,或者在一个只有一个元素的列表上崩溃。。。实际上,它会在一个包含2个元素的列表中崩溃,可能还会有更多的情况发生。@chqrlie我不打算在这里检查所有的情况。我假设用户有一个完整的链接列表,正如他在他的a问题中所示。他需要检查一下休息情况。我只给了他逻辑。你可以在
free(current->next)之前删除测试
if(current->next)
<代码>自由(空)是完美定义的。
void del_tail_n2(struct llist **pp, unsigned nn)
{
struct llist *p;

        /* Advance p pointer n positions down, starting from *pp. */
for (p= *pp; p; p=p->next) {
        if (nn-- < 1) break;
        }

        /* Do a synchronous walk down for both p and *pp, until p is NULL. */
for ( ; p; p=p->next) {
        pp = &(*pp)->next;
        }

        /* Now, *pp is the first node to delete
        ** Delete it and everything below it.
        */
for ( ;(p = *pp); ){
        *pp = p->next;
        // free (p);
        }
return;
}
struct node *deletesEnd(struct node *head) {
    struct node *temp, *last;

    last = temp = head;
    while (temp && temp->next != NULL) {
        last = temp;
        temp = temp->next;
    }
    if (last == head) {
        free(head);
        head = NULL;
    } else {
        free(last->next);
        last->next = NULL;
    }
    return head;
}
struct node *deleteLast2Nodes(struct node *head) {
    struct node *temp, *last;

    last = temp = head;
    while (temp && temp->next != NULL && temp->next->next != NULL) {
        last = temp;
        temp = temp->next;
    }
    if (last == head) {
        if (head) {
            free(head->next);
        }
        free(head);
        head = NULL;
    } else {
        free(last->next->next);
        free(last->next);
        last->next = NULL;
    }
    return head;
}