3.01 · Arreglos Unidimensionales (Vectores)
🎯 Objetivo de aprendizaje
Al terminar este tema vas a poder:
- Explicar qué es un arreglo 1D y por qué es la estructura de datos más usada en programación.
- Declarar arreglos en C++: int nums[10];, int nums[] = {1, 2, 3};, const int MAX = 5;.
- Acceder a elementos individuales con el operador [] y entender el sistema de índices 0-based.
- Recorrer arreglos con for para leer, escribir, buscar y procesar.
- Visualizar cómo se almacenan los arreglos en la memoria RAM (contigua, indexada).
- Implementar los algoritmos clásicos: búsqueda lineal, suma, mayor/menor, inversión.
- Validar los índices antes de acceder (evitar acceso fuera de rango).
- Trabajar con arreglos de cualquier tipo de dato: int, double, char, string.
Los arreglos son la base del 90% de los algoritmos. Sin ellos, no podrías procesar una lista de alumnos, una hoja de cálculo, ni un catálogo de productos. Dominar los arreglos es dominar la base de la programación.
🧠 Teoría y conceptos — 3.1.1 — El problema: ¿qué pasa con muchas variables?

El límite de las variables sueltas
Hasta ahora, cada dato que querías guardar necesitaba su propia variable:
int nota1, nota2, nota3, nota4, nota5; // 5 calificaciones
Pero, ¿qué pasa con 30 calificaciones? ¿100? ¿1 millón? Escribir 1 millón de variables es imposible.
La solución: el arreglo
Un arreglo (o vector en C++ moderno) es una colección de variables del mismo tipo, almacenadas en posiciones contiguas de memoria, accesibles por un índice numérico.
Analogía: la caja de casilleros de un gimnasio. Todos los casilleros son iguales (mismo tamaño, misma forma), están numerados del 0 al N-1, y puedes meter/retirar cosas de cualquiera de ellos por su número.
Figura: Analogía: variable vs arreglo
Una variable es como un casillero individual; un arreglo es una fila entera de casilleros numerados.
Figura: Analogía: arreglo de 6 casilleros
Un arreglo de 6 elementos. Cada casillero tiene un número (índice) y guarda un valor del mismo tipo.
la diferencia entre una variable suelta y un arreglo. Da 3 ejemplos de la vida real donde necesitarías un arreglo (no variables sueltas).
3.1.2 — ¿Qué es un arreglo? La caja de casilleros

Definición formal
Un arreglo es una estructura de datos que almacena una colección de elementos del mismo tipo en posiciones contiguas de memoria, identificadas por un índice numérico (0, 1, 2, ..., N-1).
Por qué importa el orden 0-based
En C++ (y Java, C, Python, JavaScript), el primer elemento es el índice 0, no el 1. Esto es por convención: nums[0] es el primero.
¿Por qué? Por la forma en que la memoria direcciona: el primer elemento está en la dirección base, el segundo en base+1*sizeof(tipo), etc. Empezar en 0 simplifica el cálculo.
¿por qué los índices empiezan en 0 en la mayoría de lenguajes? Investiga y escribe tu respuesta.
3.1.3 — Declaración, inicialización y acceso por índice

