4/03/2017

Ejercicio 47

Una institución educativa requiere saber la información de sus estudiantes, se debe tener en cuenta su identificación, nombre, semestre y sus notas.

Lista Simple Enlazada

Para la solución se deben implementar las clases necesarias que permitan llenar una lista simple enlazada, que guarde la información recolectada de los estudiantes. El programa debe realizar las siguientes operaciones sobre los nodos almacenados en la lista simple enlazada:

  • Registrar un estudiante.

  • Buscar mediante ID

  • Mostrar estudiantes aprobados ordenados por semestre ascendentemente.

  • Mostrar información ordenada descendentemente; para aquellos estudiantes con promedio superior al promedio general de notas

  • Eliminar estudiantes con promedio de notas igual al promedio general.

  • Salir


#include <iostream>
// se incluye la clases Nodo para despues llamar a sus metodos 
#include "Nodo.h"
// se incluye la clase Lista para despues llamar a sus metodos 
#include "Lista.h"
// se incluye la clase stdlib para poder utilizar el metodo system que nos permitira utilizar los comandos basicos de la consola, en este caso lo utilizaremos para limpiar la pantalla de la consola system("cls")  
#include "stdlib.h"

using namespace std;

// método para llenar un nodo 
void llenar(Nodo *n, Lista *obj)
{
    int id, sem;
    float nota;
    do
    {
        cout << "Digite identificacion" << endl;
        cout << ">> ";
        cin >> id;
    }
    while(obj->validarId(id) == true);//si validarId() retorna TRUE entonces la id esta utilizada. 
    n->setId(id);
    // se pide en pantalla el nombre 
    string nom;
    cout << "Digite su nombre" << endl;
    cout << ">> ";
    cin >> nom;
    // se encapsula la variable nom 
    n->setNombre(nom);
    // se pide en pantalla el semetres 
    cout << "Digite su semestre" << endl;
    cout << ">> ";
    cin >> sem;
    // se encapsula la variable sem 
    n->setSemestre(sem);
    // se itera 3 veces con el ciclo for 
    for (int i = 0; i < 3;  i++)
    {
        // se pedira la nota de nuevo si digita una nota menor a 0 ó mayor a 5 
        do
        {
            cout << "Digite la nota " << (i+1) << endl;
            cout << ">> ";
            cin >> nota;
        }
        while (nota < 0 || nota > 5);
        // se encapsula en la posicion i el valor de la variable nota 
        n->setNotas(i, nota);
    }
}

// método para mostrar la información de un nodo 
void mostrar(Nodo *n)
{
    cout << "ID: " << n->getId() << endl;
    cout << "Nombre: " << n->getNombre() << endl;
    cout << "Semestre: " << n->getSemestre() << endl;
    cout << "Nota 1: " << n->getNotas(0) << endl;
    cout << "Nota 2: " << n->getNotas(1) << endl;
    cout << "Nota 2: " << n->getNotas(2) << endl;
    cout << "Promedio: " << n->promedio() << endl << endl;
}

// método para listar la información de todos los nodos de la lista 
void listar(Nodo *n)
{
    Nodo *temp = n;
    while(temp != NULL)
    {
        mostrar(temp);
        temp = temp->getSiguiente();
    }
}

// método para mostrar el menu de opciones 
int menu()
{
    int opcion = 0;
    do
    {
        cout << "=========== SELECCIONE UNA OPCION DEL MENU ===========" << endl;
        cout << "1. Registrar estudiante." << endl;
        cout << "2. Buscar por ID." << endl;
        cout << "3. Mostar estudiantes aprobados ordenados ascendemente por el semestre." << endl;
        cout << "4. Mostar estudiantes con promedio superior al promedio de notas ordenados descendemente por el semestre." << endl;
        cout << "5. Eliminar estudiantes con promedio de notas igual al promedio general." << endl;
        cout << "6. Mostrar toda la lista." << endl;
        cout << "7. Salir" << endl << endl;
        cout << ">> ";
        cin >> opcion;
        system("cls");
    }
    while(opcion < 1 || opcion > 7);
    return opcion;
}

