[C con Clase] Ayuda con Listas simplemente ligadas

Elois@ Guevara elo_mentemaestra en hotmail.com
Mar Sep 18 07:06:32 CEST 2012


Hola, tengo un problema. Es una tarea de la unversidad. Me piden hacer un
programa con listas ligadas que permita agregar información de Recorridos y
lugares, debe existir una lista de lugares y una lista de recorridos, todo
esto lo implementé con nodos.
Despues cada recorrido debe visitar por lo menos un lugar (o más) esto debe
poder agregarlo el usuario y visualizar en un menú. Solo que no se como
insertar una referencia a cada lugar de la lista en el nodo del recorrido
(será con puteros dobles?). Tengo prohibido usar arreglos, todo debe
hacerse con memoria dinámica. Gracias de antemano por leer esto.
 Este es mi código:

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <windows.h>
using namespace std;

typedef int tipoDato;

// Estructura principal para Lugares
typedef struct NodoLugar
{
    char* nombre;
    char* ubicacion;
    struct NodoLugar* siguiente;     // Referencia al siguiente elemento

}NodoLugar;

NodoLugar* inicioL;

// Estructura para guardar la información de los recorridos
typedef struct NodoRecorrido{
    char* guia;
    int numPersonas;
    NodoLugar* lugaresVisita;
    struct NodoRecorrido* siguiente;

}NodoRecorrido;


NodoRecorrido* inicioR;

// Función para mostrar el menu principal de opciones
int Menu();
//
int SubMenu();
// Función para hacer una pausa en la pantalla
void Pausa();

//********** Funciones para lugares **************************

// Función para insertar un nuevo Lugar en la lista de lugares
void InsertarLugar(NodoLugar**, char*, char*);
// Función para eliminar un Lugar de la lista de lugares
bool EliminarLugar(NodoLugar**, char*);
// Función para mostrar la lista de Lugares
void MostrarLugar(NodoLugar**);
// Función para verificar si la lista de lugares está vacía
bool ListaVacia(NodoLugar**);
//
bool BuscarLugar(NodoLugar**, char*);

//********** Funciones para recorridos **************************

// Función para insertar un nuevo Recorrido en la lista de recorridos
void InsertarRecorrido(NodoRecorrido**, char*, int, NodoLugar*
lugaresVisita);
// Función para eliminar un Recorrido de la lista de recorridos
bool EliminarRecorrido(NodoRecorrido**, char*);
// Función para mostrar la lista de recorridos
void MostrarRecorrido(NodoRecorrido**);
// Función para verificar si la lista de recorridos está vacía
bool ListaRecVacia(NodoRecorrido**);

// ***************** Función main ******************
int main()
{
    int opc=0, o=0;

    // Datos de lugar
    char* nombre;
    char* ubicacion;

    // Datos de recorrido
    char* guia;
    int numPersonas;
    NodoLugar* lugaresVisita;

    // Es necesario inicializar el "inicio" de ambas listas en NULL ya que
al comienzo del programa están vacías
    inicioL=NULL;
    inicioR=NULL;

    do
    {

        opc=Menu();

        switch(opc)
        {
            case 1:
                do{
                    o=SubMenu();
                    }while(o < 1 || o > 2);
                if(o == 1)
                {
                cout << "   Nombre del lugar: ";
                nombre=(char*)malloc(sizeof(char)*20);
                fflush(stdin);
                gets(nombre);
                cout << "   Ubicacion del lugar: ";
                ubicacion=(char*)malloc(sizeof(char)*50);
                fflush(stdin);
                gets(ubicacion);
                InsertarLugar(&inicioL, nombre, ubicacion);
                }

                else
                {
                    if(!&inicioL)
                    {
                        cout<<"\n   Lista de lugares vacia, para agregar un
recorrido\ndebe existir por lo menos un lugar en la lista...\n";
                        break;
                    }
                cout << "   Nombre del guia: ";
                guia=(char*)malloc(sizeof(char)*30);
                fflush(stdin);
                gets(guia);
                cout << "   Numero de personas: ";
                cin >> numPersonas;
                InsertarRecorrido(&inicioR, guia, numPersonas, inicioL);
                }
                break;

            case 2:
                do{
                    o=SubMenu();
                    }while(o < 1 || o > 2);
                if(o == 1)
                {
                    cout << "   Nombre del lugar: ";
                    nombre=(char*)malloc(sizeof(char)*20);
                    fflush(stdin);
                    gets(nombre);
                    EliminarLugar(&inicioL, nombre);
                }

                else
                {
                    cout << "   Nombre del guia: ";
                    guia=(char*)malloc(sizeof(char)*30);
                    fflush(stdin);
                    gets(guia);
                    cout << "   Numero de personas: ";
                    cin >> numPersonas;
                    EliminarRecorrido(&inicioR, guia);
                }
                break;

            case 3:
                do{
                    o=SubMenu();
                    }while(o < 1 || o > 2);
                if(o == 1)
                {
                    cout<<"\n   Lista de lugares: \n";
                    MostrarLugar(&inicioL); Pausa();
                }

                else
                {
                    cout<<"\n   Lista de recorridos: \n";
                    MostrarRecorrido(&inicioR); Pausa();
                }
                break;

            case 5:
                break;

            case 0:
                exit(0);
                break;

            default:
                cout << "\a\n   Opcion invalida!...";
                Sleep(800);
                break;
        }

    }while(opc != 0);

    return 0;
}