Las 3 formas de declarar
Forma 1: declarar sin inicializar (valores basura):
int notas[5]; // 5 enteros, valores indefinidos (basura de memoria)
Forma 2: declarar e inicializar con valores:
int notas[5] = {85, 90, 78, 92, 88}; // 5 enteros, valores específicos
Forma 3: declarar sin tamaño específico (lo deduce el compilador):
int notas[] = {85, 90, 78, 92, 88}; // 5 elementos (lo deduce)
Forma 4: con constante simbólica (mejor práctica):
const int MAX_ALUMNOS = 30;
int notas[MAX_ALUMNOS]; // Usa la constante
Visualización del arreglo declarado
Figura: Declaración de un arreglo
Arreglo `int nums[5] = {10, 20, 30, 40, 50}` con 5 celdas, cada una accesible por su índice.
Acceso por índice
int nums[5] = {10, 20, 30, 40, 50};
cout << nums[0]; // Imprime 10 (primer elemento)
cout << nums[2]; // Imprime 30 (tercer elemento)
cout << nums[4]; // Imprime 50 (último elemento)
nums[0] = 100; // Cambia el primer elemento a 100
Figura: Acceso por índice
Acceso por índice: `nums[0]` da el primer elemento, `nums[4]` el último.
Reglas de oro
- El primer índice es 0, no 1.
- El último índice es N-1 (tamaño menos 1).
- Acceder fuera de rango (nums[5] en un arreglo de 5) es comportamiento indefinido (puede crashear o dar basura).
Errores comunes
int nums[5] = {10, 20, 30, 40, 50};
// ❌ MAL: empieza en 1 (índice fuera de rango)
cout << nums[1]; // Imprime 20, no 10
// Si el usuario esperaba "el primer elemento", se confunde
// ❌ MAL: índice fuera de rango
cout << nums[5]; // Comportamiento indefinido (basura o crash)
// ❌ MAL: confundir el índice con el valor
int i = 3;
cout << nums[i]; // ✅ Esto SÍ es correcto: imprime 40
// Confundir el 3 con "el tercer elemento" es un error de comprensión
las 3 reglas de oro (índice 0, último = N-1, sin acceso fuera de rango) y los 3 errores comunes. Memorízalos.
3.1.4 — Cómo se almacenan los arreglos en memoria

La memoria RAM como una fila de casilleros
La memoria RAM se puede imaginar como una secuencia enorme de casilleros numerados, cada uno con una dirección única. Un byte = un casillero. Cada casillero tiene una dirección (por ejemplo, 0x7FFE0001).
Cuando declaras int nums[5] = {10, 20, 30, 40, 50};, el sistema operativo reserva 5 casilleros contiguos en la RAM (5 × 4 bytes = 20 bytes, porque un int ocupa 4 bytes).
Diagrama de los segmentos de memoria
Figura: Segmentos de memoria
Segmentos típicos de un programa en C++. El arreglo `nums[5]` se almacena en el stack (junto con las variables locales), en posiciones contiguas de memoria.
La fórmula de direccionamiento
Si nums empieza en la dirección 0x1000 y cada int ocupa 4 bytes:
Fórmula: dirección_de_nums[i] = dirección_base + i * sizeof(tipo)
Por qué importa
- Acceso O(1): acceder a nums[i] toma el mismo tiempo sin importar i. El hardware calcula la dirección con la fórmula y la lee. No tiene que recorrer desde el principio.
- Localidad de caché: como los elementos están contiguos, cuando accedes a nums[0] el CPU trae también nums[1], nums[2], etc. a la caché, así que los accesos siguientes son más rápidos.
- Acceso fuera de rango = peligro: si intentas acceder a nums[10] en un arreglo de 5, el sistema no sabe que es tu error; lee 20 bytes más allá de tu arreglo, que pueden ser datos de otra variable. Comportamiento indefinido.
los 4 puntos clave sobre la memoria de los arreglos: contigüidad, acceso O(1), localidad de caché, peligro de fuera de rango.
3.1.5 — Recorrido con for: leer, escribir, procesar

El patrón fundamental
El 90% de las operaciones con arreglos se hacen con un for que recorre índice por índice:
const int N = 5;
int nums[N] = {10, 20, 30, 40, 50};
// RECORRIDO: pasar por todos los elementos uno por uno
for (int i = 0; i < N; i++) { // i va de 0 a N-1
cout << nums[i] << " ";
}
// Imprime: 10 20 30 40 50
Figura: Recorrido del arreglo
El bucle `for` recorre el arreglo índice por índice. `i` es el "dedo" que va señalando cada celda.
Las 4 operaciones básicas con for
- Leer (imprimir):
for (int i = 0; i < N; i++) {
cout << "nums[" << i << "] = " << nums[i] << endl;
}
- Escribir (llenar desde el usuario):
for (int i = 0; i < N; i++) {
cout << "Ingresa el valor " << (i+1) << ": ";
cin >> nums[i];
}
- Procesar (calcular suma):
int suma = 0;
for (int i = 0; i < N; i++) {
suma += nums[i];
}
cout << "Suma: " << suma << endl;
- Buscar:
int objetivo = 30;
int posicion = -1;
for (int i = 0; i < N; i++) {
if (nums[i] == objetivo) {
posicion = i;
break; // Salir al encontrar
}
}
if (posicion != -1) {
cout << "Encontrado en posición " << posicion << endl;
} else {
cout << "No encontrado" << endl;
}
el patrón fundamental `for (int i = 0; i < N; i++)`. Memorízalo: lo vas a usar 1000 veces.
3.1.6 — Validación de índices (evitar bugs comunes)