int main(void)
{
    // se crea un objeto de la clase Lista (Instanciación) 
    Lista *obj = new Lista();
    // se declaran 2 variables de tipo entero opcion e id 
    int opcion, id;
    // se declara una variable de tipo string nombre 
    string nombre;
    // se declara una variable de tipo Nodo aux 
    Nodo *aux;
    do
    {
        // se le asigna a la variable opcion el valor que retorne el metodo menu 
        opcion = menu();
        // dependiendo del valor de la variable opcion se escogera un caso 
        switch(opcion)
        {
            case 1:
                aux = new Nodo();
                llenar(aux, obj);
                obj->agregarFinal(aux);
                break;
            case 2:
                cout << "Digite ID del estudiante que quiere agregar" << endl;
                cout << ">> ";
                cin >> id;
                aux = obj->buscarId(id);
                if(aux != NULL)
                {
                    mostrar(aux);
                }
                else
                {
                    cout << "La ID NO se encuentra en la lista" << endl;
                }
                break;
            case 3:
                aux = obj->getCabeza();
                if(aux == NULL)
                {
                    cout << "No hay estudiantes matriculados" << endl;
                }
                else
                {
                    if(obj->contarNodos() > 1)
                    {
                        aux = obj->getCabeza();
                        obj->ordenarAscendentemente(aux);
                        while(aux != NULL)
                        {
                            if (aux->promedio() >= 3)
                            {
                                mostrar(aux);
                            }
                            aux = aux->getSiguiente();
                        }
                    }
                    else
                    {
                        cout << "Solo hay un estudiante, agregue por lo menos 1 estudiante mas para ordenar" << endl;
                    }
                }
                break;
            case 4:
                aux = obj->getCabeza();
                if(aux == NULL)
                {
                    cout << "No hay estudiantes matriculados" << endl;
                }
                else
                {
                    if(obj->contarNodos() > 1)
                    {
                        aux = obj->getCabeza();
                        obj->ordenarDescendentemente(aux);
                        while(aux != NULL)
                        {
                            if (aux->promedio() > obj->promedioGeneral())
                            {
                                mostrar(aux);
                            }
                            aux = aux->getSiguiente();
                        }
                    }
                    else
                    {
                        cout << "Solo hay un estudiante, agregue por lo menos 1 estudiante mas para ordenar" << endl;
                    }
                }
                break;
            case 5:
                aux = obj->getCabeza();
                if(aux == NULL)
                {
                    cout << "No hay estudiantes matriculados" << endl;
                }
                else
                {
                    obj->limpiar();
                }
                break;
            case 6:
                aux = obj->getCabeza();
                if(aux == NULL)
                {
                    cout << "No hay estudiantes matriculados" << endl;
                }
                else
                {
                    listar(aux);
                }
            default:
                break;
        }
    }
    while(opcion != 7);
}

#ifndef NODO_H
#define NODO_H
#include <iostream>

using namespace std;

class Nodo
{
    public:
        Nodo();
        virtual ~Nodo();
        // metodos publico de la clase 
        void setId(int val);
        int getId();
        void setNombre(string val);
        string getNombre();
        void setSemestre(int val);
        int getSemestre();
        void setNotas(int pos, float val);
        float getNotas(int pos);
        void setSiguiente(Nodo *val);
        Nodo *getSiguiente();
        void copiar(Nodo *nd);
        float promedio();
    protected:

    private:
        // se declaran los atributos privados de la clase 
        int id;
        string nombre;
        int semestre;
        float *notas;
        Nodo *siguiente;
};

#endif // NODO_H

#include "Nodo.h"

Nodo::Nodo()
{
    // le asignamos valores por defecto a los atributos de la clase en el constructor 
    id = 0;
    nombre = "";
    semestre = 0;
    notas = new float[3];
    siguiente = NULL;
}

Nodo::~Nodo()
{
    //dtor 
}

// metodos Setters y Getters 
void Nodo::setId(int val)
{
    id = val;
}

int Nodo::getId()
{
    return id;
}

void Nodo::setNombre(string val)
{
    nombre = val;
}

string Nodo::getNombre()
{
    return nombre;
}

void Nodo::setSemestre(int val)
{
    semestre = val;
}

int Nodo::getSemestre()
{
    return semestre;
}

void Nodo::setNotas(int pos, float val)
{
    notas[pos] = val;
}

float Nodo::getNotas(int pos)
{
    return notas[pos];
}

