Skip to content

Singly Linked List

SinglyLinkedList (LinkedList)

A singly linked list is a linear collection of nodes whose head and tail nodes are unconnected. Each node contains a reference to the node succeeding it.

Instantiate a singly linked list object

>>> a_list = SinglyLinkedList()

Append an item to the list

>>> a_list.append(0)

The L.append(x) method is an alias of L.insert_last(x)

>>> a_list.insert_last(1)

Insert an item at the head of the list

>>> a_list.insert_first(2)

Insert an item at a specific index

>>> a_list.insert(1, 3)

Insert an item at an index that's out of range raises IndexError

>>> a_list.insert(100, 3)
Traceback (most recent call last):
...
IndexError: Index out of range

Get first item of the list

>>> a_list.get_first()
2

Get first item of an empty list raises Empty

>>> SinglyLinkedList().get_first()
Traceback (most recent call last):
...
linked_list.Empty: List is empty

Get last item of the list

>>> a_list.get_last()
1

Get last item of an empty list raises Empty

>>> SinglyLinkedList().get_last()
Traceback (most recent call last):
...
linked_list.Empty: List is empty

Get item at a specific index

>>> a_list[1]
3

Get item at an index that's out of range raises IndexError

>>> a_list[100]
Traceback (most recent call last):
...
IndexError: Index out of range

Get items at slice range of the list

>>> a_list[1:3]
[3, 0]

Get items at a slice that's out of range raises IndexError

>>> a_list[1:100]
Traceback (most recent call last):
...
IndexError: Index out of range

Get items at a slice with a slice step of less than one raises a ValueError

>>> a_list[1:3:0]
Traceback (most recent call last):
...
ValueError: Step needs to be greater than zero

Get an iterable object of the list

>>> iterable_object = iter(a_list)

Get next item of the iterable object

>>> next(iterable_object)
2

Get next item of the list iterator

>>> next(a_list)
3

Get length of the the list

>>> len(a_list)
4

Get a string representation of the list

>>> str(a_list)
'[2, 3, 0, 1]'
>>> a_list
[2, 3, 0, 1]

Delete first item of the list

>>> a_list.remove_first()

Delete first item of an empty list raises Empty

>>> SinglyLinkedList().remove_first()
Traceback (most recent call last):
...
linked_list.Empty: List is empty

Delete last item of the list

>>> a_list.remove_last()

Delete last item of an empty list raises Empty

>>> SinglyLinkedList().remove_last()
Traceback (most recent call last):
...
linked_list.Empty: List is empty

Delete item at a specific index

>>> del a_list[0]

Delete item of at an index that's out of range raises IndexError

>>> del a_list[100]
Traceback (most recent call last):
...
IndexError: Index out of range

Replace item at a specific index

>>> a_list[0] = 100

Replace item of at an index that's out of range raises IndexError

>>> a_list[100] = 100
Traceback (most recent call last):
...
IndexError: Index out of range

Delete all items from the list

>>> a_list.remove_all()
>>> a_list
[]

get_last(self)

Return item at the tail of the list. Time complexity: O(n).

Returns:

Type Description
Any

last item in list

Exceptions:

Type Description
Empty

when the list is empty

Source code in linked_lists/singly_linked_list.py
def get_last(self) -> Any:
    """Return item at the tail of the list. Time complexity: O(n).

    :return: last item in list
    :raises Empty: when the list is empty
    """
    if self._length == 0:
        raise Empty("List is empty")

    current_node = self._head.next_node

    while not isinstance(current_node.next_node, LinkedList._SentinelNode):
        current_node = current_node.next_node

    return current_node.data

insert_last(self, data)

Add item at the tail of the list. Time complexity: O(n).

Parameters:

Name Type Description Default
data Any

item to insert

required
Source code in linked_lists/singly_linked_list.py
def insert_last(self, data: Any) -> None:
    """Add item at the tail of the list. Time complexity: O(n).

    :param data: item to insert
    """
    self._length += 1

    previous_node = self._head
    current_node = previous_node.next_node

    while not isinstance(current_node, LinkedList._SentinelNode):
        previous_node = current_node
        current_node = current_node.next_node

    SinglyLinkedList._insert_between(
        LinkedList._Node(data), previous_node, current_node
    )

remove_last(self)

Delete item at the tail of the list. Time complexity: O(n).

Exceptions:

Type Description
Empty

when the list is empty

Source code in linked_lists/singly_linked_list.py
def remove_last(self) -> None:
    """Delete item at the tail of the list. Time complexity: O(n).

    :raises Empty: when the list is empty
    """
    if self._length == 0:
        raise Empty("List is empty")

    self._length -= 1
    previous_node = self._head
    current_node = previous_node.next_node

    while True:
        if isinstance(current_node.next_node, LinkedList._SentinelNode):
            break
        previous_node = current_node
        current_node = current_node.next_node

    SinglyLinkedList._remove_between(previous_node, current_node.next_node)