单链接列表插入和删除的时间复杂度

时间:2014-03-24 02:49:59

标签: c++ data-structures linked-list

我对链接列表的时间复杂性感到有些困惑。在本文here中,它指出链接列表中的插入和删除是O(1)。我想知道这是怎么回事?假设前向和下一个指针是已知的吗?那不就是Double Linked List吗?如果有人能澄清这一点,我将不胜感激。以及单个链表的插入/删除的时间复杂度如何是O(1)?

3 个答案:

答案 0 :(得分:4)

  

是否假设前向和下一个指针已知?

在单链表中,对于插入和删除,您需要在插入/删除点之前指向元素。一切顺利。

例如:

# insert y after x in O(1)
def insert_after(x, y): 
    y.next = x.next
    x.next = y

# delete the element after x in O(1)
def delete_after(x):
    x.next = x.next.next

对于许多应用程序,很容易通过算法携带您当前正在查看的项目的前身,以允许在恒定时间内动态插入和删除。当然,您总是可以在O(1)中的列表前面插入和删除,这允许类似堆栈(LIFO)的使用模式。

当您只知道指向该项目的指针时,删除项目通常在O(1)中编辑:正如codebeard所示,我们只需知道指向插入/删除点的指针就可以 插入和删除。它涉及从后继者复制数据,从而避免修复前一个的next指针。

答案 1 :(得分:3)

是的,假设您已经知道要插入数据的位置。

假设您在列表中有一些项目p,并且您希望在列表中new之后插入新元素p

new->next = p->next;
p->next = new;

或者,假设您要在 new之前插入p 。这仍然可以在O(1)时间内完成:

if (p == head) {
    new->next = head;
    head = new;
} else {
    tmp = p->data;
    p->data = new->data;
    new->data = tmp;
    new->next = p->next;
    p->next = new;
}

至于删除传统单链表中的项目,严格来说不是O(1)!

删除 last 元素以外的任何元素是O(1)。如果你试图删除单链表中的最后一个元素,你需要知道它之前的元素(假设你之前不知道它需要O(N)时间)。

删除项目p

free_if_necessary(p->data);
if (p->next) {
    /* O(1) */
    nextnext = p->next->next;
    nextdata = p->next->data;
    destroy_if_necessary(p->next);
    p->data = nextdata;
    p->next = nextnext;
} else if (p == head) {
    destroy_if_necessary(p);
    head = NULL;
} else {
    /* O(n) */
    prev = find_prev(head, p);
    destroy_if_necessary(p);
    prev->next = NULL;
}

答案 2 :(得分:0)

这可能与数组的删除和插入操作有关。

前提条件是您知道插入或删除的位置。

在数组中,如果要在位置pos处插入或删除元素,则应将其他元素移到位置pos之后,因此复杂度为O(N)

但在List中,当您执行相同的操作时,您不需要考虑其他元素,因此复杂度为O(1)