void Nodo::setSiguiente(Nodo *val)
{
    siguiente = val;
}

Nodo *Nodo::getSiguiente()
{
    return siguiente;
}

// método para copiar la información de un nodo 
void Nodo::copiar(Nodo *nd)
{
    id = nd->getId();
    nombre = nd->getNombre();
    semestre = nd->getSemestre();
    for (int i = 0; i < 3; i++)
    {
        notas[i] = nd->getNotas(i);
    }
}

// método para calcular el promedio 
float Nodo::promedio()
{
    float suma = 0;
    for (int i = 0; i < 3; i++)
    {
        suma += getNotas(i);
    }
    return suma/3;
}

#ifndef LISTA_H
#define LISTA_H
#include "Lista.h"
#include "Nodo.h"

class Lista
{
    public:
        Lista();
        virtual ~Lista();
        // metodos publico de la clase 
        void setCabeza(Nodo *n);
        Nodo *getCabeza();
        bool validarId(int c);
        Nodo *ultimo();
        int contarNodos();
        void agregarFinal(Nodo *n);
        Nodo *buscarId(int c);
        void ordenarAscendentemente(Nodo *n);
        void ordenarDescendentemente(Nodo *n);
        void cambiar(Nodo *p1, Nodo *p2);
        float promedioGeneral();
        void eliminar(Nodo *n);
        void limpiar();
    protected:

    private:
        // se declara un atributo privado de tipo Nodo llamado cabeza 
        Nodo *cabeza;
};

#endif // LISTA_H

#include "Lista.h"

Lista::Lista()
{
    // le asignamos un valor por defecto al atributo de la clase en el constructor 
    cabeza = NULL;
}

Lista::~Lista()
{
    //dtor 
}

// método set y get del atributo de la clase 
void Lista::setCabeza(Nodo *n)
{
    cabeza = n;
}

Nodo *Lista::getCabeza()
{
    return cabeza;
}

// método para validar si un ID no se ha repetido 
bool Lista::validarId(int c)
{
    // se inicializa una variable de tipo Nodo y se le asigna la cabeza 
    Nodo *temp = cabeza;
    // se inicializa una variable de tipo booleana y se le asigna false 
    bool igual = false;
    // mientras haya un nodo en la lista 
    while(temp != NULL)
    {
        // si el id del nodo temporal es igual al valor de la variable c pasada como parametro 
        if(temp->getId() == c)
        {
            // entonces se le asigna a igual el valor de true 
            igual = true;
            // se rompe el ciclo 
            break;
        }
        // se salta al siguiente nodo de temp 
        temp = temp->getSiguiente();
    }
    // se retorna el valor de la variable igual 
    return igual;
}

// método para retornar el ultimo nodo de la lista 
Nodo *Lista::ultimo()
{
    // se inicializa una variable de tipo Nodo en la cabeza 
    Nodo *temp = cabeza;
    // mientras haya un nodo en la lista 
    while(temp != NULL)
    {
        // entonces, si el siguiente nodo de temp es igual a null 
        if (temp->getSiguiente() == NULL)
        {
            // entonces, se rompe el ciclo 
            break;
        }
        else
        {
            // sino, se salta al siguiente nodo del temp 
            temp = temp->getSiguiente();
        }
    }
    // se retorna el nodo temp 
    return temp;
}

// método para contar los nodos de la lista 
int Lista::contarNodos()
{
    // se inicializa la variable de tipo Nodo temp en la cabeza 
    Nodo *temp = cabeza;
    // se inicializa la variable de tipo entero contador en 0 
    int contador = 0;
    // mientras haya un nodo en la lista 
    while(temp != NULL)
    {
        // se incrementara la variable contador 
        contador++;
        // y se salta al siguiente nodo de temp 
        temp = temp->getSiguiente();
    }
    // se retorna el valor de la variable contador 
    return contador;
}

// método para agregar nodos por el final 
void Lista::agregarFinal(Nodo *n)
{
    // si la cabeza es igual a null 
    if(cabeza == NULL)
    {
        // entonces la la cabeza ahora sera el nodo n 
        setCabeza(n);
    }
    else
    {
        // sino el ultimo nodo apuntara al nodo n 
        ultimo()->setSiguiente(n);
    }
}

