It is said that the complexity of the LinkedList remove and the add operation is of O(1). and in case of ArrayList it is of O(n).
Calculation for ArrayList of size "M" : if i want to remove the element at Nth position then i can directly go to the Nth position using index in one go (i don't have to traverse till Nth index) and then i can remove the element, till this point the complexity is O(1) then i will have to shift the rest of the elements(M-N shifts) so my complexity will be linear i.e. O(M-N+1). and hence deletion or insertion at the last will give me the best performence( as N ~ M) and deletion or insertion at the start will be worst (as N ~ 1).
Now the LisnkedList of size "M" : as we can not directly reach the Nth element in the LinkedList, to access the Nth element we have to traverse N elements, so the search in the LinkedList is costlier then the ArrayList...but Remove and the add operations are said to be of O(1) in case of LinkedList as, in LinkedList the Shift is not involved, but there is traverse operation involved rigth ? so the complexity should be of order O(n) where Worst performence will be at the tail node and best performence will be at the head node.
Could anyone please explain me why don't we consider the traverse cost while calculating the complexity of LinkedList remove operation ?
So i wants to understand how it works in java.util package. and if i want to implemet the same in C or C++ how would i achieve the O(1) for random deletion and insertion in LinkedList ?
Remove and the add operations are said to be of O(1) in case of
LinkedListas, inLinkedListthe shift is not involved, but there is traverse operation involved right?
Adding to either end of a linked list does not require a traversal, as long as you keep a reference to both ends of the list. This is what Java does for its add and addFirst/addLast methods.
Same goes for parameterless remove and removeFirst/removeLast methods - they operate on list ends.
remove(int) and remove(Object) operations, on the other hand, are not O(1). They requires traversal, so you correctly identified their costs as O(n).
The complexity of removing is considered that you already have the pointer to the right position of the element you want to remove...
Is not considered the cost you took for finding it
Information on this topic is now available on Wikipedia at: Search data structure
+----------------------+----------+------------+----------+--------------+
| | Insert | Delete | Search | Space Usage |
+----------------------+----------+------------+----------+--------------+
| Unsorted array | O(1) | O(1) | O(n) | O(n) |
| Value-indexed array | O(1) | O(1) | O(1) | O(n) |
| Sorted array | O(n) | O(n) | O(log n) | O(n) |
| Unsorted linked list | O(1)* | O(1)* | O(n) | O(n) |
| Sorted linked list | O(n)* | O(1)* | O(n) | O(n) |
| Balanced binary tree | O(log n) | O(log n) | O(log n) | O(n) |
| Heap | O(log n) | O(log n)** | O(n) | O(n) |
| Hash table | O(1) | O(1) | O(1) | O(n) |
+----------------------+----------+------------+----------+--------------+
* The cost to add or delete an element into a known location in the list (i.e. if you have an iterator to the location) is O(1). If you don't know the location, then you need to traverse the list to the location of deletion/insertion, which takes O(n) time.
** The deletion cost is O(log n) for the minimum or maximum, O(n) for an arbitrary element.
Yes, you are corrrect if you consider two operations (indexing and inserting) in one go. It is not true in this case because when you are inserting a node in the middle of a linked list, the assumption taken is that you are already at the address where you have to insert the node.
The time complexity of accessing the node is O(n) whereas only inserting a node is O(1).
Insertion at the head requires you to add the element and update the head pointer.
newnode->next = head;
head = newnode;
Insertion at the tail requires you to keep a pointer to the tail element, add the element at the tail and update the tail pointer.
tail->next = newnode;
tail = newnode;
Deleting the head element requires updating the head and deleting the previously head element.
temp = head;
head = head->next;
delete temp; /* or free(temp); */
All the above are trivial operations and don’t depend upon the number of elements in linked list. Hence, they are O(1)
Deleting the tail element would, however, be a O(n) operation because even though you might have a tail pointer, you would still need the penultimate node that would be setup as the new tail node ( by updating the tail pointer and setting the node’s next member to NULL). For this, you need to traverse through the whole linked list.
penultimate_el = find_penultimate_el(head); /* this is O(n) operation */
delete tail; /* or free(tail) */
tail = penultimate_el;
tail->next = NULL;