【问题标题】:Algorithm to delete node from middle in a singly linked list从单链表中间删除节点的算法
【发布时间】:2021-06-21 09:49:20
【问题描述】:

我正在阅读《Cracking the Coding Interview》并做练习题,但我被困在了这个问题上:

“实现一个算法来删除中间的节点(即除第一个和最后一个节点之外的任何节点,不一定是确切的中间)或单链表,只允许访问该节点。

EXAMPLE 输入:链表中的节点 a->b->c->d->e->f 结果:没有返回任何内容,但是新的链表看起来像 a->b->d-> e->f"

void solution1(Node* node)
{
    if (node == NULL || node->next == NULL) {
        return;
    } else {
        Node* ptr = node;
        //ptr is the node accessible
        Node* ptr2 = ptr->next;
        ptr->data = ptr2->data;
        ptr->next = ptr2->next;
        delete ptr2;
    }
    cout << "updated list is" << endl;
    display();
}

我实现了这个功能,但我想确认它的复杂性。这将是 O(1) 空间和 O(1) 时间复杂度,对吧? 另外,如果我们想删除最后一个节点,我们如何使用一个虚拟节点呢?

【问题讨论】:

  • 请每个问题回答一个问题。为什么它与 O(1) 有什么不同?没有循环,没有调用其他函数(除了display,我假设实际上是O(N))
  • 这不适用于最后一个列表节点。此外,它违背了使用动态节点链接范例的目的。理想情况下,通过从列表中修剪节点来删除节点,将引用它的指针在列表中(例如,某个节点的next 指针或列表head 指针)设置为about-to-被删除节点的next 成员值。那时您可以删除现在孤立的节点并完成。简而言之,理想情况下,在像这样的列表管理操作期间,唯一需要使用的成员是头指针或列表中的 next 成员; 没有别的....
  • ...但是您无法使用提供的有限数据来做到这一点。例如中间某处的按值节点指针。您无法获取指向相关节点的next(或head),因此您可以执行的操作受到严重限制。简短版:残酷的任务,但也许你会从中有所收获。
  • 请注意,这是糟糕的 C++ 设计。问题出在ptr-&gt;data=ptr2-&gt;data; 行,它没有考虑异常安全。看来你想要std::move_if_noexcept 那里。这并不意味着在算法介绍课上这是一个糟糕的问题——你必须从某个地方开始学习。但对于生产代码,请坚持使用std::forward_list&lt;T&gt;
  • @msalters 它可能是(但我们缺少代码)一个带有两个指针的结构,所以不需要移动任何东西。不删除数据可能是也可能不是错误。变量的名称,更重要的是函数的名称……需要改进。

标签: c++ linked-list singly-linked-list


【解决方案1】:

实际上它取决于display() 的空间和时间复杂度,但如果您不考虑这一点,那么是的,它将是 O(1) 空间和 O(1) 时间。简单地使用delete node 删除最后一个节点将使前一个节点的next 指针成为悬空指针,因此如果没有指向前一个节点的指针(或链表的head 指针),您将无法删除最后一个节点。

【讨论】:

    【解决方案2】:

    是的,这个删除算法的时间和空间复杂度是O(1)。

    要确定虚拟节点,您可以自己创建一个虚拟标志:

    Node* dummy_flag = new Node();
    ...
    
    if (node == nullptr || node->next == dummy_flag) {
        return;
    }
    
    if (node->next == nullptr) { // if last node
        node->next = dummy_flag;
    } else {
        Node* next_node = node->next;
        node->data = next_node->data;
        node->next = next_node->next;
        delete next_node;
    }
    

    现在如果你的节点->next == dummy_flag 那么节点是虚拟的。

    【讨论】:

    • 另外我建议你使用 nullptr 而不是 NULL
    猜你喜欢
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    • 2021-02-21
    • 1970-01-01
    相关资源
    最近更新 更多