// método para buscar por ID 
Nodo *Lista::buscarId(int c)
{
    // se inicializa la variable de tipo Nodo temp en la cabeza 
    Nodo *temp = cabeza;
    // mientras haya un nodo en la lista 
    while(temp != NULL)
    {
        // si el id del nodo actual es igual al valor de la variable c pasada como parametro 
        if(temp->getId() == c)
        {
            // se rompe el ciclo 
            break;
        }
        // se salta al siguiente nodo de temp 
        temp = temp->getSiguiente();
    }
    // se retorna el nodo temp 
    return temp;

}

// método para ordenar ascendentemente 
void Lista::ordenarAscendentemente(Nodo *n)
{
    // se declaran dos variables de tipo Nodo 
    Nodo *actual;
    Nodo *siguiente;
    // se le asigna a la variable actual el valor de n 
    actual = n;
    // mientras el siguiente nodo del nodo actual sea diferente a null 
    while(actual->getSiguiente() != NULL)
    {
        // el nodo siguiente saltara al siguiente nodo del nodo actual 
        siguiente = actual->getSiguiente();
        // mientras el nodo siguiente sea diferente a null 
        while(siguiente != NULL)
        {
            // si el semestre del nodo actual es mayor al semestre del nodo siguiente 
            if(actual->getSemestre() > siguiente->getSemestre())
            {
                // entonces se cambiara al nodo actual con el siguiente 
                cambiar(actual, siguiente);
            }
            // el nodo siguiente saltara a su siguiente nodo 
            siguiente = siguiente->getSiguiente();
        }
        // el nodo actual saltara a su siguiente nodo 
        actual = actual->getSiguiente();
    }
}

// método para ordenar descendentemente 
void Lista::ordenarDescendentemente(Nodo *n)
{
    // se declaran dos variables de tipo Nodo 
    Nodo *actual;
    Nodo *siguiente;
    // se le asigna a la variable actual el valor de n 
    actual = n;
    // mientras el siguiente nodo del nodo actual sea diferente a null 
    while(actual->getSiguiente() != NULL)
    {
        // el nodo siguiente saltara al siguiente nodo del nodo actual 
        siguiente = actual->getSiguiente();
        // mientras el nodo siguiente sea diferente a null 
        while(siguiente != NULL)
        {
            // si el semestre del nodo actual es menor al semestre del nodo siguiente 
            if(actual->getSemestre() < siguiente->getSemestre())
            {
                // entonces se cambiara al nodo actual con el siguiente 
                cambiar(actual, siguiente);
            }
            // el nodo siguiente saltara a su siguiente nodo 
            siguiente = siguiente->getSiguiente();
        }
        // el nodo actual saltara a su siguiente nodo 
        actual = actual->getSiguiente();
    }
}

// método para cambiar los nodos 
void Lista::cambiar(Nodo *p1, Nodo *p2)
{
    // creo un nuevo nodo para poder realizar la copia 
    Nodo *temp = new Nodo();
    // le asigno al nodo temp los datos del nodo actual (p1) 
    temp->copiar(p1);
    // le asigno al nodo p1 los datos del nodo siguiente (p2) 
    p1->copiar(p2);
    // le asigno al nodo p2 los datos del temp 
    p2->copiar(temp);
}

// método para calcular el promedio general 
float Lista::promedioGeneral()
{
    // se inicializa la variable de tipo Nodo temp en la cabeza 
    Nodo *temp = cabeza;
    // se inicializa una variable de tipo float en 0 
    float suma = 0;
    // mientras haya un nodo en la lista 
    while(temp != NULL)
    {
        // se le acumulara a la variable suma el valor de suma mas el valor del promedio del nodo temp 
        suma += temp->promedio();
        // se salta al siguiente nodo de temp 
        temp = temp->getSiguiente();
    }
    // se retorna el valor de la variable suma entre el total de nodos 
    return suma/contarNodos();
}

