COMPARTE ESTE ARTÍCULO

Material de apoyo (teoría + práctica) para trabajar arrays, ArrayList, búsquedas, desplazamientos e inserciones ordenadas con objetos.


0) Contexto: clases y modelo de datos

Trabajaremos con estas entidades:

  • Jugador: identifica a un jugador y su dorsal (numero).
  • Equipo: contiene una plantilla (Jugador[] jugadores) y metadatos (nombre, ciudad, ligas ganadas, etc.).
  • ManejoDeArrays: contiene un array de equipos (Equipo[] equipos) y una colección de equipos (ArrayList<Equipo> liga).

0.1) Recordatorio: encapsulación y getters/setters

Como los atributos son private, el acceso a datos debe hacerse mediante getters/setters:

  • Jugador.getNumero(), Jugador.setBaja(boolean)
  • Equipo.getJugadores(), Equipo.getLigasGanadas()
  • ManejoDeArrays.getEquipos(), ManejoDeArrays.getLiga()

En ejercicios y exámenes se suele penalizar el acceso directo a atributos privados.

0.2) Invariantes útiles (supuestos típicos)

En este tipo de problemas, suele asumirse:

  • En Equipo.jugadores, los primeros nJugadores elementos están ocupados y el resto son null (capacidad libre).
  • Si se indica que están ordenados por dorsal, se entiende por Jugador.numero.
  • En equipos puede haber posiciones null (equipos no cargados).

1) Desplazar a la derecha entre posiciones x e y (array equipos)

1.1) Qué significa “desplazar a la derecha” (dentro del tramo)

Cuando se pide desplazar a la derecha entre x e y (incluidos), lo más habitual en teoría es un desplazamiento circular del tramo:

  • El elemento en y “sale” del final del tramo y entra en x.
  • Cada elemento i en [x, y-1] pasa a i+1.

Es decir:

  • equipos[y] → equipos[x]
  • equipos[i] → equipos[i+1] para i = y-1 … x

Si en tu asignatura el desplazamiento NO es circular (se pierde el de y), el bucle es parecido pero cambia el uso del auxiliar. Aquí se presenta el modelo circular (el más frecuente cuando se habla de “casos particulares” y “caso general”).

1.2) Plantilla de respuesta “sin texto”: sólo gráficos + código

En algunos enunciados se exige NO explicar con texto. A continuación tienes una forma estándar de responder sólo con dibujos ASCII y código.

(A) Dibujar el array (tramo x..y)

Índices:   ...   x     x+1     x+2     ...    y-1      y    ...
Valores:   ...  [A]    [B]      [C]     ...    [Y]     [Z]   ...

(B) Dibujar el movimiento de datos

[B]  →  x+1
[C]  →  x+2
...
[Y]  →   y
[Z]  →   x

(C) Casos particulares (por posición)

Caso i = y:     equipos[y]  →  AUX
Caso i = y-1:   equipos[y-1] → equipos[y]
Caso i = y-2:   equipos[y-2] → equipos[y-1]
...
Caso i = x:     equipos[x]   → equipos[x+1]
Final:          AUX          → equipos[x]

(D) Caso general

Para i desde y hasta x+1:
   equipos[i] = equipos[i-1]

(E) Bucle (código)

Equipo aux = equipos[y];
for (int i = y; i > x; i--) {
    equipos[i] = equipos[i - 1];
}
equipos[x] = aux;

1.3) Checklist de validez (para evitar errores)

  • 0 <= x, y < equipos.length
  • x < y (si x == y, no hay nada que desplazar)
  • Control de null (si hay null en el tramo, se desplaza igual: null también se mueve)

2) Preguntas típicas sobre arrays / acceso a atributos

2.a) buscarMenor(int pos1, int pos2) por ligas ganadas

Objetivo: devolver el Equipo entre pos1 y pos2 (posiciones válidas) con menos ligasGanadas.

Puntos técnicos:

  • Normalizar rango: si pos1 > pos2, intercambiar.
  • Validar límites.
  • Tratar null (si hay huecos): lo correcto es ignorarlos y buscar entre los no nulos. Si todo es null, devolver null.

Código orientativo (en ManejoDeArrays):

