However, the loop will always iterate a specific number of times depending on how many items are in the list. This makes me believe it's actually O(1).
Am I wrong?
Your reasoning is wrong.
A complexity analysis of an algorithm needs to take account of all possible inputs.
While the number of elements in a single given list can be assumed to be constant while you are looping, the number of elements in any list is not a constant. If you consider all possible lists that could be inputs to the algorithm, the length of the list is a variable whose value can get arbitrarily large1.
If we call that variable N
then it is clear that the complexity class for your algorithm is O(N)
. (I won't go into the details because I think you already understand them.)
The only way that your reasoning could be semi-correct would be if you could categorically state that the input list length was less than some constant L
. The complexity class then collapses to O(1)
. However even this reasoning is dubious2, since the algorithm as written does not check that constraint. It has no control over the list length!
On the other hand, if you rewrote the algorithm as this:
public static final int L = 42;
public Node<T> enqueue(T data){
Node<T> toQueue = new Node<>(data);
if (this.head == null) {
this.head = toQueue;
return toQueue;
}
Node<T> lastNode = this.head;
int count = 0;
while(lastNode.next != null){
lastNode = lastNode.next;
if (count++ > L) {
throw InvalidArgumentException("list too long");
}
}
lastNode.next = toQueue;
return toQueue;
}
then we can legitimately say that the method is O(1)
. It will either give a result or throw an exception within a constant time.
1 - I am ignoring the fact that there are practical limits on how long a simple linked list like this can be in a Java program. If the list is too large, it won't fit in the heap. And there are limits on how large you could make the heap.
2 - A more mathematically sound way to describe the scenario is that your algorithm is O(N)
but your use of the algorithm is O(1)
because the calling code (not shown) enforces a bound on the list length.