【发布时间】:2010-12-26 03:07:10
【问题描述】:
为什么在双向链表中删除节点的时间复杂度(O(1))比在单链表中删除节点的时间复杂度(O(n))快?
【问题讨论】:
标签: linked-list complexity-theory time-complexity singly-linked-list doubly-linked-list
为什么在双向链表中删除节点的时间复杂度(O(1))比在单链表中删除节点的时间复杂度(O(n))快?
【问题讨论】:
标签: linked-list complexity-theory time-complexity singly-linked-list doubly-linked-list
问题假设要删除的节点是已知的,并且指向该节点的指针可用。
为了删除一个节点并将前一个节点和下一个节点连接在一起,您需要知道它们的指针。在双向链表中,两个指针在要删除的节点中都可用。在这种情况下,时间复杂度是恒定的,即 O(1)。
而在单链表中,指向前一个节点的指针是未知的,只能通过从头遍历列表直到到达具有指向要删除的节点的下一个节点指针的节点才能找到。这种情况下的时间复杂度是 O(n)。
如果要删除的节点仅通过值知道,则必须搜索列表,并且在单链表和双链表中时间复杂度都变为 O(n)。
【讨论】:
实际上单链表中的删除也可以在O(1)中实现。
给定一个具有以下状态的单链表:
SinglyLinkedList:
Node 1 -> Node 2
Node 2 -> Node 3
Node 3 -> Node 4
Node 4 -> None
Head = Node 1
我们可以这样实现delete Node 2:
Node 2 Value <- Node 3 Value
Node 2 -> Node 4
这里我们将Node 2的值替换为其下一个节点的值(Node 3),并将其下一个值指针设置为Node 3的下一个值指针(Node 4),有效地跳过了现在“重复”Node 3。因此不需要遍历。
【讨论】:
因为你不能向后看……
【讨论】:
在已知位置插入和删除是 O(1)。但是,找到该位置是 O(n),除非它是列表的头部或尾部。
当我们谈论插入和删除复杂性时,我们通常假设我们已经知道这将发生在哪里。
【讨论】:
这与修复要删除的节点之前的节点中的下一个指针的复杂性有关。
【讨论】:
除非要删除的元素是头(或第一个)节点,否则我们需要遍历到要删除的节点之前的节点。因此,在最坏的情况下,即当我们需要删除最后一个节点时,指针必须一直到达倒数第二个节点,从而遍历 (n-1) 个位置,这给了我们 O(n) 的时间复杂度.
【讨论】:
我不认为它是 O(1),除非你知道 必须删除的节点.....不要循环到达必须从头中删除的节点????
如果您拥有必须删除的节点地址,则为 O(1),因为您拥有它的 prev node link 和 next node link 。 由于您拥有所有必要的链接,只需通过重新排列链接然后 free() 将“感兴趣的节点”从列表中删除。
但是在单个链表中,您必须从 head 遍历以获得它的上一个和下一个地址,无论您是否拥有要删除的节点的地址或节点位置(如 1st ,2nd ,10th等等,。)将被删除。
【讨论】:
假设有一个从 1 到 10 的链表,你必须删除给定位置的节点 5。
1 -> 2 -> 3 -> 4 -> 5-> 6-> 7-> 8 -> 9 -> 10
您必须将 4 的下一个指针连接到 6 才能删除 5。
4->next = 5->next;
或
Node* temp = givenNode->prev;
temp->next = givenNode->next;
时间复杂度 = O(1)
Node* temp = head;
while(temp->next != givenNode)
{
temp = temp->next;
}
temp->next = givenNode->next;
时间复杂度 = O(N)
【讨论】: