05Module · Goodrich Ch. 5
Week 5 — Array-Based Sequences
Low-level and referential arrays, dynamic arrays, amortized analysis, and multidimensional data.
Array-Based Sequences
Python's list/tuple/str internals, dynamic resizing, amortized cost of append, and multidimensional structures.
Theory
Python lists are referential arrays — slots hold references, not raw values — giving O(1) random access.
A dynamic array doubles its capacity when full. Although a single append may cost O(n), the amortized cost is O(1).
Multidimensional data should be allocated carefully — [[0]*n]*n creates n references to the same row.
Key points
- list.append is amortized O(1); list.insert(0, x) is O(n).
- Tuples are immutable and use less memory than lists.
- The 'accounting method' charges each append for its share of future resizing.
Code examples
Dynamic array from scratch
Dynamic array from scratch
import ctypes
class DynamicArray:
def __init__(self):
self._n = 0
self._capacity = 1
self._A = (self._capacity * ctypes.py_object)()
def __len__(self): return self._n
def append(self, obj):
if self._n == self._capacity:
self._resize(2 * self._capacity)
self._A[self._n] = obj
self._n += 1
def _resize(self, c):
B = (c * ctypes.py_object)()
for k in range(self._n):
B[k] = self._A[k]
self._A = B
self._capacity = cSafe 2-D matrix initialization
Safe 2-D matrix initialization
# WRONG — all rows are aliased
bad = [[0] * 3] * 3
bad[0][0] = 9
print(bad) # [[9, 0, 0], [9, 0, 0], [9, 0, 0]]
# RIGHT — independent rows
good = [[0] * 3 for _ in range(3)]
good[0][0] = 9
print(good) # [[9, 0, 0], [0, 0, 0], [0, 0, 0]]