// Menu de opciones
int Menu()
{
    int opcion;
    system("cls"); system("COLOR 4F");
    cout << "\n     === Recorridos ===\n\n";
    cout << "   1. Insertar\n";
    cout << "   2. Eliminar\n";
    cout << "   3. Mostrar\n";
    cout << "   4. Buscar\n";
    cout << "   5. Instrucciones\n";
    cout << "\t\tOpcion o presione 0 para salir: ";
    /*
    Especificaciones que faltan
    Insertar lugares si repetir (Crear funcion que busque lugar por nombre
*)
    Modificar numero de personas (Funcion que muestre la lista con # y
pregunte el numero de nodo
    Modificar nombre del guia (Funcion que muestre la lista con # y
pregunte el numero de nodo busque ese nodo y cambie
    Buscar los recorridos que van a un mismo lugar
    Buscar los lugares de un recorrido
    */
    cin >> opcion;
    system("cls");
    return opcion;
}

int SubMenu()
{
    int opc;
    system("CLS");
    cout << "\n  1. Lugar\n";
    cout << "  2. Recorrido\n";
    cout << "\tOpcion: ";
    cin >> opc;
    system("CLS");
    return opc;
}

void Pausa()
{
    cout << "\a\n   Presione una tecla para continuar...";
    fflush(stdin);
    getchar();
}

bool ListaVacia(NodoLugar** nodo)
{
    if(nodo == NULL)
        return true;
    return false;
}

void InsertarLugar(NodoLugar** lista , char* nombre, char* ubicacion)
{
    // Reservar memoria para insertar el nuevo nodo
    NodoLugar* nuevoNodo=(NodoLugar*)malloc(sizeof(NodoLugar));

    //Si la memoria no es suficiente, salir de la función
    if(nuevoNodo == NULL)
        return;

    // Reservar memoria para la nueva informacion
    nuevoNodo->nombre=(char*)malloc(sizeof(char)*20);
    nuevoNodo->ubicacion=(char*)malloc(sizeof(char)*30);

    // Introducir la información en el nuevo nodo
    // strcpy(destino,fuente)

    strcpy(nuevoNodo->nombre, nombre);
    strcpy(nuevoNodo->ubicacion, ubicacion);

    //Verificar cuando la lista está vacía
    if(ListaVacia(lista) == true)
        // Si está vacía, el nuevo nodo apunta al inicio
        nuevoNodo->siguiente = (*lista);

    else
        // Si no, hacer que el nuevo nodo apunte al siguiente elemento de
la lista
        nuevoNodo->siguiente= (*lista);

    // Finalmente, el apuntador al ultimo elemento insertado es el nuevo
nodo
    (*lista) = nuevoNodo;
    cout<< "\n   El dato ha sido insertado correctamente..."; Sleep(800);

}

