Atlasingeniería

Algoritmos y programaciónManejo de datosTema 1

Arreglos, listas y matrices

Estas estructuras organizan secuencias y tablas con costos diferentes. La representación elegida decide acceso, inserción, memoria y forma de recorrer los datos.

Para este tema conviene tener claro:Variables, tipos y expresiones

Guardar varios valores no resuelve cómo accederlos. Un arreglo privilegia posiciones, una lista enlazada privilegia cambios locales y una matriz agrega dos dimensiones lógicas sobre una representación concreta.

El arreglo: posiciones consecutivas

Un arreglo asocia índices consecutivos con elementos. Acceder a una posición cuesta O(1)O(1); recorrer todas cuesta O(n)O(n). En un arreglo dinámico, agregar al final suele ser O(1)O(1) amortizado gracias a reservas de capacidad mayores que el tamaño actual.

Insertar o borrar en el medio puede desplazar el sufijo y cuesta O(n)O(n). La operación visible es pequeña, pero preservar índices obliga a mover datos.

Queremos insertar el 5 en la posición 1. Hay que hacerle lugar.

1 / 5
El elemento nuevo es uno solo; lo que cuesta es correr todo lo que venía después para que cada valor siga estando en el índice que le toca.

Antes de seguir, predecí

Tenés un arreglo de un millón de elementos y hay que insertar uno al principio. ¿Cuánto cuesta?

La lista enlazada: cambios locales baratos

Una lista enlazada conecta nodos mediante referencias. Insertar después de un nodo conocido cuesta O(1)O(1), pero llegar a la posición kk cuesta O(k)O(k). También agrega enlaces por nodo y peor localidad de memoria.

No hay una estructura universalmente superior. Si predominan acceso por índice y recorridos, el arreglo suele ganar; si predominan ediciones sobre nodos ya localizados, una lista puede evitar desplazamientos.

Dos dimensiones sobre una memoria lineal

Una matriz de ff filas y cc columnas puede almacenarse como filas separadas o como un arreglo plano. En orden por filas, la posición (i,j)(i,j) corresponde a:

indice(i,j)=ic+j.indice(i,j)=i\cdot c+j.

Recorrer en el mismo orden que el almacenamiento mejora localidad. Intercambiar los ciclos puede mantener O(fc)O(fc) y aun así rendir peor por saltar entre regiones distantes.

Escena 1 — Por qué agregar al final sale barato

paso a paso

Cargando la escena…

Subí las inserciones y mirá el contador de copias: crece a saltos y cada salto está más lejos del anterior. Nueve inserciones cuestan ocho copias, y ese total dividido por las inserciones es la constante que se esconde detrás de «amortizado».

Los casos de borde que revelan supuestos

Los índices válidos van de cero a longitud menos uno. Arreglos vacíos, una sola fila y matrices no cuadradas revelan supuestos escondidos. Una “matriz” con filas de distinta longitud necesita otro contrato: es una colección irregular, no una tabla rectangular.

Antes de acceder, definí quién valida dimensiones y qué ocurre si no coinciden. Esa decisión pertenece a la interfaz, no debería repetirse de manera distinta en cada ciclo.

Las operaciones que cuestan distinto

const values = [10, 20, 30, 40, 50];

values[2];              // O(1): la posición se calcula, no se busca
values.push(60);        // O(1) amortizado: agregar al final
values.pop();           // O(1)
values.unshift(5);      // O(n): corre todo una posición a la derecha
values.shift();         // O(n): corre todo a la izquierda
values.splice(2, 1);    // O(n): borrar del medio también desplaza
values.indexOf(40);     // O(n): recorre hasta encontrarlo
values.includes(40);    // O(n), lo mismo con otro nombre

// Una matriz es un arreglo de arreglos, y las filas pueden compartirse sin querer
const wrong = new Array(3).fill(new Array(3).fill(0)); // ¡las tres filas son el mismo arreglo!
wrong[0]![0] = 9;       // cambia las tres

const right = Array.from({ length: 3 }, () => new Array(3).fill(0)); // una fila nueva por vez

La última parte es el error de matrices más común y no da ningún aviso: fill con un objeto guarda la misma referencia en todas las posiciones, así que la matriz tiene una sola fila repetida tres veces. Se ve bien al imprimirla y falla al escribir.

Cuándo un arreglo no es la estructura

Lo que necesitásEstructuraPor qué no un arreglo
Buscar por una claveMapindexOf es O(n) en cada consulta
Saber si algo ya estáSetincludes recorre; has no
Agregar y sacar del principiolista enlazada o colashift y unshift son O(n)
Mantener el orden por prioridadheapreordenar en cada inserción es O(n log n)
Valores únicosSetgarantizarlo a mano se olvida siempre
La primera fila es la que más aparece y la que más cuesta: un arreglo de objetos que se busca por id en cada iteración es el patrón cuadrático más frecuente en código real.

Cierre

Arreglos, listas y matrices expresan formas de acceso. Compará operación dominante, costo de recorrido, crecimiento y representación física. Elegir bien no depende del nombre del dato, sino de cómo el programa lo consulta y modifica.

Autoevaluación

¿Lo entendiste?

Insertar en el medio de un arreglo cuesta O(n). ¿Por qué, si sólo se agrega un elemento?
Una matriz guardada por filas, con índice(i, j) = i·c + j. ¿Qué pasa si se intercambian los ciclos del recorrido?
¿Cuándo conviene una lista enlazada por sobre un arreglo?
Una «matriz» cuyas filas tienen distinta longitud…