// método para eliminar nodo 
void Lista::eliminar(Nodo *n)
{
    // se declara una variable de tipo Nodo llamada anterior 
    Nodo *anterior;
    // si promedio del nodo n es igual al promedio general 
    if(n->promedio() == promedioGeneral())
    {
        // si el nodo nd es igual a la cabeza 
        if(n  == cabeza)
        {
            // entonces, la cabeza saltara a su siguiente (saltaria a null) 
            cabeza = cabeza->getSiguiente();
        }
        else
        {
            // sino, el nodo anterior tendra el valor de la cabeza 
            anterior = cabeza;
            // mientras el siguiente nodo del anterior sea difente al nodo nd 
            while(anterior->getSiguiente() != n)
            {
                // entonces se salta al siguiente nodo del anterior 
                anterior = anterior->getSiguiente();
            }
            // el siguiente del anterior ahora sera el siguiente nodo de nd 
            anterior->setSiguiente(n->getSiguiente());
        }
        // el anterior del siguiente nodo de nd ahora sera el nodo anterior 
        n->setSiguiente(NULL);
    }
}

// método para limpiar toda la lista 
void Lista::limpiar()
{
    // mientras haya un nodo en la lista 
    while(cabeza != NULL)
    {
        // se elimina la cabeza 
        eliminar(cabeza);
    }
}

// se importa paquete JOptionPane para dibujar un cuadro de dialogo en pantalla
// que muestre información o para llenar información 
import javax.swing.JOptionPane;

public class Main
{
    // método para llenar un nodo 
    public static void llenar(Nodo n, Lista obj)
    {
        int id, sem;
        float nota;
        do
        {
            id = Integer.parseInt(JOptionPane.showInputDialog(null, "Digite identificación:"));
        }
        while(obj.validarId(id) == true);//si validarId() retorna TRUE entonces la id esta utilizada. 
        n.setId(id);
        // se pide en pantalla el nombre 
        String nom = JOptionPane.showInputDialog(null, "Digite su nombre:");
        // se encapsula la variable nom 
        n.setNombre(nom);
        // se pide en pantalla el semetres 
        sem = Integer.parseInt(JOptionPane.showInputDialog(null, "Digite su semestre"));
        // se encapsula la variable sem 
        n.setSemestre(sem);
        // se itera 3 veces con el ciclo for 
        for (int i = 0; i < 3;  i++)
        {
            // se pedira la nota de nuevo si digita una nota menor a 0 ó mayor a 5 
            do
            {
                nota = Float.parseFloat(JOptionPane.showInputDialog("Digite la nota " + (i+1)));
            }
            while (nota < 0 || nota > 5);
            // se encapsula en la posicion i el valor de la variable nota 
            n.setNotas(i, nota);
        }
    }
    
    // método para mostrar la información de un nodo 
    public static void mostrar(Nodo n)
    {
        String datosNodo = "";
        datosNodo += String.valueOf(
            "ID: " + n.getId() + "\n" +
            "Nombre: " + n.getNombre() + "\n" +
            "Semestre: " + n.getSemestre() + "\n" +
            "Nota 1: " + n.getNotas(0) + "\n" +
            "Nota 2: " + n.getNotas(1) + "\n" +
            "Nota 2: " + n.getNotas(2) + "\n" +
            "Promedio: " + n.promedio() + "\n\n");
        JOptionPane.showMessageDialog(null, "=========== INFORMACÓN DE LOS NODOS DE LA LISTA =========== \n"+ datosNodo);
    }
    
    // método para listar la información de todos los nodos de la lista 
    public static void listar(Nodo n)
    {
        Nodo temp = n;
        while(temp != null)
        {
            mostrar(temp);
            temp = temp.getSiguiente();
        }
    }
    
    // método para mostrar el menu de opciones 
    public static int menu()
    {
        int opcion = 0;
        do
        {
            opcion = Integer.parseInt(JOptionPane.showInputDialog("=========== SELECCIONE UNA OPCIÓN DEL MENÚ =========== \n" +
            "1. Registrar estudiante.\n" +
            "2. Buscar por ID.\n" +
            "3. Mostar estudiantes aprobados ordenados ascendemente por el semestre.\n" +
            "4. Mostar estudiantes con promedio superior al promedio de notas ordenados descendemente por el semestre.\n" +
            "5. Eliminar estudiantes con promedio de notas igual al promedio general.\n" +
            "6. Mostrar toda la lista\n" +
            "7. Salir\n\n" +
            " Seleccione una opción del 1 al 7:"));
        }
        while(opcion < 1 || opcion > 7);
        return opcion;
    }
    