bool EliminarLugar(NodoLugar** inicioLista, char* nombre)
{
    // * Caso 1: Si la lista está vacía, salir de la función
    if(ListaVacia(inicioLista)==true)
        return false;

    // Variable auxiliar tipo apuntador a Nodo, requiere recibir la
posición del primer elemento de la lista
    NodoLugar* auxEliminar=(*inicioLista);

    // * Caso 2: Comparar si el dato insertado por el usuario es igual al
primer dato de la lista
    if(strcmp(auxEliminar->nombre, nombre) == 0)
    {
        // Si es verdadero, recorrer el apuntador al inicio de la lista al
siguiente elemento
        (*inicioLista)=(*inicioLista)->siguiente;

        // Liberar la memoria del auxiliar
        free(auxEliminar);

        // Retornar verdadero porque el nodo se eliminó correctamente
        return true;
    }

    // * Caso 3: Si sólo hay un dato en la lista y no está el dato buscado
    if (auxEliminar->siguiente == NULL)
        return false;

    // * Caso 4: El elemento puede estar en el resto de la lista

    // Variable auxiliar tipo apuntador a Nodo, para guardar la posición
anterior al nodo que se va a eliminar
    NodoLugar* anterior= (*inicioLista);

    // Recorrer el apuntador auxEliminar a la siguiente posición
    auxEliminar=(*inicioLista)->siguiente;

    // Buscar en el resto de la lista mientras no se encuentre el elemento
y la lista no se acabe
    while(strcmp(auxEliminar->nombre, nombre) != 0 && auxEliminar != NULL)
    {
        // Si ya no hay más nodos, asignar NULL al auxEliminar
        if(auxEliminar->siguiente == NULL)
            auxEliminar = NULL;
        // Si aun hay nodos, recorrer el auxiliar al siguiente nodo
        else
            auxEliminar = auxEliminar->siguiente;

        // Recorrer el auxiliar que guarda la posición anterior al nodo que
se va a eliminar al siguiente nodo
        anterior = anterior->siguiente;
    }

    // Si auxEliminar no es nulo, se encontró el dato
    if(auxEliminar != NULL)
    {
        // Si el dato es el último de la lista, asignar NULL al siguiente
nodo
        if(auxEliminar->siguiente == NULL)
            anterior->siguiente = NULL;
        // Si no, el dato no es el ultimo,
        else
            anterior->siguiente = auxEliminar->siguiente;

        // Liberar memoria de auxEliminar, se pierde la referencia
        free(auxEliminar);

        // Retornar verdadero ya que el dato se eliminó correctamente
        return true;
    }

    // Retornar falso ya que auxEliminar es NULL, entonces el dato no está
en la lista
    return false;
}


void MostrarLugar(NodoLugar** inicioLista)
{
    // Indice para contar los elementos de la lista que se han mostrado
    int i=0;

    // Variable tipo apuntador auxiliar a Nodo para recorrer la lista
    NodoLugar* auxVer=(*inicioLista);

    // Si la lista está vacía muestra un mensaje.
    if(auxVer==NULL)
        cout << "\n\t\aLista vacia!...\n";

    // Mientras la lista no esté vacía
    while( auxVer != NULL)
    {
        // Incrementa el contador
        i++;

        // Muestra los datos
        cout<<"\t"<<i<<".- Nombre: "<<auxVer->nombre;
        cout<<"\tUbicacion: "<<auxVer->ubicacion<<endl;
        // Si la lista está vacía, asignar nulo al auxiliar para cerrar el
ciclo while
        if(auxVer == NULL)
            auxVer = NULL;
        // Si no, recorrer el apuntador auxiliar a la posición del
siguiente elemento para continuar mostrando
        else
            auxVer = auxVer->siguiente;
    }

     cout<<"\n\t\aFin de registros...\n"<<"\tTotal: "<<i<<endl;
}

bool BuscarLugar(NodoLugar** inicioLista, char* nombre)
{


    int i=0;
    NodoLugar* anterior;
    NodoLugar* auxBusca=(*inicioLista);

    if(auxBusca==NULL)
    {
    cout<<"\a\n   Lista vacia!...\n"; Sleep(700);
    return false;
    }

    while(auxBusca != NULL )
    {
        i++;
        if( strcmp(auxBusca->nombre,nombre)==0)
        {
            cout<<"\n   El lugar buscado se encuentra en el nodo "<<i<<endl;
            return true;
        }
        else
        {
        anterior=auxBusca;
        if(auxBusca == NULL)
            auxBusca=NULL;
        else
            auxBusca=auxBusca->siguiente;
        }

    }

    cout<<"\n\n\a   El lugar no se encuentra en la lista...\n";
 Sleep(800);
    return false;
}


 ////////////////////////////////////////////////


 bool ListaRecVacia(NodoRecorrido** nodoR)
{
    if(nodoR == NULL)
        return true;
    return false;
}

void InsertarRecorrido(NodoRecorrido** lista , char* guia, int numPersonas,
NodoLugar* lugaresVisita)
{
    // Reservar memoria para insertar el nuevo nodo
    NodoRecorrido* nuevoNodo=(NodoRecorrido*)malloc(sizeof(NodoRecorrido));

    //Si la memoria no es suficiente, salir de la función
    if(nuevoNodo == NULL)
        return;

    nuevoNodo->guia= (char*)malloc(sizeof(char)*30);

    // Introducir la información en el nuevo nodo
    // strcpy(destino,fuente)
    strcpy(nuevoNodo->guia, guia);
    nuevoNodo->numPersonas = numPersonas;
    nuevoNodo->lugaresVisita = NULL;

    //Verificar cuando la lista está vacía
    if(ListaRecVacia(lista) == true)
        // Si está vacía, el nuevo nodo apunta al inicio
        nuevoNodo->siguiente = (*lista);

    else
        // Si no, hacer que el nuevo nodo apunte al siguiente elemento de
la lista
        nuevoNodo->siguiente= (*lista);

    // Finalmente, el apuntador al ultimo elemento insertado es el nuevo
nodo
    (*lista) = nuevoNodo;
    cout<< "\n   El dato ha sido insertado correctamente..."; Sleep(800);

}

