Linked list
In computer science, a linked list is one of the simplest data structures used in computer programming. It consists of a sequence of nodes, each containing arbitrary data fields and one or two references ("links") pointing to the next and/or previous nodes. Linked lists permit insertion and removal of nodes at any point in the list in constant time, but do not allow random access.
The simplest kind of linked list is a singly linked list, which has one link per node. This link points to the next node in the list, or to a null value if it is the last node.
Xor-linking is an elegant alternative to doubly-linked lists, where the two pointers fields are replaced by a single field.
The "data" field of a node can be another linked list. By this device, one can emulate arbitrary linked data structures with lists — a principle which is fundamental to the Lisp programming language, where linked lists are the primary (if not the only) data structuring mechanism.
Sometimes, linked lists are used to implement associative arrays, and are in this context called association lists. There is very little good to be said about this use of linked lists; they are easily outperformed by other data structures such as self-balancing binary search trees even on small data sets (see the discussion in associative array). However, sometimes a linked list is dynamically created out of a subset of nodes in such a tree, and used to more efficiently traverse that set.
As for most choices in computer programming and design, no method is well suited to all circumstances. A linked list data structure might work well in one case, and cause problems in another. This is a list of some of the common tradeoffs involving linked list structures.
Further memory savings can be achieved, in certain cases, by sharing the same tail elements among two or more lists. In this way, one can add new elements to the front of the list while keeping a reference to both the new and the old versions — which provides the simplest example of a persistent data structure.
On the other hand, compared to an array, the chief disadvantage of a linked list is that it only allows sequential access to elements, and only in one direction (from front to back). In particular, when removing or inserting an element in the middle of the list, one needs to know the address of the preceding element.
Another disadvantage of linked lists is the extra storage needed for the address fields, which often makes them impractical for lists of small data items such as characters or boolean values. Even more significant is the time cost of allocating memory separately for each new element (and, in some systems, of locating and recycling elements that cannot be reached; see garbage collection). There are a number of techniques to reduce this overhead, such as using a free list or memory pool, storing the data itself inside the nodes, and CDR coding.
When manipulating linked lists in-place, care must be taken to not use values that you have invalidated in previous assignments. This makes algorithms for inserting or deleting linked list nodes somewhat subtle. This section gives pseudocode for adding or removing nodes from singly, doubly, and circularly linked lists in-place. Throughout we will use null to refer to an end-of-list marker or sentinel, which may be implemented in a number of ways.
Our node data structure will have two fields:
With doubly-linked lists there are even more pointers to update, but also less information is needed, since we can use backwards pointers to observe preceding elements in the list. This enables new operations, and eliminates special-case functions. We will add a prev field to our nodes, pointing to the previous element, and a tail variable which always points to the last node in the list. Both head and tail are null for an empty list.
Iterating through a doubly linked list can be done in either direction. In fact, direction can change many times, if desired.
Forwards
These symmetric functions add a node either after or before a given node:
A curious way of implementing doubly linked lists that uses half as much space for pointers is the xor linked list.
Circularly-linked lists can be either singly or doubly linked. For both, their circular versions, which link all the nodes into a continuous circle without using null, benefit from the ability to traverse the full list beginning at any given node. This often allows us to avoid storing head and tail, although if the list may be empty we need a special representation for the empty list, such as a head variable which points to some node in the list or is null if it's empty; we use such a head here.
This representation significantly simplifies adding and removing nodes into a non-empty list, but empty lists are a special case. Assuming that someNode is some node in the list, this code iterates through that list starting with someNode:
Forwards
Backwards
Notice the postponing of the test to the end of the loop. This is important for the case where the list contains only the single node someNode.
This simple function inserts a node into a doubly-linked circularly linked list after a given element:
Inserting an element in a possibly empty list requires a special function:
Finally, removing a node must deal with the case where the list empties:
Many programming languages, such as Lisp and Scheme have singly linked lists built in. In other languages it is simple to create the data structure using references. For example, here is a complete example in C which adds the numbers 1 through n using a linked list:
Some linked list materials are available from the Stanford Computer Science department:
Variants
Singly linked lists