public Equipo buscarMenor(int pos1, int pos2) {
    if (equipos == null || equipos.length == 0) return null;

    // Normalizar rango
    int a = Math.min(pos1, pos2);
    int b = Math.max(pos1, pos2);

    // Ajustar a límites válidos (si el enunciado dice "posiciones válidas",
    // este bloque podría sustituirse por una excepción)
    if (a < 0) a = 0;
    if (b >= equipos.length) b = equipos.length - 1;

    Equipo menor = null;
    for (int i = a; i <= b; i++) {
        if (equipos[i] == null) continue;
        if (menor == null || equipos[i].getLigasGanadas() < menor.getLigasGanadas()) {
            menor = equipos[i];
        }
    }
    return menor;
}

2.b) Recuperar numero del jugador posición 2, del equipo posición 1 (array equipos)

Recuerda: como los atributos son privados, se usa getter.

int dorsal = equipos[1].getJugadores()[2].getNumero();

(Con controles defensivos, si se pidiera robustez: comprobar equipos[1] != null, getJugadores() != null, etc.)

2.c) Asignar true a baja del jugador posición 1, del equipo posición 0, del ArrayList liga

liga.get(0).getJugadores()[1].setBaja(true);

3) eliminarEquipos() usando liga e iterador

3.1) Idea del método

Eliminar de liga todos los equipos que NO tengan ningún jugador con numero == 1.

  • Debe usarse un Iterator para poder borrar durante el recorrido sin errores.
  • Muy recomendable: método auxiliar tieneDorsal1(Equipo e).

3.2) Método auxiliar recomendado

private boolean tieneDorsal1(Equipo e) {
    if (e == null) return false;
    Jugador[] js = e.getJugadores();
    if (js == null) return false;

    for (Jugador j : js) {
        if (j != null && j.getNumero() == 1) {
            return true;
        }
    }
    return false;
}

3.3) Implementación con iterador (obligatoria)

public int eliminarEquipos() {
    if (liga == null) return 0;

    int eliminados = 0;
    java.util.Iterator<Equipo> it = liga.iterator();

    while (it.hasNext()) {
        Equipo e = it.next();
        if (!tieneDorsal1(e)) {
            it.remove();
            eliminados++;
        }
    }

    return eliminados;
}

3.4) Errores comunes

  • ❌ Usar for (Equipo e : liga) { liga.remove(e); } → lanza ConcurrentModificationException.
  • ❌ Usar índices (for (int i=0; i<liga.size(); i++)) y borrar sin ajustar → saltos de elementos.

4) Inserción ordenada de jugadores por dorsal (sin ordenar con métodos)

En el enunciado aparece el nombre darDorsal, pero el javadoc describe un método insertarJugador. El comportamiento pedido es: insertar un jugador manteniendo el array ordenado por dorsal.

4.1) Problema a resolver

  • Buscar un equipo por nombre dentro del array equipos.
  • Insertar nuevoJugador en Equipo.jugadores manteniendo orden ascendente por numero.
  • Si ya existe un jugador con el mismo dorsal → throw DorsalOcupado.
  • Si el equipo no existe / es nullthrow NoExiste.
  • NO se puede usar sort() ni métodos de ordenación.

4.2) Patrón de inserción ordenada (esquema)

  1. Localizar el equipo.
  2. Comprobar dorsal duplicado.
  3. Encontrar posición de inserción (primer j.numero > nuevo.numero).
  4. Desplazar a la derecha desde el final ocupado.
  5. Insertar.
  6. Devolver nJugadores actualizado.

4.3) Búsqueda del equipo en equipos

private int indiceEquipoPorNombre(String nombreEquipo) {
    if (equipos == null || nombreEquipo == null) return -1;

    for (int i = 0; i < equipos.length; i++) {
        if (equipos[i] != null && nombreEquipo.equals(equipos[i].getNombre())) {
            return i;
        }
    }
    return -1;
}

4.4) Comprobar si un dorsal está ocupado

private boolean dorsalOcupado(Equipo e, int nJugadores, int dorsal) {
    Jugador[] js = e.getJugadores();
    for (int i = 0; i < nJugadores; i++) {
        if (js[i] != null && js[i].getNumero() == dorsal) return true;
    }
    return false;
}

4.5) Implementación completa (sin ordenación)

/**
 * Método (insertarJugador) que añada un nuevo jugador al equipo de
 * nombre dado, suponiendo que los jugadores del equipo ya están
 * ordenados de menor a mayor por su dorsal.
 *
 * El jugador no se añadirá si su dorsal ya está usado por otro jugador.
 * Si se añade, se insertará en la posición adecuada para mantener orden.
 *
 * Usar el array equipos.
 *
 * @param equipo Nombre del equipo.
 * @param nJugadores Número de jugadores que hay en el equipo.
 * @param nuevoJugador Objeto Jugador a insertar.
 * @return Número de jugadores del equipo.
 * @throws DorsalOcupado si el equipo ya tenía un jugador con el mismo dorsal.
 * @throws NoExiste si el equipo es null o no existe en el array.
 */