    public static void main(String[] args)
    {
        // se crea un objeto de la clase Lista (Instanciación) 
        Lista obj = new Lista();
        // se declaran 2 variables de tipo entero opcion e id 
        int opcion, id;
        // se declara una variable de tipo string nombre 
        String nombre;
        // se declara una variable de tipo Nodo aux 
        Nodo aux;
        do
        {
            // se le asigna a la variable opcion el valor que retorne el metodo menu 
            opcion = menu();
            // dependiendo del valor de la variable opcion se escogera un caso 
            switch(opcion) 
            {
                case 1:
                    aux = new Nodo();
                    llenar(aux, obj);
                    obj.agregarFinal(aux);
                    break;
                case 2:
                    id = Integer.parseInt(JOptionPane.showInputDialog("Digite ID del estudiante que quiere agregar: "));
                    aux = obj.buscarId(id);
                    if(aux != null)
                    {
                        mostrar(aux);
                    }
                    else
                    {
                        JOptionPane.showMessageDialog(null, "La ID NO se encuentra en la lista");
                    }
                    break;
                case 3:
                    aux = obj.getCabeza();
                    if(aux == null)
                    {
                        JOptionPane.showMessageDialog(null, "No hay estudiantes matriculados");
                    }
                    else
                    {
                        if(obj.contarNodos() > 1)
                        {
                            aux = obj.getCabeza();
                            obj.ordenarAscendentemente(aux);
                            while(aux != null)
                            {
                                if (aux.promedio() >= 3)
                                {
                                    mostrar(aux);
                                }
                                aux = aux.getSiguiente();
                            }
                        }
                        else
                        {
                            JOptionPane.showMessageDialog(null, "Solo hay un estudiante, agregue por lo menos 1 estudiante mas para ordenar");
                        }
                    }
                    break;
                case 4:
                    aux = obj.getCabeza();
                    if(aux == null)
                    {
                        JOptionPane.showMessageDialog(null, "No hay estudiantes matriculados");
                    }
                    else
                    {
                        if(obj.contarNodos() > 1)
                        {
                            aux = obj.getCabeza();
                            obj.ordenarDescendentemente(aux);
                            while(aux != null)
                            {
                                if (aux.promedio() > obj.promedioGeneral())
                                {
                                    mostrar(aux);
                                }
                                aux = aux.getSiguiente();
                            }
                        }
                        else
                        {
                            JOptionPane.showMessageDialog(null, "Solo hay un estudiante, agregue por lo menos 1 estudiante mas para ordenar");
                        }
                    }
                    break;
                case 5:
                    aux = obj.getCabeza();
                    if(aux == null)
                    {
                        JOptionPane.showMessageDialog(null, "No hay estudiantes matriculados");
                    }
                    else
                    {
                        obj.limpiar();
                    }
                    break;
                case 6:
                    aux = obj.getCabeza();
                    if(aux == null)
                    {
                        JOptionPane.showMessageDialog(null, "No hay estudiantes matriculados");
                    }
                    else
                    {
                        listar(aux);
                    }
                default:
                    break;
            }
        }
        while(opcion != 7);
    }
}

public class Nodo
{
    // se declaran los atributos privados de la clase 
    private int id;
    private String nombre;
    private int semestre;
    private float [] notas;
    private Nodo siguiente;
    
    public Nodo()
    {
        // le asignamos valores por defecto a los atributos de la clase en el constructor 
        id = 0;
        nombre = "";
        semestre = 0;
        notas = new float[3];
        siguiente = null;
    }
    
    // metodos Setters y Getters 
    public void setId(int val)
    {
        id = val;
    }
    
    public int getId()
    {
        return id;
    }
    
    public void setNombre(String val)
    {
        nombre = val;
    }
    
    public String getNombre()
    {
        return nombre;
    }
    
    public void setSemestre(int val)
    {
        semestre = val;
    }
    
    public int getSemestre()
    {
        return semestre;
    }
    
    public void setNotas(int pos, float val)
    {
        notas[pos] = val;
    }
    
    public float getNotas(int pos)
    {
        return notas[pos];
    }
    
    public void setSiguiente(Nodo val)
    {
        siguiente = val;
    }
    
    public Nodo getSiguiente()
    {
        return siguiente;
    }
    
