Estructuras con Punteros

10. Ejemplo integrador

//     EJEMPLO DE LISTA ENLAZADA SIMPLE      //
//     ================================      //
// Se agregan instancias de a una dinámicamente.
// Se eliminan de a una.
// Ing. Germán Andrés Xander 2018.

#include<iostream>
using namespace std;

struct data{
    int orden;
    struct data *pprox;
};

void agregar_final(data *&pt);
void agregar_principio(data *&pt);
void listar(data *pt);
void eliminar_final(data *&pt)
void eliminar_principio(data *&pt);

int main() {
    char opcion;
    data *lista=NULL;            //creo el puntero en main()
    do{
        cout<<"\t a para agregar al final"<<endl
            <<"\t A para agregar al principio"<<endl
            <<"\t l para listar"<<endl
            <<"\t e para eliminar del final"<<endl
            <<"\t E para eliminar del principio"<<endl;
        cin>>opcion;
        switch(opcion){
            case 'a':
                agregar_final(lista);
                break;
            case 'A':
                agregar_principio(lista);
                break;
            case 'l':
                listar(lista);
                break;
            case 'e':
                eliminar_final(lista);
                break;
            case 'E':
                eliminar_principio(lista);
                break;
        }
    }while(opcion!='s');
    return 0;
}

void agregar_final(data *&pt){            //paso por referencia para poder modificar "a dónde apunta"
    if(!pt){                    //la primer vez el puntero es NULL y evalua por true.
                                //"...the null pointer is implicitly converted into boolean false
                                //while non-null pointers are converted into true..."
        pt=new data;            //para la primer instancia debo modificar "a dónde apunta" el puntero original (lista)
        cout<<"ingrese orden"<<endl;
        cin>>pt->orden;
        pt->pprox=NULL;
    }else{                        // para las instancia posteriores debo trabajar sobre una copia del puntero
        data *pt2=pt;            // para no perder la dirección de la 1er instancia
        while(pt2->pprox!=0){        //me posiciono en la última instancia
            pt2=pt2->pprox;
        }
        pt2->pprox=new data;        //solicito una nueva instancia y asigno la dirección en el puntero al prox de la última
        cout<<"ingrese orden"<<endl;
        cin>>pt2->pprox->orden;
        pt2->pprox->pprox=NULL;
    }
}

void agregar_principio(data *&pt){            //paso por referencia para poder modificar "a dónde apunta"
    if(!pt){                    //la primer vez el puntero es NULL y evalua por false.
                                //"...the null pointer is implicitly converted into boolean false
                                //while non-null pointers are converted into true..."
        pt=new data;            //para la primer instancia debo modificar "a dónde apunta" el puntero original (lista)
        cout<<"ingrese orden"<<endl;
        cin>>pt->orden;
        pt->pprox=NULL;
    }else{
        data *pt2=pt;            // para no perder la dirección de la, hasta ahora, 1er instancia
        pt=new data;            //solicito una nueva instancia y asigno la dirección al puntero original
        cout<<"ingrese orden"<<endl;
        cin>>pt->orden;
        pt->pprox=pt2;            // apunto a la antigua 1ra instancia
    }
}

void listar(data *pt){  //como no pasa por referencia no se alterar el original
    while(pt!=0){
        cout<<"orden: "<<pt->orden<<"\t dirección al próximo: "<<pt->pprox<<endl;
        pt=pt->pprox;
    }
    cout<<endl<<endl;
}

void eliminar_final(data *&pt){
    data *pt2=pt,*pt3=pt;
    if(!pt){
        cout<<"no hay instancias"<<endl;
    }else{
        while(pt2->pprox!=0){        //me posiciono en la última instancia
            pt3=pt2;
            pt2=pt2->pprox;
        }
        if(pt2==pt3){             //nunca entro al while anterior. es la última
            delete pt;            //libero la memoria original
            pt=NULL;              //para saber que ya no apunta a memoria mía
            cout<<"ya no quedan instancias"<<endl<<endl;
        }else{
            delete pt2;
            pt3->pprox=NULL;
        }
    }
}

void eliminar_principio(data *&pt){
    data *pt2=pt;
    if(!pt){
        cout<<"no hay instancias"<<endl;
    }else{
        if(pt->pprox!=0){        //no es la última instancia
            pt2=pt->pprox;
            delete pt;
            pt=pt2;
        }else{
            delete pt;            //libero la memoria original
            pt=NULL;            //para saber que ya no apunta a memoria mía
            cout<<"ya no quedan instancias"<<endl<<endl;
        }
    }
}