La complejidad espacial describe cuánta memoria adicional usa un algoritmo respecto del tamaño de la entrada n. En C el control de memoria es manual, por lo que entender cómo crecen las estructuras es clave para evitar fugas y sobrecostos.
k elementos de sizeof(T) ocupa O(k) bytes.malloc suele ser O(1) amortizado, aunque depende del asignador.calloc agrega costo lineal por poner ceros.int *buffer = malloc(sizeof(int) * n);
if (!buffer) {
perror("malloc");
return 1;
}
Cada nodo en una lista, árbol o grafo aporta una unidad de memoria adicional. Liberar de forma simétrica es esencial.
typedef struct Nodo {
int valor;
struct Nodo *sig;
} Nodo;
Nodo *crear_nodo(int valor) {
Nodo *n = malloc(sizeof(Nodo));
if (!n) return NULL;
n->valor = valor;
n->sig = NULL;
return n;
}
void destruir_lista(Nodo *head) {
while (head) {
Nodo *tmp = head->sig;
free(head);
head = tmp;
}
}
El uso de memoria es O(n) en cantidad de nodos. El recorrido de destrucción también es O(n) en tiempo.
O(n) pero sin redimensionar.int estatico[1024]; // en stack, tamaño fijo
int *dinamico = malloc(n * sizeof(int)); // en heap, depende de n
O(mn) celdas; en enteros de 4 bytes, 1000x1000 → ~4 MB.O(V + E).O(V^2); solo conviene en grafos densos.// Matriz dinamica simple fila contigua
int **crear_matriz(int filas, int cols) {
int *datos = malloc(sizeof(int) * filas * cols);
int **m = malloc(sizeof(int*) * filas);
for (int i = 0; i < filas; i++) {
m[i] = datos + i * cols;
}
return m;
}
destroy simétricas, revisar errores tempranos.char *linea = malloc(256);
if (!linea) return -1;
if (leer(linea) != 0) {
free(linea); // evitar fuga en rutas de error
return -1;
}
procesar(linea);
free(linea);
valgrind --leak-check=full ./programa reporta fugas y usos incorrectos; agrega sobrecosto pero es exhaustivo.-g) y compilar sin optimizaciones agresivas al analizar.