If you already have the element
, then indeed the delete operation has a time complexity of O(1).
But:
Java's LinkedList
class implements a doubly linked list, but its nodes are private. The API only provides access to the values in the linked list, not the nodes. So you never have a reference to the element to delete.
Even if you use an alternative implementation where you do have access to the nodes, you start out with a reference to the head node only, not with an array of references to all nodes in the list. So that means if you want to delete the kth node in the list, you'll have to traverse the list to locate it first. It is only fair to include that work in the work of deleting the kth node.
You wrote in a comment:
Suppose I have a LinkedList<Person> ll
, I have the Person p1
and I want to do ll.remove(p1)
.
That will not work like you hoped, because Person
does not have the prev/next properties. When you create LinkedList<Person> ll
, there is a private node class involved that contains a reference to a Person
, but has in addition those prev/next references. That p1
does not help you to get access to those prev/next members. You would still need to traverse the list to find which node has that particular p1
and then update that node. This is what Java's removeFirstOccurrence
does.
Should Java's LinkedList
have given access to nodes for better performance?
You may think that Java's choice to make the Node objects private and not provide methods to work on those nodes directly is a bad one, as it seems to make some operations on the list less efficient, but consider this:
If you have access to nodes directly, you can accidently make the list "inconsistent" in a way: you could:
- introduce cycles
- link to a node that is actually part of another list, and consequently:
- mutate another list B by mutating list A.
Even if those effects are acceptable in your scenario, then consider that you don't have a direct reference to each node in the linked list. If you would, then you really ended up with a collection of node references, where you have the additional task to manage CRUD operations on that collection. For instance, if it is a vector, then deletion of a node reference in that vector will be O(n). Or if it is a Map, you need unique keys for your nodes, while linked lists allow for duplicates.
Whatever that collection would be like, it would represent an additional overhead, and in some cases you might then decide to drop the linked list and only keep that collection. For instance, with a TreeMap you get the order, and you get sublinear methods to get, set and delete an entry.