bool EliminarRecorrido(NodoRecorrido** inicioLista, char* guia)
{
    // * Caso 1: Si la lista está vacía, salir de la función
    if(ListaRecVacia(inicioLista)==true)
        return false;

    // Variable auxiliar tipo apuntador a Nodo, requiere recibir la
posición del primer elemento de la lista
    NodoRecorrido* auxEliminar=(*inicioLista);

    // * Caso 2: Comparar si el dato insertado por el usuario es igual al
primer dato de la lista
    if(strcmp(auxEliminar->guia, guia) == 0)
    {
        // Si es verdadero, recorrer el apuntador al inicio de la lista al
siguiente elemento
        (*inicioLista)=(*inicioLista)->siguiente;

        // Liberar la memoria del auxiliar
        free(auxEliminar);

        // Retornar verdadero porque el nodo se eliminó correctamente
        return true;
    }

    // * Caso 3: Si sólo hay un dato en la lista y no está el dato buscado
    if (auxEliminar->siguiente == NULL)
        return false;

    // * Caso 4: El elemento puede estar en el resto de la lista

    // Variable auxiliar tipo apuntador a Nodo, para guardar la posición
anterior al nodo que se va a eliminar
    NodoRecorrido* anterior= (*inicioLista);

    // Recorrer el apuntador auxEliminar a la siguiente posición
    auxEliminar=(*inicioLista)->siguiente;

    // Buscar en el resto de la lista mientras no se encuentre el elemento
y la lista no se acabe
    while(strcmp(auxEliminar->guia, guia) != 0 && auxEliminar != NULL)
    {
        // Si ya no hay más nodos, asignar NULL al auxEliminar
        if(auxEliminar->siguiente == NULL)
            auxEliminar = NULL;
        // Si aun hay nodos, recorrer el auxiliar al siguiente nodo
        else
            auxEliminar = auxEliminar->siguiente;

        // Recorrer el auxiliar que guarda la posición anterior al nodo que
se va a eliminar al siguiente nodo
        anterior = anterior->siguiente;
    }

    // Si auxEliminar no es nulo, se encontró el dato
    if(auxEliminar != NULL)
    {
        // Si el dato es el último de la lista, asignar NULL al siguiente
nodo
        if(auxEliminar->siguiente == NULL)
            anterior->siguiente = NULL;
        // Si no, el dato no es el ultimo,
        else
            anterior->siguiente = auxEliminar->siguiente;

        // Liberar memoria de auxEliminar, se pierde la referencia
        free(auxEliminar);

        // Retornar verdadero ya que el dato se eliminó correctamente
        return true;
    }

    // Retornar falso ya que auxEliminar es NULL, entonces el dato no está
en la lista
    return false;
}


void MostrarRecorrido(NodoRecorrido** inicioLista)
{
    // Indice para contar los elementos de la lista que se han mostrado
    int i=0;

    // Variable tipo apuntador auxiliar a Nodo para recorrer la lista
    NodoRecorrido* auxVer=(*inicioLista);

    // Si la lista está vacía muestra un mensaje.
    if(auxVer==NULL)
        cout << "\n\t\aLista vacia!...\n";

    // Mientras la lista no esté vacía
    while( auxVer != NULL)
    {
        // Incrementa el contador
        i++;

        // Muestra los datos
        cout<<"\t"<<i<<".- Nombre del guia: "<<auxVer->guia;
        cout<<"\tNumero de personas: "<<auxVer->numPersonas<<endl;
        // Si la lista está vacía, asignar nulo al auxiliar para cerrar el
ciclo while
        if(auxVer == NULL)
            auxVer = NULL;
        // Si no, recorrer el apuntador auxiliar a la posición del
siguiente elemento para continuar mostrando
        else
            auxVer = auxVer->siguiente;
    }

     cout<<"\n\t\aFin de registros...\n"<<"\tTotal: "<<i<<endl;
}
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20120918/4a8894f8/attachment.html>


Más información sobre la lista de distribución Cconclase