El error #1: acceso fuera de rango
const int N = 5;
int nums[N] = {10, 20, 30, 40, 50};
// ❌ PELIGROSO: accede a memoria fuera del arreglo
cout << nums[5]; // Índice 5 no existe (último válido es 4)
cout << nums[100]; // Muy fuera, comportamiento impredecible
¿Por qué es peligroso? El programa no avisa. Lee lo que esté en esa posición de memoria (basura, otra variable, etc.). Puede crashear o dar resultados incorrectos silenciosamente.
La regla: validar SIEMPRE
// ✅ BIEN: validar antes de acceder
int i;
cout << "Índice: "; cin >> i;
if (i >= 0 && i < N) {
cout << "Valor: " << nums[i] << endl;
} else {
cout << "Índice fuera de rango" << endl;
}
En bucles: usar < N o <= N-1
// ✅ BIEN: < N evita el off-by-one
for (int i = 0; i < N; i++) { // i: 0, 1, 2, 3, 4
cout << nums[i];
}
// ❌ MAL: <= N causa acceso fuera de rango
for (int i = 0; i <= N; i++) { // i: 0, 1, 2, 3, 4, 5 (¡fuera!)
cout << nums[i];
}
la regla `< N` (NO `<= N`). Memorízala: previene el 90% de los bugs de acceso a arreglos.
3.1.7 — Algoritmos clásicos con arreglos
Algoritmo 1: Suma y promedio
const int N = 5;
int nums[N] = {85, 90, 78, 92, 88};
int suma = 0;
for (int i = 0; i < N; i++) {
suma += nums[i];
}
double promedio = (double)suma / N;
cout << "Suma: " << suma << endl;
cout << "Promedio: " << promedio << endl;
Algoritmo 2: Mayor y menor (con inicialización correcta)
const int N = 5;
int nums[N] = {85, 90, 78, 92, 88};
// Inicializar con el PRIMER elemento (no con 0)
int mayor = nums[0];
int menor = nums[0];
for (int i = 1; i < N; i++) {
if (nums[i] > mayor) mayor = nums[i];
if (nums[i] < menor) menor = nums[i];
}
cout << "Mayor: " << mayor << endl;
cout << "Menor: " << menor << endl;
Algoritmo 3: Búsqueda lineal
Figura: Búsqueda lineal
Búsqueda lineal: recorremos uno por uno hasta encontrar el valor. Aquí, el 15 está en la posición 3.
const int N = 7;
int nums[N] = {5, 12, 8, 23, 17, 9, 30};
int objetivo = 23;
int posicion = -1;
for (int i = 0; i < N; i++) {
if (nums[i] == objetivo) {
posicion = i;
break;
}
}
if (posicion != -1) {
cout << "Encontrado en posición " << posicion << endl;
} else {
cout << "No encontrado" << endl;
}
Algoritmo 4: Inversión del arreglo
const int N = 5;
int nums[N] = {1, 2, 3, 4, 5};
// Intercambiar nums[i] con nums[N-1-i] hasta la mitad
for (int i = 0; i < N / 2; i++) {
int temp = nums[i];
nums[i] = nums[N - 1 - i];
nums[N - 1 - i] = temp;
}
// nums ahora es {5, 4, 3, 2, 1}
Algoritmo 5: Encontrar duplicados
const int N = 7;
int nums[N] = {5, 12, 8, 23, 12, 9, 5};
bool hayDuplicados = false;
for (int i = 0; i < N - 1; i++) {
for (int j = i + 1; j < N; j++) {
if (nums[i] == nums[j]) {
cout << "Duplicado encontrado: " << nums[i] << endl;
hayDuplicados = true;
}
}
}
if (!hayDuplicados) {
cout << "No hay duplicados" << endl;
}
los 5 algoritmos clásicos (suma, mayor/menor, búsqueda, inversión, duplicados) con tu implementación. Memorízalos.
⚠️ Errores típicos — ❌ Errores típicos del razonamiento
Error 1: "El primer elemento es nums[1]"
Idea equivocada: en algunos lenguajes (MATLAB, Lua, R) los arreglos empiezan en 1, así que en C++ también.
Realidad: en C++, Java, C#, Python, JavaScript, el primer elemento es [0]. Acostumbrarse a esto desde el principio.
Cómo evitarlo: siempre escribe arr[0] para el primero, arr[N-1] para el último.
Error 2: "El for debe ir de 1 a N"
Idea equivocada: "es más natural contar desde 1".
Realidad: en C++ (y la mayoría de lenguajes), los arreglos van de 0 a N-1. Un for (int i = 1; i <= N; i++) salta el primer elemento y accede fuera de rango al final.
Cómo evitarlo: siempre for (int i = 0; i < N; i++).
Error 3: "Si el programa no crashea, no hay error"
Idea equivocada: "accedí a nums[10] en un arreglo de 5 y no crasheó, así que está bien".
Realidad: comportamiento indefinido significa que el programa PUEDE crashear, PUEDE dar basura, o PUEDE parecer que funciona. No significa que esté bien. En otro sistema operativo, con otro compilador, en otro momento, va a fallar.
Cómo evitarlo: validar SIEMPRE los índices antes de acceder.
Error 4: "El tamaño del arreglo se puede cambiar en tiempo de ejecución"
Idea equivocada: "el usuario me dijo 10, pero después me dijo 100, así que cambio el tamaño del arreglo".
Realidad: en C++ los arreglos estáticos tienen tamaño fijo al compilar. Para tamaños dinámicos, necesitas arreglos dinámicos (new/delete, Tema 3.4) o vectores (std::vector, Tema 3.5).
Cómo evitarlo: usa una constante simbólica (const int MAX = 100;) y limita el tamaño al inicio.
Error 5: "Mayor = 0 funciona si todos los números son positivos"
Idea equivocada: "siempre inicializo con 0 porque mis datos son calificaciones".
Realidad: si un día los datos son números negativos, "mayor = 0" da el resultado incorrecto. La regla universal es: inicializa con el primer elemento.
Cómo evitarlo: mayor = nums[0] o menor = nums[0]. SIEMPRE.
🤖 IA como copiloto — 🤖 AI Mission 3.1 — Arreglos con IA
Regla de los 3 minutos (obligatoria): primero intenta por tu cuenta, después la IA con prompts específicos.
Prompts sugeridos
Prompt 1 — Detectar bug en un arreglo:
"Te voy a pegar un programa en C++ que accede a un arreglo. NO me lo corrijas. Solo dime: (1) qué hace, (2) si hay acceso fuera de rango, (3) en qué línea. Máximo 100 palabras."
Prompt 2 — Convertir a función:
"Te voy a pegar código que recorre un arreglo. NO me lo conviertas a función. Solo dime: (1) qué hace, (2) si se puede extraer a una función, (3) qué nombre le pondrías. Máximo 100 palabras."
Prompt 3 — Comparar rendimiento:
"Tengo un programa que busca un valor en un arreglo de 1 millón de elementos. ¿Es eficiente la búsqueda lineal? Dame 3 razones por las que sí o por las que no. Sin código, máximo 150 palabras."
Prompt 4 — Generar datos de prueba:
"Necesito 5 arreglos de prueba para un programa de calificaciones. Dame: (1) un arreglo normal, (2) uno con todos 10s, (3) uno con todos 0s, (4) uno con un solo valor, (5) uno con notas negativas. Para cada uno, dame los 5 valores y dime qué resultado esperarías. No me des código. Máximo 200 palabras."
🧪 Laboratorio — 🧪 LAB 3.1 — 6 ejercicios de arreglos 1D
Tiempo total: 1 h 30 min | Entregable: 6 programas funcionando con sus pruebas.
🛠️ Herramienta recomendada para los diagramas de flujo de este LAB: Para los ejercicios que pidan un diagrama de flujo, usa [draw.io (diagrams.net)](https://app.diagrams.net/) — herramienta gratis, sin registro, que funciona en el navegador. Tiene plantillas con la simbología ANSI/ISO lista (en `General → Flowchart`). Exporta tus diagramas como PNG e insértalos en tu cuaderno digital o entrégalos junto con el código.
Ejercicio 1 — Declarar y mostrar (básico, 10 min)
Enunciado. Declara un arreglo de 5 enteros, inicialízalo con valores, e imprímelo en formato índice: valor (uno por línea). Haz un diagrama de flujo clásico del proceso.
Rúbrica (10 pts): declaración correcta (2 pts) + inicialización (2 pts) + recorrido (3 pts) + formato (2 pts) + diagrama (1 pt).
Ejercicio 2 — Suma, promedio, mayor y menor (básico, 20 min)
Enunciado. Dado un arreglo de 10 calificaciones, calcula y muestra: suma, promedio (con 2 decimales), calificación más alta y más baja. Inicializa mayor y menor con el primer elemento.
Rúbrica (10 pts): suma (2 pts) + promedio (2 pts) + mayor (2 pts) + menor (2 pts) + formato (2 pts).
Ejercicio 3 — Búsqueda lineal (intermedio, 20 min)
Enunciado. Pide al usuario un valor a buscar. Recorre el arreglo y di si está, y en qué posición. Si hay duplicados, di TODAS las posiciones. Valida que el índice esté en rango.
Rúbrica (10 pts): búsqueda simple (3 pts) + duplicados (3 pts) + validación (2 pts) + mensajes (2 pts).
Ejercicio 4 — Inversión del arreglo (intermedio, 20 min)
Enunciado. Pide 5 números, guárdalos en un arreglo, e inviértelos (sin usar un segundo arreglo). Muestra el original y el invertido. Dibuja el diagrama de flujo del algoritmo de inversión.
Rúbrica (10 pts): algoritmo correcto (4 pts) + dibujo del diagrama (3 pts) + mensajes (2 pts) + verificación (1 pt).
Ejercicio 5 — Ordenamiento por burbuja manual (avanzado, 30 min)
Enunciado. Implementa el ordenamiento por burbuja (sin pedirle a la IA que te lo dé). Pide 10 números, ordénalos ascendentemente, y muestra el arreglo original y el ordenado paso a paso. Dibuja el diagrama de flujo del algoritmo.
Rúbrica (10 pts): algoritmo correcto (4 pts) + paso a paso (3 pts) + diagrama (2 pts) + formato (1 pt).
Ejercicio 6 — Detección de duplicados (avanzado, 30 min)
Enunciado. Pide 10 números al usuario. Detecta si hay duplicados y, si los hay, muestra cuáles y cuántas veces aparece cada uno. Usa el patrón de doble bucle (for anidado).
Rúbrica (10 pts): doble bucle (4 pts) + detección (3 pts) + conteo (2 pts) + mensajes (1 pt).
Ejercicio bonus — Ordenamiento con swap (opcional, 30 min)
Enunciado. Implementa el ordenamiento por selección: busca el menor de toda la lista, ponlo en la posición 0; luego el segundo menor en la posición 1, etc. Pide 6 números, ordénalos, muestra paso a paso.
Rúbrica bonus (5 pts): algoritmo (3 pts) + paso a paso (1 pt) + verificación (1 pt).
🎯 Cierre del tema
Lo que aprendiste hoy:
- Qué es un arreglo y por qué es la estructura más usada.
- Declaración, inicialización y acceso por índice 0-based.
- Almacenamiento contiguo en memoria y fórmula de direccionamiento.
- Recorrido con for y las 4 operaciones básicas.
- Validación de índices y prevención de accesos fuera de rango.
- 5 algoritmos clásicos: suma, mayor/menor, búsqueda lineal, inversión, duplicados.
- Comparación con Java y Python.
Lo que sigue: en el Tema 3.2 — Operaciones con Vectores + Análisis de Complejidad O(n) (8h), vas a profundizar en las operaciones más usadas con arreglos: ordenamiento (burbuja, selección, inserción), búsqueda avanzada, y vas a aprender a medir la eficiencia de tus algoritmos con la notación Big O. Esta es la skill que te separa de un junior "que programa" de un mid-level "que programa eficientemente".
Antes de seguir, asegúrate de tener en tu cuaderno:
- [ ] 6 programas del LAB 3.1 funcionando.
- [ ] El diagrama de "segmentos de memoria" dibujado a mano con tus palabras.
- [ ] Los 5 algoritmos clásicos (suma, mayor/menor, búsqueda, inversión, duplicados).
- [ ] Glosario con: arreglo, índice, contigüidad, O(1), fuera de rango, 0-based, stack, off-by-one.
XP obtenida al completar este tema: 100 base + 30 por LAB (6 ejercicios) + 20 por Quest = 150 XP. Insignia desbloqueada al cerrar el capítulo: Vector Master (parcial).
*"Un programa sin arreglos es una persona con un solo bolsillo. Un programa con arreglos es una persona con un maletín organizado: cada cosa en su lugar, accesible al instante."* — De la introducción de este manual.
Fin del Tema 3.1
📝 Quest · Cuestionario — 📝 Quest — Reactivos para autoevaluación
Las siguientes preguntas te sirven para autoevaluarte después de leer el tema. Responde en tu cuaderno o mentalmente, y luego revisa las Respuestas modelo (disponibles en libre acceso, sin iniciar sesión).
Sección A · Opción múltiple
Elige la opción correcta (A, B, C o D). Las respuestas están en la sección Respuestas modelo.
- ¿Cómo se declara un arreglo de 10 enteros en C++?
- int arr(10);
- int arr[10];
- array<int> arr;
- int arr = 10;
- ¿Cuál es el primer índice de un arreglo en C++?
- 1
- 0
- -1
- Depende
- Para acceder al 5to elemento de arr:
- arr[5]
- arr[4]
- arr(5)
- arr->5
- ¿Qué pasa si accedes a arr[10] en un arreglo de tamaño 10?
- Devuelve 0
- Comportamiento indefinido (puede crashear)
- Error de compilación
- Devuelve null
- ¿Cómo se inicializa un arreglo en C++?
- int arr[5] = {1,2,3,4,5};
- int arr = [1,2,3,4,5];
- int arr(5) = 1,2,3;
- Solo en tiempo de compilación
- ¿Qué pasa con elementos no inicializados en un arreglo global?
- Son null
- Son 0
- Son aleatorios
- Causan error
- Un arreglo de 5 doubles ocupa:
- 5 bytes
- 40 bytes
- 20 bytes
- 10 bytes
- ¿Cómo se recorre un arreglo en C++?
- for (auto x : arr)
- for (int i=0; i<n; i++)
- while
- Todas las anteriores
- ¿Cuál es la diferencia entre un arreglo y un vector?
- Son iguales
- Vector es dinámico, arreglo es tamaño fijo
- Vector es más lento siempre
- Arreglo tiene métodos
- ¿Cómo se pasa un arreglo a una función en C++?
- Por valor (copia completa)
- Por puntero o por referencia (evita copia)
- No se puede
- Por valor es lo único
Sección B · Preguntas abiertas
Desarrolla tu respuesta en al menos 3 líneas. Compara con la respuesta modelo después de escribir.
- Diseña una función en pseudocódigo que encuentre el máximo de un arreglo. ¿Complejidad?→ Escribe tu respuesta aquí (en tu cuaderno o mentalmente)…
- Explica la diferencia entre pasar un arreglo por valor y por puntero a una función. ¿Por qué es importante?→ Escribe tu respuesta aquí (en tu cuaderno o mentalmente)…
- ¿Cómo se inicializa un arreglo de 100 elementos con todos en 0? ¿Y uno de 10 elementos con valores específicos?→ Escribe tu respuesta aquí (en tu cuaderno o mentalmente)…
🟢 Cuando termines, revisa las Respuestas modelo y compáralas con las tuyas. La mejor forma de aprender es discutir cada respuesta contigo mismo o con un compañero.