cs_survival_kit.data_structures.singly_linked_list ¶
A singly linked list with head and tail references.
Provides SinglyLinkedList, a sequence built from nodes that each hold one
element and a link to the next node. Keeping a reference to both ends makes
adding at either end O(1). Removing from the front is also O(1), but finding
an element by position or value means walking the chain, so those operations
are O(n).
SinglyLinkedList ¶
Bases: AbstractList[T]
A sequence of nodes, each linked to the next, with head and tail references.
Each element lives in its own node, and each node links only forward to
the next one. The list keeps references to the first node (head) and the
last node (tail), plus a running size count:
headmakesprependandpop_frontO(1).tailmakesappendO(1). Without it, appending would mean walking the whole chain to find the last node.- The size count makes
lenO(1) instead of a full traversal.
Links only point forward, so there is no fast way to reach a node's
predecessor. Removing the last element would require walking from the head
to the second-to-last node, so the list offers no O(1) pop_back. That
limitation is what a doubly linked list removes.
Compared with DynamicArray, adding at the front is O(1) instead of O(n),
but indexing is O(n) instead of O(1), and every element pays for an extra
node object and link.
Unlike list, indexing accepts only non-negative indices in the range
0 <= index < len(self). Negative indices and slices are not supported.
Complexity
| Operation | Time | Space |
|---|---|---|
prepend |
O(1) | O(1) |
append |
O(1) | O(1) |
pop_front |
O(1) | O(1) |
a[i] |
O(n) | O(1) |
item in a |
O(n) | O(1) |
remove |
O(n) | O(1) |
reverse |
O(n) | O(1) |
len(a) |
O(1) | O(1) |
| iteration | O(n) | O(1) |
Total storage is O(n): one node per element.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
items
|
Iterable[T]
|
Elements to add to the new list, in order. Defaults to empty. |
()
|
Examples:
>>> a = SinglyLinkedList[int]([2, 3])
>>> a.prepend(1)
>>> a.append(4)
>>> a
SinglyLinkedList([1, 2, 3, 4])
>>> a.pop_front()
1
>>> a[1], 3 in a, len(a)
(3, True, 3)
>>> a.reverse()
>>> list(a)
[4, 3, 2]
- Data Structures Singly Linked List
Source code in lib/cs_survival_kit/data_structures/singly_linked_list.py
__len__ ¶
Return the number of elements in the list.
Returns:
| Type | Description |
|---|---|
int
|
The number of elements in the list. |
Complexity
- Time: O(1), from the stored size count
- Space: O(1)
Source code in lib/cs_survival_kit/data_structures/singly_linked_list.py
__iter__ ¶
Iterate over the elements from head to tail.
Yields:
| Type | Description |
|---|---|
T
|
Each element, in list order. |
Complexity
- Time: O(n) to exhaust the iterator
- Space: O(1)
Source code in lib/cs_survival_kit/data_structures/singly_linked_list.py
__getitem__ ¶
Return the element at index.
Nodes are scattered in memory and each one only knows where the next
node is, so there is no way to compute where element index lives.
The lookup walks index links from the head. An array can jump
straight there because its elements sit at evenly spaced positions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index
|
int
|
The position of the element. Must satisfy
|
required |
Returns:
| Type | Description |
|---|---|
T
|
The element at |
Raises:
| Type | Description |
|---|---|
IndexError
|
If |
Complexity
- Time: O(n); O(index) links are followed
- Space: O(1)
Source code in lib/cs_survival_kit/data_structures/singly_linked_list.py
__contains__ ¶
Return whether item is in the list.
Checks the elements from the head onward and stops at the first match.
An element matches if it is item or equals it, the same rule that
list uses.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item
|
object
|
The value to look for. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Complexity
- Time: O(n)
- Space: O(1)
Source code in lib/cs_survival_kit/data_structures/singly_linked_list.py
__repr__ ¶
Return a string showing the class name and the elements, like list.
Returns:
| Type | Description |
|---|---|
str
|
A string such as |
Source code in lib/cs_survival_kit/data_structures/singly_linked_list.py
prepend ¶
Add item to the front of the list.
The new node links to the current head and becomes the new head. No existing element moves. An array must shift every element one slot to the right to make room at index 0, which costs O(n).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item
|
T
|
The element to add. |
required |
Complexity
- Time: O(1)
- Space: O(1) for the new node
Examples:
- Data Structures Singly Linked List Working at the front
Source code in lib/cs_survival_kit/data_structures/singly_linked_list.py
append ¶
Add item to the end of the list.
The tail reference points straight at the last node, so the new node
is linked after it and becomes the new tail. Without a tail reference,
finding the last node would mean walking the whole chain, making
append O(n).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item
|
T
|
The element to add. |
required |
Complexity
- Time: O(1)
- Space: O(1) for the new node
Examples:
- Data Structures Singly Linked List Working at the end
Source code in lib/cs_survival_kit/data_structures/singly_linked_list.py
pop_front ¶
Remove and return the first element.
The head moves to the second node. If that empties the list, the tail is cleared too.
Returns:
| Type | Description |
|---|---|
T
|
The element that was at the front of the list. |
Raises:
| Type | Description |
|---|---|
IndexError
|
If the list is empty. |
Complexity
- Time: O(1)
- Space: O(1)
Examples:
>>> a = SinglyLinkedList[int]([1])
>>> a.pop_front()
1
>>> a.pop_front()
Traceback (most recent call last):
...
IndexError: pop_front from empty list
- Data Structures Singly Linked List Working at the front
Source code in lib/cs_survival_kit/data_structures/singly_linked_list.py
remove ¶
Remove the first element that matches item.
Only the first match, scanning from the head, is removed. An element
matches if it is item or equals it, as in item in a. Unlinking a
node means pointing its predecessor's next past it, and nodes have no
backward link, so the scan carries a reference to the previous node as
it goes. The head and tail references are updated when the removed node
is at either end.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item
|
T
|
The value to remove. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no element matches |
Complexity
- Time: O(n)
- Space: O(1)
Examples:
>>> a = SinglyLinkedList[int]([1, 2, 1])
>>> a.remove(1)
>>> a
SinglyLinkedList([2, 1])
>>> a.remove(5)
Traceback (most recent call last):
...
ValueError: item not in list
- Data Structures Singly Linked List Finding an element
Source code in lib/cs_survival_kit/data_structures/singly_linked_list.py
reverse ¶
Reverse the list in place.
Walks the list once, re-pointing each node's next at the node before
it. Three references track progress: the previous node, the current
node, and the next node (saved before its link is overwritten). When
the walk ends, the old tail is the new head and the old head is the new
tail. No nodes are allocated or copied.
Complexity
- Time: O(n)
- Space: O(1)
Examples:
>>> a = SinglyLinkedList[int]([1, 2, 3])
>>> a.reverse()
>>> a
SinglyLinkedList([3, 2, 1])
>>> a.append(0) # the tail reference was updated too
>>> a
SinglyLinkedList([3, 2, 1, 0])
- Data Structures Singly Linked List Reversing