问题
I do not quiet understand why deleting at the end of a single linked list goes in O(1) time, as the wikipedia article says.
A single linked list consists out of nodes. A node contains some kind of data, and a reference to the next node. The reference of the last node in the linked list is null.
-------------- -------------- --------------
| data | ref | -> | data | ref | -> ... -> | data | ref |
-------------- -------------- --------------
I indeed can remove the the last node in O(1). But in that case you don't set the reference of the newly last node, the previous one, to null since it still contains the reference to the deleted last node. So I was wondering do they neglect that in the running time analysis? Or is it consired that you don't have to change that since the reference, well, just points to nothing, and such is seen as null?
Because if it would not be neglected I would argue that deleting is O(n). Since you have to iterate over the whole list to get to the newly last node and set its reference also to null. Only in a double linked list it would be really O(1).
-edit- Maybe this point of view gives some more clearence. But I see "deletion of a node" as succesfully deleting the node itself and setting the previous reference to null.
回答1:
I am not sure I see in the Wikipedia article where it says that it's possible to remove the last entry of a singly-linked list in O(1) time, but that information is incorrect in most cases. Given any individual node in a linked list, it is always possible to remove the node after it in O(1) time by rewiring the list around that new node. Consequently, if you were given a pointer to the penultimate node in a linked list, then you could delete the last element of the list in O(1) time.
However, if you didn't have any extra pointers into the list other than a head pointer, then you could not delete the last element of the list without scanning to the end of the list, which would require Θ(n) time, as you have noted. You are absolutely correct that just deleting the last node without first changing the pointers into it would be a Very Bad Idea, since if you were to do this the existing list would contain a pointer to a deallocated object.
More generally - the cost to do an insertion or deletion in a singly-linked list is O(1), assuming you have a pointer to the node right before the one you want to insert or delete. However, you might have to do extra work (up to Θ(n)) to find that node.
Hope this helps!
回答2:
The addition/deletion of ANY node at ANY location is O(1). Code just play with fixed cost (few pointers calculations and malloc/frees) to add/delete the node. This arithmetical cost is fixed for any specific case.
However, the cost to reach(Indexing) the desired node is O(n).
The article is merely listing the addition/deletion in multiple sub-categories(adding in middle, beginning, end) to show that cost for adding in middle differs than adding in beginning/end (But the respective costs are still fixed).
回答3:
For example, you can have a pointer to the element before last ("second from end") and when deleting: 1. Delete *next of this "second from end" element. 2. Set this "second from end" *next to NULL
回答4:
If you're including the cost of fixing the dangling node, you can still do it in O(1) with the use of sentinel node for the end (also described on that page).
Your "empty" list starts with a single sentinel
Head -> [Sentinel]
Add some stuff
Head -> 1 -> 2 -> 3 -> [Sentinel]
Now delete the tail (3) by marking the node that was 3 as invalid, and then removing the link to the old sentinel, and freeing the memory for it:
Head -> 1 -> 2 -> 3 -> [Sentinel]
Head -> 1 -> 2 -> [Sentinel] -> [Sentinel]
Head -> 1 -> 2 -> [Sentinel]
回答5:
O(1) simply means "constant cost". It does not mean 1 operation. It means "at most C" operations with C being fixed regardless of other parameters changing (such as list size). In fact, in the sometimes confusing world of big-Oh: O(1) == O(22).
By contrast deleting the whole list has O(n) cost, because the cost changes with the size (n) of the list.
回答6:
For future reference, I must say after some research I found that none of the arguments provided in response to this question are relevant. The answer is that we simply decide for the top of the stack to be the head of the linked list (rather than the tail). This will introduce a slight change into the push routine but then the pop and push will both remain o(1).
回答7:
If you are give a pointer to the node to be deleted in a single linked list, then you can delete this node in constant time by simply copying the next node onto the node to be deleted.
M pointer to node to delete
M.data=M.next.data
M.next=M.next.next
Otherwise, if you need to search for the node then you cannot do better than O(n)
回答8:
Yes, you can do this in O(1) time even if you're not maintaining a pointer to the "previous element".
Let's say you have this list, where "head" and "tail" are static pointers, and "End" is a node marked as an end. You can use "next == NULL" as normal, but in this case you have to disregard the value:
head -> 1 -> 2 -> 3 -> 4 -> 5 -> End <- tail
Now, you're given a pointer to node 3, but not its previous node. you have the head and tail pointers too. Here's some python-ish code, assuming a SingleLinkedList class.
class SingleLinkedList:
# ... other methods
def del_node(self, node): # We "trust" that we're only ever given nodes that are in this list.
if node is self.head:
# Simple case of deleting the start
self.head = node.next
# Free up 'node', which is automatic in python
elif node.next is self.tail
# Simple case of deleting the end. This node becomes the sentinel
node.value = None
node.next = None
# Free up 'self.tail'
self.tail = node
else:
# Other cases, we move the head's value here, and then act
# as if we're deleting the head.
node.value = self.head.value
self.head = self.head.next
new_head = self.head.next
# Free up 'self.head'
self.head = new_head
Alas, this reorders the list, and moves values around, which may or may not be okay for your application.
来源:https://stackoverflow.com/questions/14048143/why-is-deleting-in-a-single-linked-list-o1