    // método para copiar la información de un nodo 
    public void copiar(Nodo nd)
    {
        id = nd.getId();
        nombre = nd.getNombre();
        semestre = nd.getSemestre();
        for (int i = 0; i < 3; i++)
        {
            notas[i] = nd.getNotas(i);
        }
    }
    
    // método para calcular el promedio 
    public float promedio()
    {
        float suma = 0;
        for (int i = 0; i < 3; i++)
        {
            suma += getNotas(i);
        }
        return suma/3;
    }
}

public class Lista
{
    // se declara un atributo privado de tipo Nodo llamado cabeza 
    private Nodo cabeza;
    
    public Lista()
    {
        // le asignamos un valor por defecto al atributo de la clase en el constructor 
        cabeza = null;
    }
    
    // método set y get del atributo de la clase 
    public void setCabeza(Nodo n)
    {
        cabeza = n;
    }
    
    public Nodo getCabeza()
    {
        return cabeza;
    }
    
    // método para validar si un ID no se ha repetido 
    public boolean validarId(int c)
    {
        // se inicializa una variable de tipo Nodo y se le asigna la cabeza 
        Nodo temp = cabeza;
        // se inicializa una variable de tipo booleana y se le asigna false 
        boolean igual = false;
        // mientras haya un nodo en la lista 
        while(temp != null)
        {
            // si el id del nodo temporal es igual al valor de la variable c pasada como parametro 
            if(temp.getId() == c)
            {
                // entonces se le asigna a igual el valor de true 
                igual = true;
                // se rompe el ciclo 
                break;
            }
            // se salta al siguiente nodo de temp 
            temp = temp.getSiguiente();
        }
        // se retorna el valor de la variable igual 
        return igual;
    }
    
    // método para retornar el ultimo nodo de la lista 
    public Nodo ultimo()
    {
        // se inicializa una variable de tipo Nodo en la cabeza 
        Nodo temp = cabeza;
        // mientras haya un nodo en la lista 
        while(temp != null)
        {
            // entonces, si el siguiente nodo de temp es igual a null 
            if (temp.getSiguiente() == null)
            {
                // entonces, se rompe el ciclo 
                break; 
            }
            else
            {
                // sino, se salta al siguiente nodo del temp 
                temp = temp.getSiguiente(); 
            }
        }
        // se retorna el nodo temp 
        return temp; 
    }
    
    // método para contar los nodos de la lista 
    public int contarNodos()
    {
        // se inicializa la variable de tipo Nodo temp en la cabeza 
        Nodo temp = cabeza;
        // se inicializa la variable de tipo entero contador en 0 
        int contador = 0;
        // mientras haya un nodo en la lista 
        while(temp != null)
        {
            // se incrementara la variable contador 
            contador++;
            // y se salta al siguiente nodo de temp 
            temp = temp.getSiguiente();
        }
        // se retorna el valor de la variable contador 
        return contador;
    }
    
    // método para agregar nodos por el final 
    public void agregarFinal(Nodo n)
    {
        // si la cabeza es igual a null 
        if(cabeza == null)
        {
            // entonces la la cabeza ahora sera el nodo n 
            setCabeza(n);
        }
        else
        {
            // sino el ultimo nodo apuntara al nodo n 
            ultimo().setSiguiente(n);
        }
    }
    
    // método para buscar por ID 
    Nodo buscarId(int c)
    {
        // se inicializa la variable de tipo Nodo temp en la cabeza 
        Nodo temp = cabeza;
        // mientras haya un nodo en la lista 
        while(temp != null)
        {
            // si el id del nodo actual es igual al valor de la variable c pasada como parametro 
            if(temp.getId() == c)
            {
                // se rompe el ciclo 
                break;
            }
            // se salta al siguiente nodo de temp 
            temp = temp.getSiguiente();
        }
        // se retorna el nodo temp 
        return temp;
    }
    
