4 Linked Lists
A practical guide to how linked lists store data, support traversal and updates, compare with arrays, and guide data-structure choices.
How linked lists are organized
A stores an ordered sequence as connected records rather than as a contiguous block of memory. Each contains a payload and one or more links to neighboring nodes. The links preserve the logical order even when the nodes are located in different memory locations.
The list keeps a reference to its first , called the . A ’s next link identifies the following , and the final ’s next link is null. Some implementations also maintain a , which refers to the last .
A useful mental model is a chain: the identifies where the chain begins, each identifies the next link in the chain, and null marks its end.
Takeaway: Linked lists trade direct positional access for flexible -based storage.
Singly and doubly linked lists
A gives each a link only to the next . To perform , begin at the and repeatedly follow next until the current reference is null. Visiting every in a list of nodes takes time.
Accessing the element at position also requires following links from the , so it takes time and can take time in the worst case. The list cannot move backward directly because nodes do not store links to their predecessors.
A adds a prev link to every . Its nodes can therefore move forward through next and backward through prev. The first has prev equal to null, and the last has next equal to null.
Doubly linked lists use more memory and require more link updates. If one link is updated without consistently updating the corresponding neighboring link, the structure can become invalid.
Takeaway: Singly linked lists are simpler and use less link storage; doubly linked lists provide bidirectional movement.
Insertion and deletion
Linked-list updates are efficient when the relevant location is already known. To insert a new at the front, connect the new to the current and then make the new the . This requires a constant number of reference changes and takes time.
If a reference to a named current is available, insertion after it can be performed by connecting the new to current.next and then connecting current to the new . The relinking takes time, but finding current by index or value may take time.
Deleting the first also takes time: save the current and advance the to its next . To delete a after a known predecessor, connect the predecessor directly to the removed ’s successor. The pointer update is , while locating the predecessor may take .
In a , removing a known requires reconnecting its previous neighbor to its next neighbor and updating the reverse link. This is when the target reference is already available.
Takeaway: Separate the cost of locating a position from the cost of changing links at that position.
Searching linked lists
A checks nodes one at a time. It begins at the , compares each ’s value with the target, and stops when it finds a match or reaches null. The best case is when the target is at the . The worst case is when the target is at the end or absent.
A sorted may stop once it encounters a value greater than the target, but ordinary binary search is still not efficient. Binary search needs fast access to the middle element, whereas finding that element in a requires walking through nodes.
Thus, linked lists are generally searched sequentially rather than by repeatedly jumping to a middle position.
Takeaway: Sorting can allow early stopping, but it does not give a fast random access.
Linked lists versus arrays
An and a both represent ordered sequences, but they favor different operations.
An provides indexed access in time because an element’s location can be calculated directly.
A usually needs time to access an arbitrary index because it must follow links from the .
Searching an unsorted or takes time.
Inserting or deleting near the front or middle of an commonly takes time because elements may need to shift.
Inserting or deleting after a known linked-list reference takes time because only links change.
Traversing all elements takes time in both structures.
Arrays usually have compact, contiguous storage, while linked lists use non-contiguous storage and require extra memory for links.
The linked-list comparison assumes that the insertion or deletion location is already known. If the program must first search for that location, the search cost must be included. A dynamic may also append in amortized time, although an occasional resize can take time.
Takeaway: Choose based on the dominant operation: arrays favor random access, while linked lists favor known-location structural changes.
Choosing the right structure
Choose a when the program mainly moves forward, low per- memory use matters, and updates can use a known predecessor. Its simpler structure reduces link-maintenance work.
Choose a when the program must move both forward and backward, or when nodes need to be removed efficiently using their own references. The extra prev link costs memory and creates another relationship that must remain consistent.
A is not automatically faster than an . Its advantage appears when frequent insertions and deletions matter more than fast indexing, compact storage, or favorable cache behavior. If a program frequently accesses elements by numeric position, an may be the better choice.
Takeaway: Match the structure to the access pattern, update pattern, memory constraints, and whether the relevant or predecessor is already known.