删除链表的最后一个节点,并将其添加到另一个链表

Remove last node of a linked list, and add this to another linked list

我正在尝试弄清楚如何操作链表。我想删除给定链表的结束节点并将其添加到另一个给定链表的末尾。

出于某种原因,我无法得到正确的指示,好吧 - 至少那是我认为的问题所在。

(此方法位于一个 while 循环中,因此一个列表不断变小,而另一个列表不断增长。)

void movenode(struct Node **cards,struct Node **column)
{
    struct Node *head = NULL;
    struct Node *tmp,*head1 = *cards;
    struct Node *tmp2,*head2 = *column;

    if (*cards == NULL || (*cards)->next == NULL){
        return;
    }
    while (tmp->next != NULL) {
        head->next = tmp;
        tmp = tmp->next;
    }
    while (tmp2->next != NULL) {
        tmp2 = tmp2->next;
    }
    head->next = NULL;
    tmp2->data = tmp;
    tmp2->next = NULL;


    *cards = head1;
    *column = head2;
}

希望有人能帮助我更好地理解这一点。

我不完全确定你的解决方案的机制,所以我将提供一个单独的实现和解决方案。

typedef struct Node {
    void *data;
    struct Node *next;
}

void poppush(Node *popHead, Node *pushHead) {
    Node *pushLastNode = pushHead;
    while (pushLastNode->next != NULL) {
        pushLastNode = pushLastNode->next;
    }

    Node *popLastNode = popHead;
    while (popLastNode->next != NULL) {
        popLastNode = popLastNode->next;
    }

    Node *popSecondLastNode = popHead;
    while (popSecondLastNode->next != popLastNode) {
        popSecondLastNode = popSecondLastNode->next;
    }

    popSecondLastNode->next = NULL;
    pushLastNode->next = popLastNode;
}

但是,对于此类操作,我建议使用 doubly-linked 列表 and/or 创建一些专用于管理列表的函数。

For some reason I can not get my pointers right, well.. atleast that is where I think the problem lays.

你说得对,但还不止于此。例如,在 struct Node *head = NULL; 之后,没有任何内容会修改 head 中的值,因此每次您执行 head->next 时,您都在访问“NULL + 一个小偏移量”的内存(并且可能会崩溃)。

要从单链表中删除最后一个条目,您必须找到最后一个条目之前的条目(以便您可以修改其next);并且要将条目添加到链接列表中,您必须找到最后一个条目(以便您可以修改其 next)。考虑到这一点,我们可以将其分为 5 个部分:

  • 进行完整性检查

  • 查找 *cards 列表中最后一个条目之前的条目

  • 删除 *cards 列表中的最后一个条目

  • 找到 *column 列表中的最后一个条目

  • 将(删除的)条目添加到 *columns 列表的末尾

您可以一次实现这 5 个部分中的每一个(并测试它们)。这是编程的重要组成部分 - 将更复杂的东西分解成更简单的东西。

生成的代码可能类似于(未经测试):

void movenode(struct Node **cards,struct Node **column) {
    struct Node *temp = *cards;
    struct Node *removed;

    // Do sanity checks

    if (temp == NULL) {
        return;
    }

    // Find the entry before the last entry in the `*cards` list

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

    // Remove the last entry in the `*cards` list

    if(temp == NULL) {
        // The last entry was the first entry
        removed = temp;
        *cards = NULL;
    } else {
        removed = temp->next;
        temp->next = NULL;
    }

    // Find the last entry in the `*column` list

    temp = *column;
    if(temp != NULL) {
        while(temp->next != NULL) {
            temp = temp->next;
        }
    }

    // Add the (removed) entry to the end of the `*columns` list       

    if(temp == NULL) {
        // There was no last entry (list was empty)
        *column = removed;
    } else {
        temp->next = removed;
    }
 }