liveBook · Manning

Tail

As explained in Grokking Data Structures

The tail is the reference or position identifying the last node of a linked list.

The tail identifies the last node in a linked list. In a singly linked list, its next pointer is empty; in a doubly linked list, it also links back to its predecessor. section 6.4 section 6.24

Keeping a direct reference to the tail changes what the list can do efficiently:

  • Doubly linked lists can reach the tail in constant time and insert a new node after it without traversing the list. section 6.17
  • Deleting the final node requires updating the tail to the previous node; deleting the only node clears both tail and head. section 6.19 section 6.9
  • A doubly linked list can traverse backward from its tail, while a singly linked list can traverse only from head to tail. section 6.24

Appending at the back

An empty list assigns the new node to both _head and _tail. Otherwise, it saves the old tail, creates a new node, makes the new node the tail, and connects the old tail to it. section 6.17

def insert_to_back(self, data):
    if self._tail is None:
        self._tail = self._head = Node(data)
    else:
        old_tail = self._tail
        self._tail = Node(data)
        self._tail.prepend(old_tail)

Inspect the Python implementation that uses the tail reference to append directly at the back. section 6.17

def delete(self, target):
    node = self._search(target)
    if node is None:
        raise ValueError(f'{target} not found in the list.')
    if node.prev() is None:            #1
        self._head = node.next()
        if self._head is None:         #2
            self._tail = None
        else:
            self._head.prepend(None)
    elif node.next() is None:          #3
        self._tail = node.prev()
        self._tail.append(None)
    else:                              #4
        node.prev().append(node.next())
        del node
#1 Delete the node at the beginning of the list.
#2 In this case, the list’s head was the only element in the list.
#3 Delete the node at the end of the list.
#4 General case

Inspect how deletion updates the tail when removing the final node and clears it when the list becomes empty. section 6.19

How Grokking Data Structures covers it

How deep it goes
Explains tail semantics, constant-time end insertion, backward traversal, and deletion updates, but does not formalize implementation invariants.
Examples
Shows Python append and deletion implementations that assign, advance, or clear the tail.
What it assumes
Assumes linked-list nodes and pointers, while defining head, tail, successor, and predecessor relationships in plain language.
What you can do after
Build it from scratch by maintaining tail references during linked-list insertion and deletion.
How it connects
Connects the tail with linked lists, nodes, head pointers, singly linked lists, doubly linked lists, insertion, deletion, and traversal.

Also explained in

Compare how 3 books explain tail →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Grokking Data Structures. The section links point to the parts of the book it draws on.