cs_survival_kit.data_structures.doubly_linked_list ¶
A generic doubly linked list implementation.
A doubly linked list stores each element in a node containing references to both the previous and next nodes. The backward link permits traversal in both directions and makes operations such as removing the tail O(1) when a tail reference is maintained. It also allows indexed traversal to begin at whichever end of the list is closer to the requested index.
These capabilities come at the cost of an additional reference per node and additional pointer updates when inserting or removing nodes compared with a singly linked list.
DoublyLinkedList ¶
Bases: AbstractList[T]
A generic sequence implemented as a doubly linked list.
Elements are stored in nodes connected by prev and next references.
The list maintains references to both the head and tail nodes as well as
its current size. This permits O(1) insertion and removal at either end
and O(1) length queries.
Indexed access requires traversal because nodes are not stored
contiguously. Traversal begins at the head or tail depending on which is
closer to the requested index, requiring
O(min(i, n - 1 - i)) time for index i and O(n) time in the worst case.
Compared with a singly linked list, the backward reference enables direct traversal toward the head and O(1) removal from the tail. The tradeoff is an additional reference per node and additional pointer maintenance. Compared with a dynamic array, this structure provides O(1) insertion and removal at either end without shifting elements, but does not provide O(1) random access and has greater per-element storage overhead.
Complexity
| Operation | Time | Space |
|---|---|---|
a[i], a[i] = x |
O(min(i, n - 1 - i)), O(n) worst | O(1) |
insert(i, x) |
O(min(i, n - i)), O(n) worst | O(1) |
pop(i) |
O(min(i, n - 1 - i)), O(n) worst | O(1) |
prepend |
O(1) | O(1) |
append |
O(1) | O(1) |
pop_front |
O(1) | O(1) |
pop_back |
O(1) | O(1) |
remove |
O(n) | O(1) |
reverse |
O(n) | O(1) |
len(a) |
O(1) | O(1) |
item in a |
O(n) | O(1) |
| iteration | O(n) | O(1) |
| reversed iteration | O(n) | O(1) |
The list requires O(n) total storage. Each element is stored in a separate node containing the element and two node references.
The space bounds above describe auxiliary space used by each operation, excluding storage for newly inserted nodes and iterator objects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
items
|
Iterable[T]
|
Elements used to initialize the list, in iteration order. |
()
|
Examples:
>>> values = DoublyLinkedList([1, 2, 3])
>>> list(values)
[1, 2, 3]
>>> list(reversed(values))
[3, 2, 1]
>>> values.insert(1, 4)
>>> list(values)
[1, 4, 2, 3]
- Data Structures Doubly Linked List
Source code in cs_survival_kit/data_structures/doubly_linked_list.py
·
View on GitHub
__len__ ¶
Return the number of elements in the list.
Returns:
| Type | Description |
|---|---|
int
|
The number of elements currently stored. |
Complexity
- Time: O(1)
- Space: O(1)
Source code in cs_survival_kit/data_structures/doubly_linked_list.py
·
View on GitHub
__iter__ ¶
Iterate over the elements from head to tail.
Yields:
| Type | Description |
|---|---|
T
|
Each element in list order. |
Complexity
- Time: O(n) for complete iteration
- Space: O(1) auxiliary space
Source code in cs_survival_kit/data_structures/doubly_linked_list.py
·
View on GitHub
__reversed__ ¶
Iterate over the elements from tail to head.
Each node stores a reference to its predecessor, allowing traversal backward from the tail without first reversing the list or repeatedly searching from the head. A singly linked list does not have these backward references.
Yields:
| Type | Description |
|---|---|
T
|
Each element in reverse list order. |
Complexity
- Time: O(n) for complete iteration
- Space: O(1) auxiliary space
Examples:
Source code in cs_survival_kit/data_structures/doubly_linked_list.py
·
View on GitHub
__getitem__ ¶
Return the element at the given index.
Traversal begins at whichever end of the list is closer to index.
This reduces the number of nodes visited for positions near the tail,
although indexed access remains O(n) in the worst case.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index
|
int
|
Zero-based index of the element to retrieve. |
required |
Returns:
| Type | Description |
|---|---|
T
|
The element stored at |
Raises:
| Type | Description |
|---|---|
IndexError
|
If |
Complexity
- Time: O(min(index, n - 1 - index)); O(n) worst case
- Space: O(1)
Source code in cs_survival_kit/data_structures/doubly_linked_list.py
·
View on GitHub
__setitem__ ¶
Replace the element at the given index.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index
|
int
|
Zero-based index of the element to replace. |
required |
item
|
T
|
New element to store at |
required |
Raises:
| Type | Description |
|---|---|
IndexError
|
If |
Complexity
- Time: O(min(index, n - 1 - index)); O(n) worst case
- Space: O(1)
Source code in cs_survival_kit/data_structures/doubly_linked_list.py
·
View on GitHub
insert ¶
Insert an element at the given index.
Insertion at the head or one position past the tail requires no
traversal and runs in O(1) time. For an interior insertion, the node
currently at index is located by traversing from the nearer end.
Its prev reference identifies the predecessor, after which the four
links surrounding the new node are updated in O(1) time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index
|
int
|
Zero-based position at which to insert the element. An index equal to the current size appends the element. |
required |
item
|
T
|
Element to insert. |
required |
Raises:
| Type | Description |
|---|---|
IndexError
|
If |
Complexity
- Time: O(min(index, n - index)); O(n) worst case
- Space: O(1) auxiliary space
Examples:
- Data Structures Doubly Linked List Walking from the nearer end
Source code in cs_survival_kit/data_structures/doubly_linked_list.py
·
View on GitHub
pop ¶
Remove and return the element at the given index.
Removing the head or tail requires only pointer updates and therefore
runs in O(1) time. In particular, the tail's prev reference gives
direct access to the new tail, whereas a singly linked list must
traverse from the head to locate the tail's predecessor.
Removing an interior element first locates its node by traversing from
the nearer end. The node's prev and next references then provide
direct access to both neighbors so it can be unlinked in O(1) time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index
|
int
|
Zero-based index of the element to remove. |
required |
Returns:
| Type | Description |
|---|---|
T
|
The element removed from the list. |
Raises:
| Type | Description |
|---|---|
IndexError
|
If |
Complexity
- Time: O(min(index, n - 1 - index)); O(n) worst case
- Space: O(1)
Examples:
- Data Structures Doubly Linked List Walking from the nearer end
Source code in cs_survival_kit/data_structures/doubly_linked_list.py
·
View on GitHub
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | |
reverse ¶
Reverse the list in place.
Each node's prev and next references are swapped. After a node's
links are swapped, its former next node is reachable through prev,
which allows traversal to continue through the original list order.
Once every node has been updated, the head and tail references are
swapped to complete the reversal.
Complexity
- Time: O(n)
- Space: O(1)
Examples:
- Data Structures Doubly Linked List Reversing