public int insertarJugador(String equipo, int nJugadores, Jugador nuevoJugador)
        throws DorsalOcupado, NoExiste {

    if (equipo == null) throw new NoExiste("Nombre de equipo null");
    if (equipos == null) throw new NoExiste("Array de equipos null");

    int idx = indiceEquipoPorNombre(equipo);
    if (idx == -1) throw new NoExiste("Equipo no encontrado");

    Equipo e = equipos[idx];
    if (e == null) throw new NoExiste("Equipo null");

    Jugador[] js = e.getJugadores();
    if (js == null) throw new NoExiste("Plantilla (jugadores) null");

    // (Opcional) validar nJugadores
    if (nJugadores < 0) nJugadores = 0;
    if (nJugadores > js.length) nJugadores = js.length;

    int dorsalNuevo = nuevoJugador.getNumero();

    // 1) Duplicado
    if (dorsalOcupado(e, nJugadores, dorsalNuevo)) {
        throw new DorsalOcupado("Dorsal ya usado: " + dorsalNuevo);
    }

    // 2) Comprobar capacidad
    if (nJugadores >= js.length) {
        // Si existiera una excepción de capacidad (no indicada), aquí se lanzaría.
        // Como no se especifica, se podría devolver nJugadores sin cambios o lanzar RuntimeException.
        // Recomendación: lanzar una excepción específica si está definida en el temario.
        return nJugadores;
    }

    // 3) Encontrar posición de inserción
    int pos = 0;
    while (pos < nJugadores && js[pos].getNumero() < dorsalNuevo) {
        pos++;
    }

    // 4) Desplazar a la derecha para abrir hueco
    for (int i = nJugadores; i > pos; i--) {
        js[i] = js[i - 1];
    }

    // 5) Insertar
    js[pos] = nuevoJugador;

    // 6) Nuevo tamaño lógico
    return nJugadores + 1;
}

4.6) Errores comunes

  • ❌ Recorrer hasta js.length en vez de hasta nJugadores (puede haber null).
  • ❌ Desplazar de izquierda a derecha (se sobrescriben datos). Debe ser de derecha a izquierda.
  • ❌ No validar que hay hueco para insertar.

5) Mini-banco de pruebas (para practicar)

5.1) Preparar un equipo con plantilla ordenada

Jugador j1 = new Jugador("Ana", "DEL", new String[]{"A"}, 3, false);
Jugador j2 = new Jugador("Luis", "POR", new String[]{"B"}, 8, false);
Jugador j3 = new Jugador("Marta", "DEF", new String[]{"C"}, 10, false);

Jugador[] plantilla = new Jugador[5];
plantilla[0] = j1;
plantilla[1] = j2;
plantilla[2] = j3;

Equipo eq = new Equipo("SanRoque FC", "Cádiz", plantilla, 2, true);

5.2) Insertar un jugador manteniendo orden

Jugador nuevo = new Jugador("Pepe", "MED", new String[]{"D"}, 9, false);
int n = 3;

// Debe quedar: 3, 8, 9, 10
n = manejo.insertarJugador("SanRoque FC", n, nuevo);

5.3) Probar el desplazamiento (x..y)

// equipos: [E0, E1, E2, E3, E4]
// desplazar x=1, y=3 => [E0, E3, E1, E2, E4]

6) Resumen operativo (para examen/práctica)

  • Desplazar tramo x..y a la derecha → aux = a[y], for (i=y; i>x; i--) a[i]=a[i-1]; a[x]=aux.
  • Buscar menor por ligas ganadas → recorrido lineal con variable menor.
  • Accesos anidados (array/ArrayList) → encadenar getters: equipos[1].getJugadores()[2].getNumero().
  • Eliminar en colección → siempre con Iterator si se borra durante el recorrido.
  • Insertar ordenado sin ordenar → hallar posición + desplazar a la derecha + colocar.

Contenido restringido

Acceso de usuarios existentes
   
Registro de un nuevo usuario
*Campo necesario

Categories:

Tags:

Comments are closed

Estado de acceso
ESTADO DE ACCESO
TRADUCTORES
COMPARTENOS
Insert math as
Block
Inline
Additional settings
Formula color
Text color
#333333
Type math using LaTeX
Preview
\({}\)
Nothing to preview
Insert
error: CONTENIDO PROTEGIDO