链表:删除节点

时间:2021-04-16 13:22:51

标签: algorithm

假设要删除一个链表的第四个节点,p指向第四个节点?

为什么需要指向链表第三个节点的指针?

2 个答案:

答案 0 :(得分:0)

您需要引用前一个节点,因为它的下一个指针指向要删除的节点。这显然不能保持这样:需要更新下一个指针以跳过要删除的节点并指向下一个。

如果您只有对要删除的节点的引用,则无法在前一个节点上进行更新——除了从头节点开始在列表中开始新的遍历,以便找回前一个节点并进行更新。

这是一个带有五个节点和值 1、2、3、4 和 5 的链表的可视化:

 head
  ↓ 
┌───────────┐   ┌───────────┐   ┌───────────┐   ┌───────────┐   ┌───────────┐
│ value: 1  │   │ value: 2  │   │ value: 3  │   │ value: 4  │   │ value: 5  │
│ next: ——————→ │ next: ——————→ │ next: ——————→ │ next: ——————→ │ next:null │
└───────────┘   └───────────┘   └───────────┘   └───────────┘   └───────────┘

现在假设您要删除值为 4 的节点(我将其称为节点 4)……那么结果应该是:

 head
  ↓ 
┌───────────┐   ┌───────────┐   ┌───────────┐   ┌───────────┐   ┌───────────┐
│ value: 1  │   │ value: 2  │   │ value: 3  │   │ value: 4  │   │ value: 5  │
│ next: ——————→ │ next: ——————→ │ next: ──────┐ │ next:null │   │ next:null │
└───────────┘   └───────────┘   └───────────┘ │ └───────────┘   └───────────┘
                                              │                    ↑
                                              └────────────────────┘

...之后可以释放该节点使用的内存。

这里发生了两件事:

  • 节点 3 的 next 指针重定向到节点 5
  • 节点 4 的 next 指针设置为 NULL -- 这是可选的,但真正强调的是该节点不再与列表有关系。

由于我们需要更改 Node 3 中的某些内容,因此我们需要对其进行引用。当我们只有对节点 4 的引用时,这是一个问题。获得对节点 3 的引用的唯一方法是从 head 开始并从那里跟随 next 指针......直到我们到达节点 3。但那是浪费时间。

然而,如果我们有对节点 3 的引用,那么我们有对节点 4 的引用:它是位于节点 3 中的 next 指针!因此,当我们只有节点 3 的引用时,我们拥有了执行删除节点 4 所需的一切。

所以一个实现可能看起来像这样——我使用 c:

void delete_after(Node * prev) {
    Node * node = prev->next; // get a reference to the node that needs removal
    if (node == NULL) return; // Nothing to do
    // And here is the reason why we need prev:
    prev->next = node->next; // Rewire, skipping the node to delete
    node->next = NULL; // optional
    free(node);
}

答案 1 :(得分:0)

这里有两种情况:

  1. 第四个节点是链表中的最后一个节点:
    在这种情况下,我们将需要一个指向第三个节点的指针,因此我们可以为它更新下一个指针(也在@trincot 的回答中进行了解释)
  2. 节点数超过4个:
    在这里,您实际上不需要指向第三个节点的指针。您可以将第 5 个节点复制到第 4 个节点上,然后删除第 5 个节点。示例:让链表为 1 -> 3 -> 6 -> 2 -> 5 -> None。首先,我们将第 5 个节点复制到第 4 个节点上。该列表现在变为 1 -> 3 -> 6 -> 5 -> 5 -> None。由于您已经拥有指向第 4 个节点的指针,因此您可以轻松删除第 5 个节点(通过为第 4 个节点设置 node.next = node.next.next)。链表现在看起来像 1 -> 3 -> 6 -> 5 -> None,我们从原始链表中删除了第 4 个节点,而没有使用指向第三个节点的指针。