An SLList (singly-linked list) is a sequence of Nodes. Each node stores a data value and a reference to the next node in the sequence. For the last node in the sequence,
class Node { T x; Node next; }
For efficiency, an SLList uses variables and to keep track of the first and last node in the sequence, as well as an integer to keep track of the length of the sequence:
Node head; Node tail; int n;A sequence of Stack and Queue operations on an SLList is illustrated in Figure 3.1.
An SLList can efficiently implement the Stack operations and by adding and removing elements at the head of the sequence. The operation simply creates a new node with data value , sets to the old head of the list and makes the new head of the list. Finally, it increments since the size of the SLList has increased by one:
T push(T x) { Node u = new Node(); u.x = x; u.next = head; head = u; if (n == 0) tail = u; n++; return x; }
The operation, after checking that the SLList is not empty, removes the head by setting and decrementing . A special case occurs when the last element is being removed, in which case is set to :
T pop() { if (n == 0) return null; T x = head.x; head = head.next; if (--n == 0) tail = null; return x; }
Clearly, both the and operations run in time.
An SLList can also implement the FIFO queue operations and in constant time. Removals are done from the head of the list, and are identical to the operation:
T remove() { if (n == 0) return null; T x = head.x; head = head.next; if (--n == 0) tail = null; return x; }
Additions, on the other hand, are done at the tail of the list. In most cases, this is done by setting , where is the newly created node that contains . However, a special case occurs when , in which case . In this case, both and are set to .
boolean add(T x) { Node u = new Node(); u.x = x; if (n == 0) { head = u; } else { tail.next = u; } tail = u; n++; return true; }
Clearly, both and take constant time.
The following theorem summarizes the performance of an SLList:
An SLList nearly implements the full set of Deque operations. The only missing operation is removing from the tail of an SLList. Removing from the tail of an SLList is difficult because it requires updating the value of so that it points to the node that precedes in the SLList; this is the node such that . Unfortunately, the only way to get to is by traversing the SLList starting at and taking steps.
opendatastructures.org