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