Estructuras de Datosc++structestructurastipos-personalizados
Struct en C++
Aprende a crear y usar estructuras personalizadas para organizar datos relacionados
OOI Oaxaca9 de febrero de 20266 min read
¿Qué es un struct?
Un struct permite agrupar variables relacionadas bajo un mismo nombre. Es útil para representar entidades con múltiples atributos.
Definición básica
struct Persona {
string nombre;
int edad;
double altura;
};
int main() {
Persona p;
p.nombre = "Juan";
p.edad = 25;
p.altura = 1.75;
cout << p.nombre << " tiene " << p.edad << " años" << endl;
return 0;
}
Inicialización
// Método 1: Inicialización por campos
Persona p1;
p1.nombre = "Ana";
p1.edad = 30;
// Método 2: Inicialización con llaves
Persona p2 = {"Carlos", 28, 1.80};
// Método 3: Inicialización designada (C++20)
Persona p3 = {.nombre = "María", .edad = 22, .altura = 1.65};
Structs con arreglos y vectores
struct Persona {
string nombre;
int edad;
};
// Arreglo de structs
Persona personas[100];
personas[0] = {"Juan", 25};
// Vector de structs (recomendado)
vector<Persona> lista;
lista.push_back({"Ana", 30});
lista.push_back({"Carlos", 28});
for (const Persona& p : lista) {
cout << p.nombre << ": " << p.edad << endl;
}
Structs como parámetros
Por valor (copia)
void imprimir(Persona p) {
cout << p.nombre << " - " << p.edad << endl;
}
Por referencia (eficiente, sin copia)
void cumpleAnios(Persona& p) {
p.edad++;
}
Por referencia constante (eficiente, solo lectura)
void mostrar(const Persona& p) {
cout << p.nombre << endl;
// p.edad = 30; // Error: no se puede modificar
}
Struct para competencias: Punto
struct Punto {
int x, y;
};
// Distancia entre dos puntos
double distancia(const Punto& a, const Punto& b) {
return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
}
Struct para competencias: Par ordenado
struct Par {
int valor;
int indice;
};
int main() {
vector<Par> arr = {{5, 0}, {3, 1}, {8, 2}, {1, 3}};
// Ordenar por valor
sort(arr.begin(), arr.end(), [](const Par& a, const Par& b) {
return a.valor < b.valor;
});
// Ahora arr está ordenado por valor, pero conservamos los índices originales
for (const Par& p : arr) {
cout << "Valor: " << p.valor << ", Índice original: " << p.indice << endl;
}
return 0;
}
Operadores de comparación
Para poder ordenar structs, necesitas definir cómo se comparan:
Método 1: Operador menor que
struct Persona {
string nombre;
int edad;
bool operator<(const Persona& otra) const {
if (edad != otra.edad) {
return edad < otra.edad; // Menor edad primero
}
return nombre < otra.nombre; // Si igual edad, orden alfabético
}
};
// Ahora puedes usar sort directamente
vector<Persona> lista = {{"Ana", 30}, {"Juan", 25}, {"María", 30}};
sort(lista.begin(), lista.end());
Método 2: Función comparadora
struct Persona {
string nombre;
int edad;
};
bool compararPorEdad(const Persona& a, const Persona& b) {
return a.edad < b.edad;
}
bool compararPorNombre(const Persona& a, const Persona& b) {
return a.nombre < b.nombre;
}
// Uso
sort(lista.begin(), lista.end(), compararPorEdad);
Método 3: Lambda (más común en competencias)
sort(lista.begin(), lista.end(), [](const Persona& a, const Persona& b) {
return a.edad < b.edad;
});
Struct para representar aristas
Común en problemas de grafos:
struct Arista {
int origen, destino, peso;
bool operator<(const Arista& otra) const {
return peso < otra.peso;
}
};
int main() {
vector<Arista> aristas = {
{0, 1, 5},
{1, 2, 3},
{0, 2, 8}
};
// Ordenar por peso (para Kruskal)
sort(aristas.begin(), aristas.end());
return 0;
}
Struct para eventos
struct Evento {
int tiempo;
int tipo; // 0 = inicio, 1 = fin
bool operator<(const Evento& otro) const {
if (tiempo != otro.tiempo) return tiempo < otro.tiempo;
return tipo < otro.tipo; // Priorizar inicios
}
};
// Útil para sweep line
Ejemplo: Ordenar estudiantes
struct Estudiante {
string nombre;
double promedio;
int id;
};
int main() {
vector<Estudiante> lista = {
{"Ana", 9.5, 1},
{"Juan", 8.7, 2},
{"María", 9.5, 3},
{"Carlos", 9.0, 4}
};
// Ordenar por promedio (mayor a menor), si empatan por nombre
sort(lista.begin(), lista.end(), [](const Estudiante& a, const Estudiante& b) {
if (a.promedio != b.promedio) {
return a.promedio > b.promedio; // Mayor promedio primero
}
return a.nombre < b.nombre; // Alfabéticamente
});
for (const auto& e : lista) {
cout << e.nombre << ": " << e.promedio << endl;
}
return 0;
}
Struct con funciones miembro
struct Rectangulo {
int ancho, alto;
int area() const {
return ancho * alto;
}
int perimetro() const {
return 2 * (ancho + alto);
}
bool esValido() const {
return ancho > 0 && alto > 0;
}
};
int main() {
Rectangulo r = {5, 3};
cout << "Área: " << r.area() << endl; // 15
cout << "Perímetro: " << r.perimetro() << endl; // 16
return 0;
}
pair y tuple de la STL
Para casos simples, puedes usar las estructuras de la STL:
pair
#include <utility>
pair<int, string> p = {1, "uno"};
cout << p.first << " " << p.second << endl;
// Común para coordenadas
pair<int, int> punto = {3, 4};
tuple
#include <tuple>
tuple<int, string, double> t = {1, "uno", 1.0};
cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl;
// Desempaquetar (C++17)
auto [a, b, c] = t;
Ejercicios de práctica
Ejercicio 1
Crea un struct para representar un intervalo [inicio, fin] y ordena intervalos por inicio.
Ver solución
struct Intervalo {
int inicio, fin;
bool operator<(const Intervalo& otro) const {
if (inicio != otro.inicio) return inicio < otro.inicio;
return fin < otro.fin;
}
};
int main() {
vector<Intervalo> intervalos = {{5, 10}, {1, 3}, {2, 8}};
sort(intervalos.begin(), intervalos.end());
// Resultado: [1,3], [2,8], [5,10]
return 0;
}
Ejercicio 2
Crea un struct para representar fracciones con función de simplificar.
Ver solución
struct Fraccion {
int num, den;
void simplificar() {
int g = __gcd(abs(num), abs(den));
num /= g;
den /= g;
if (den < 0) {
num = -num;
den = -den;
}
}
Fraccion operator+(const Fraccion& otra) const {
Fraccion r = {num * otra.den + otra.num * den, den * otra.den};
r.simplificar();
return r;
}
};
int main() {
Fraccion a = {1, 2};
Fraccion b = {1, 3};
Fraccion c = a + b;
cout << c.num << "/" << c.den << endl; // 5/6
return 0;
}
Siguiente paso
Aprende sobre Ordenamiento con Sort de STL para ordenar estructuras eficientemente.