    // método para ordenar ascendentemente 
    public void ordenarAscendentemente(Nodo n)
    {
        // se declaran dos variables de tipo Nodo 
        Nodo actual, siguiente;
        // se le asigna a la variable actual el valor de n 
        actual = n;
        // mientras el siguiente nodo del nodo actual sea diferente a null 
        while(actual.getSiguiente() != null)
        {
            // el nodo siguiente saltara al siguiente nodo del nodo actual 
            siguiente = actual.getSiguiente();
            // mientras el nodo siguiente sea diferente a null 
            while(siguiente != null)
            {
                // si el semestre del nodo actual es mayor al semestre del nodo siguiente 
                if(actual.getSemestre() > siguiente.getSemestre())
                {
                    // entonces se cambiara al nodo actual con el siguiente 
                    cambiar(actual, siguiente);
                }
                // el nodo siguiente saltara a su siguiente nodo 
                siguiente = siguiente.getSiguiente();
            }
            // el nodo actual saltara a su siguiente nodo 
            actual = actual.getSiguiente();
        }
    }
    
    // método para ordenar descendentemente 
    public void ordenarDescendentemente(Nodo n)
    {
        // se declaran dos variables de tipo Nodo 
        Nodo actual, siguiente;
        // se le asigna a la variable actual el valor de n 
        actual = n;
        // mientras el siguiente nodo del nodo actual sea diferente a null 
        while(actual.getSiguiente() != null)
        {
            // el nodo siguiente saltara al siguiente nodo del nodo actual 
            siguiente = actual.getSiguiente();
            // mientras el nodo siguiente sea diferente a null 
            while(siguiente != null)
            {
                // si el semestre del nodo actual es menor al semestre del nodo siguiente 
                if(actual.getSemestre() < siguiente.getSemestre())
                {
                    // entonces se cambiara al nodo actual con el siguiente 
                    cambiar(actual, siguiente);
                }
                // el nodo siguiente saltara a su siguiente nodo 
                siguiente = siguiente.getSiguiente();
            }
            // el nodo actual saltara a su siguiente nodo 
            actual = actual.getSiguiente();
        }
    }
    
    // método para cambiar los nodos 
    public void cambiar(Nodo p1, Nodo p2)
    {
        // creo un nuevo nodo para poder realizar la copia 
        Nodo temp = new Nodo();
        // le asigno al nodo temp los datos del nodo actual (p1) 
        temp.copiar(p1);
        // le asigno al nodo p1 los datos del nodo siguiente (p2) 
        p1.copiar(p2);
        // le asigno al nodo p2 los datos del temp 
        p2.copiar(temp);
    }
    
    // método para calcular el promedio general 
    public float promedioGeneral()
    {
        // se inicializa la variable de tipo Nodo temp en la cabeza 
        Nodo temp = cabeza;
        // se inicializa una variable de tipo float en 0 
        float suma = 0;
        // mientras haya un nodo en la lista 
        while(temp != null)
        {
            // se le acumulara a la variable suma el valor de suma mas el valor del promedio del nodo temp 
            suma += temp.promedio();
            // se salta al siguiente nodo de temp 
            temp = temp.getSiguiente();
        }
        // se retorna el valor de la variable suma entre el total de nodos 
        return suma/contarNodos();
    }
    
    // método para eliminar nodo 
    public void eliminar(Nodo n)
    {
        // se declara una variable de tipo Nodo llamada anterior 
        Nodo anterior;
        // si promedio del nodo n es igual al promedio general 
        if(n.promedio() == promedioGeneral())
        {
            // si el nodo nd es igual a la cabeza 
            if(n  == cabeza)
            {
                // entonces, la cabeza saltara a su siguiente (saltaria a null) 
                cabeza = cabeza.getSiguiente();
            }
            else
            {
                // sino, el nodo anterior tendra el valor de la cabeza 
                anterior = cabeza;
                // mientras el siguiente nodo del anterior sea difente al nodo nd 
                while(anterior.getSiguiente() != n)
                {
                    // entonces se salta al siguiente nodo del anterior 
                    anterior = anterior.getSiguiente();
                }
                // el siguiente del anterior ahora sera el siguiente nodo de nd 
                anterior.setSiguiente(n.getSiguiente());
            }
            // el anterior del siguiente nodo de nd ahora sera el nodo anterior 
            n.setSiguiente(null);
        }
    }
    
    // método para limpiar toda la lista 
    public void limpiar()
    {
        // mientras haya un nodo en la lista 
        while(cabeza != null)
        {
            // se elimina la cabeza 
            eliminar(cabeza);
        }
    }
}