cs_survival_kit.data_structures.dynamic_array ¶
A dynamic array with pluggable growth policies.
Provides DynamicArray, a resizable array backed by fixed-capacity storage,
and a set of growth policies that decide how much capacity to add each time
the array resizes. The growth policy determines the amortized cost of
DynamicArray.append: geometric policies give amortized O(1) appends, while
additive policies give amortized O(n) appends.
GrowthPolicy ¶
Maps the current capacity to the new capacity after an array resize.
A valid policy must return a value strictly greater than its input.
DynamicArray.append raises ValueError if a policy does not.
DynamicArray ¶
Bases: AbstractList[T]
A resizable array backed by fixed-capacity storage.
Elements are stored in a fixed-size backing list of capacity slots,
where only the first len(self) slots are in use. When an append finds
no free slot, the array first resizes: it allocates a larger backing list,
sized by the growth policy, and copies every element into it. The backing
storage never shrinks, so popping elements leaves capacity unchanged.
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 |
|---|---|---|
append |
O(1) amortized, O(n) worst | O(1) amortized, O(n) worst |
pop |
O(1) | O(1) |
a[i], a[i] = x |
O(1) | O(1) |
len(a) |
O(1) | O(1) |
item in a |
O(n) | O(1) |
| iteration | O(n) | O(1) |
| resize | O(n) | O(n) |
The append bounds assume a geometric growth policy such as the
default doubling. With an additive policy, append is amortized
O(n). Total storage is O(capacity). For an array built by appends
alone, doubling keeps capacity below 2n once the array has grown past
its initial capacity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
capacity
|
int
|
The number of slots to allocate up front. Must be at least 1. |
4
|
growth
|
GrowthPolicy
|
The growth policy that computes the new capacity on each
resize. Must return a value greater than its input. Defaults to
|
doubling
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Examples:
>>> a = DynamicArray[int](capacity=2)
>>> a.append(1)
>>> a.append(2)
>>> len(a), a.capacity
(2, 2)
>>> a.append(3) # no free slot, so the array doubles first
>>> len(a), a.capacity
(3, 4)
>>> a
DynamicArray([1, 2, 3])
>>> a[0] = 10
>>> a.pop()
3
>>> list(a)
[10, 2]
- Data Structures Dynamic Array
Source code in lib/cs_survival_kit/data_structures/dynamic_array.py
capacity
property
¶
The number of allocated slots, used or not.
Always at least len(self). The two are equal when the array is full,
and the next append will trigger a resize.
Complexity
- Time: O(1)
- Space: O(1)
__len__ ¶
Return the number of elements in the array.
Returns:
| Type | Description |
|---|---|
int
|
The number of elements in the array. |
Complexity
- Time: O(1)
- Space: O(1)
__getitem__ ¶
Return the element at index.
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(1)
- Space: O(1)
Source code in lib/cs_survival_kit/data_structures/dynamic_array.py
__setitem__ ¶
Replace the element at index with item.
Only overwrites an existing element. Use append to add one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index
|
int
|
The position of the element to replace. Must satisfy
|
required |
item
|
T
|
The new element. |
required |
Raises:
| Type | Description |
|---|---|
IndexError
|
If |
Complexity
- Time: O(1)
- Space: O(1)
Source code in lib/cs_survival_kit/data_structures/dynamic_array.py
__iter__ ¶
Iterate over the elements from index 0 to len(self) - 1.
Yields:
| Type | Description |
|---|---|
T
|
Each element, in index order. |
Complexity
- Time: O(n) to exhaust the iterator
- Space: O(1)
Source code in lib/cs_survival_kit/data_structures/dynamic_array.py
__contains__ ¶
Return whether item is in the array.
Checks the elements in index order and stops at the first match. An
element matches if it is item or equals it, the same rule that
list uses. Unused slots are never examined, so None in a is
True only if None was actually stored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item
|
object
|
The value to look for. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Complexity
- Time: O(n), since the elements are not ordered and each one may have to be checked; O(1) if the first element matches
- Space: O(1)
Examples:
Source code in lib/cs_survival_kit/data_structures/dynamic_array.py
__repr__ ¶
Return a string showing the class name and the elements, like list.
Unused slots and the capacity are not shown. Use capacity to inspect
the backing storage.
Returns:
| Type | Description |
|---|---|
str
|
A string such as |
Source code in lib/cs_survival_kit/data_structures/dynamic_array.py
append ¶
Add item to the end of the array.
If the array is full, it first resizes to the capacity returned by the growth policy, copying every element, and then stores the item in the first free slot. Resizing only when there is no room means every allocated slot gets used before the array grows.
The growth policy's result is checked before anything changes. If it
is not greater than the current capacity, ValueError is raised and
the array is left exactly as it was.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item
|
T
|
The element to add. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the array is full and the growth policy returns a capacity that is not greater than the current capacity. |
Complexity
- Time: O(1) amortized with a geometric growth policy; O(n) for the append that triggers a resize
- Space: O(1) amortized; O(n) for the append that triggers a resize
Examples:
>>> a = DynamicArray[str](capacity=2)
>>> a.append("x")
>>> a.append("y") # fills the last free slot; no resize yet
>>> a.capacity
2
>>> a.append("z") # no free slot, so the array grows first
>>> a.capacity
4
A growth policy that doesn't grow is rejected:
>>> stuck = DynamicArray[int](capacity=1, growth=lambda c: c)
>>> stuck.append(1)
>>> stuck.append(2)
Traceback (most recent call last):
...
ValueError: growth policy must increase capacity (1 -> 1)
>>> list(stuck), stuck.capacity
([1], 1)
Source code in lib/cs_survival_kit/data_structures/dynamic_array.py
pop ¶
Remove and return the last element.
The freed slot is cleared, so the array no longer holds a reference to the element. Capacity is unchanged.
Returns:
| Type | Description |
|---|---|
T
|
The element that was at index |
Raises:
| Type | Description |
|---|---|
IndexError
|
If the array is empty. |
Complexity
- Time: O(1)
- Space: O(1)
Examples:
>>> a = DynamicArray[int]()
>>> a.append(1)
>>> a.pop()
1
>>> a.pop()
Traceback (most recent call last):
...
IndexError: pop from empty array
Source code in lib/cs_survival_kit/data_structures/dynamic_array.py
doubling ¶
Double the capacity on each resize.
The default growth policy for DynamicArray. Equivalent to
geometric(2.0).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
curr_capacity
|
int
|
The current capacity of the array. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Twice the current capacity. |
Examples:
- Data Structures Dynamic Array Growth policies
- Reference (cs-survival-kit 0.6.0) cs_survival_kit data_structures
Source code in lib/cs_survival_kit/data_structures/dynamic_array.py
geometric ¶
Build a growth policy that multiplies the capacity by a constant factor.
Any factor greater than 1 gives amortized O(1) appends. The factor trades
memory for copying: a resize copies every element, so a larger factor means
fewer resizes, but right after a resize the capacity is about factor times
the number of elements. CPython's list over-allocates by roughly ⅛,
choosing low memory overhead over fewer resizes.
Because the new capacity is truncated to an integer, a small factor applied to a small capacity could round back down to the current capacity. The returned policy always grows the capacity by at least 1 to prevent that.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factor
|
float
|
The multiplier applied to the current capacity. Must be finite and greater than 1. |
required |
Returns:
| Type | Description |
|---|---|
GrowthPolicy
|
A growth policy that returns |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Examples:
- Data Structures Dynamic Array Growth policies
Source code in lib/cs_survival_kit/data_structures/dynamic_array.py
additive ¶
Build a growth policy that adds a fixed number of slots on each resize.
This policy is a counterexample to geometric growth. A resize happens
every step appends and copies every element, so n appends perform about
n² / (2 · step) copies in total. That is amortized O(n) per append, and
O(n²) to build an array of n elements. In exchange, a resize never leaves
more than step unused slots.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
step
|
int
|
The number of slots to add on each resize. Must be at least 1. |
required |
Returns:
| Type | Description |
|---|---|
GrowthPolicy
|
A growth policy that returns |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Examples:
- Data Structures Dynamic Array Growth policies