A singly linked list containing three integer valuesDoubly-linked list
A more sophisticated kind of linked list is a doubly linked list. Each node has two links, one to the previous node and one to the next.
An example of a doubly linked list.Circular lists
In a circularly linked list, the first and last nodes are linked together. This can be done for both singly and doubly linked lists. To traverse a circular linked list, you begin at any node and follow the list in either direction until you return to the original node. Sentinel nodes
Linked lists sometimes have a special dummy or sentinel node at the beginning and/or at the end of the list, which is not used to store data. Its purpose is to simplify or speed up some operations, by ensuring that every data node always has a previous and/or next node, and that every list (even one that contains no data elements) always has a "first" and "last" node.Applications of linked lists
Linked lists are used as a building block for many other data structures, such as stacks, queues and their variations.Tradeoffs
Linked lists vs. arrays
Linked lists have several advantages over arrays. For one thing, a linked list allows a new element to be inserted or deleted in any position, with a constant number of operations (changing a couple of pointers). Linked lists can also save memory in applications that need one or more lists of unpredictable size, since the total space used will be proportional to the number of elements actually present in all lists (as opposed to the number of lists times the maximum size of each list). Double-linking vs. single-linking
Double-linked lists require more space per node (unless one uses xor-linking), and their elementary operations are more expensive; but they are often easier to manipulate because they allow sequential access to the list in both directions. In particular, one can insert or delete a node, in a constant number of operations, given only that node's address. On the other hand, they do not allow tail-sharing.Circular lists
Circular linked lists are most useful for describing naturally circular structures, and have the advantage of regular structure and being able to traverse the list starting at any point; their main disadvantage is the complexity of iteration, which has subtle special cases.Sentinel nodes
Sentinel nodes may simplify certain list operations, by ensuring that the next and/or previous nodes exist for every element. However sentinel nodes use up extra space (especially in applications that use many short lists), and they may complicate other operations.Linked List Operations
Singly-linked lists
We also keep a variable head which always points to the first node in the list, or is null for an empty list. Traversal of a singly-linked list is easy:
node := head
while node not null
The following code inserts a node after an existing node in a singly linked list. Inserting a node before an existing one cannot be done; instead, you have to locate it while keeping track of the previous node.
node := node.next
insertAfter(node, newNode)
Inserting at the beginning of the list requires a separate function. This requires updating head.
newNode.next := node.next
node.next := newNode
insertBeginning(newNode)
Similarly, we have functions for removing the node after a given node, and for removing a node from the beginning of the list. To find and remove a particular node, one must again keep track of the previous element.
newNode.next := head
head := newNode
removeAfter(node)
Notice that removeBeginning() sets head to null when removing the last node in the list. nodeBeingRemoved := node.next
node.next := node.next.next
destroy nodeBeingRemoved
removeBeginning(node)
nodeBeingRemoved := head
head := head.next
destroy nodeBeingRemoved
Doubly-linked lists
node := head
while node not null
Backwards
node := node.next
node := tail
while node not null
node := node.prev
insertAfter(node,newNode)
We also need a function to insert a node at the beginning of a possibly-empty list:
newNode.prev := node
newNode.next := node.next
if node.next is null
tail := newNode
else
node.next.prev := newNode
node.next := newNode
insertBefore(node,newNode)
newNode.prev := node.prev
newNode.next := node
if node.prev is null
head := newNode
else
node.prev.next := newNode
node.prev := newNode
insertBeginning(newNode)
A symmetric function inserts at the end:
if head is null
head := newNode
tail := newNode
newNode.prev := null
newNode.next := null
else
insertBefore(head, newNode)
insertEnd(newNode)
Removing a node is easier, only requiring care with head and tail:
if tail is null
insertBeginning(newNode)
else
insertAfter(tail, newNode)
remove(node)
One subtle consequence of this procedure is that deleting the last element of a list sets both head and tail to null. if node.prev is null
head = node.next
else
node.prev.next = node.next
if node.next is null
tail := node.prev
else
node.next.prev = node.prev
destroy node
Circularly-linked lists
node := someNode
do
node := node.next
while node not someNode
node := someNode
do
node := node.prev
while node not someNode
insertAfter(node, newNode)
newNode.next := node.next
newNode.prev := node
node.next.prev := newNode
node.next := newNode
insertBeginning(node)
if head is null
node.prev := node
node.next := node
else
insertAfter(head.prev, node)
head := node
remove(node)
if node.next is node
head := null
else
node.next.prev := node.prev
node.prev.next := node.next
destroy node
Language Support
struct node {
int value;
struct node *next; /* next node in list */
};
int add_up_to(int n) {
struct node first_node; /* first item in the linked list */
struct node *p = &first_node;
int i, sum;
p->next = NULL;
/* Add the numbers 1 through n to the linked list */
for(i=1; i <= n; i++) {
struct node *new_node =
(struct node *)malloc(sizeof(struct node));
p->value = i;
new_node->next = NULL;
p->next = new_node;
p = new_node;
}
/* Iterate through the list, summing up the values */
sum = 0;
for(p = &first_node; p != NULL; p = p->next) {
sum = sum + p->value;
}
return sum;
}
Warning: This is just an example. This is not the best way to add the numbers 1 through n, and the memory allocated for the list nodes is not being freed, resulting in a memory leak. Take caution.Linked Lists On The Web