Las estructuras de datos determinan la eficiencia de las operaciones básicas. A continuación resumimos complejidad temporal (y cuando aplica, espacial) en escenarios típicos al trabajar con Python.
O(1) por índice.O(1) amortizado; O(n) si requiere crecer la capacidad.O(n) por corrimiento de elementos.O(n) por corrimiento; al final es O(1).def insertar(valores, pos, valor):
valores.insert(pos, valor) # corrimiento interno
O(n); hay que recorrer nodo a nodo.O(1) usando la cabeza.O(1); localizar el nodo es lo costoso.O(n) pero con sobrecosto por punteros.class Nodo:
def __init__(self, valor, siguiente=None):
self.valor = valor
self.siguiente = siguiente
def push_front(head, valor):
return Nodo(valor, head)
Pila (stack LIFO):
push/pop son O(1).O(n) puntual, pero amortizado O(1) si se duplica capacidad.Cola (FIFO):
enqueue/dequeue en O(1).O(1) si se mantiene puntero a cabeza y cola.h = O(log n), degenerado h = O(n).O(n) ya que visita cada nodo una vez.O(h), depende de la altura real.O(log n) para insertar, buscar y eliminar.O(n).O(1) por operación, por eso el orden amortizado se conserva.O(1) si la función hash distribuye bien y la tabla se redimensiona.O(n) si todas las claves colisionan; se mitiga con buena función hash y resize.O(n), pero ocurre cada varios inserts → amortizado O(1).def hash_simple(clave, mod):
h = 5381
for ch in clave:
h = ((h << 5) + h) + ord(ch)
return h % mod
O(log n) por subir el elemento.O(log n) por bajar el elemento.O(1) porque está en la raíz.O(n) usando heapify de abajo hacia arriba.def sift_up(valores, idx):
while idx > 0:
padre = (idx - 1) // 2
if valores[padre] <= valores[idx]:
break
valores[padre], valores[idx] = valores[idx], valores[padre]
idx = padre