3

estoy diseñando un programa en C++ con pila dinamica pero al momento de extraer los datos quiero que lo haga de forma invertida, me pueden ayudar. Este es mi codigo:

#include <iostream>
using namespace std;
#define true 1
#define false 0

    struct docentes{
        char nom [10],ap[10],ced[10];
        float s;
    };
    typedef struct pila{
docentes d;
pila *sgte;
 }p;
 typedef pila *pila1;
 typedef pila *pila2;
 void ingresar(pila1 *p1, docentes d);
 docentes extraer(pila1 *p1);
 void mostrar(pila1 *p1);
 void veriifcar(pila1 *p1);
 int main(){
 pila1 pila_nueva=NULL;
 int op;
 docentes d,x;
do{
    cout<<"eliga una opcion"<<endl;
    cout<<"1.ingresar"<<endl;
    cout<<"2.extraer"<<endl;
    cout<<"3.mostrar"<<endl;
    cout<<"4.verificar"<<endl;
    cin>>op;
    switch(op){
        case 1:{
            cout<<"ingrese nombre"<<endl;
            cin>>d.nom;
            cout<<"apellido"<<endl;
            cin>>d.ap;
            cout<<"cedula"<<endl;
            cin>>d.ced;
            cout<<"sueldo :"<<endl;
            cin>>d.s;
            ingresar(&pila_nueva,d);
            break;
        }
        case 2:{
            x=extraer(&pila_nueva);
            if(pila_nueva!=NULL){
                cout<<"extrayendo datos"<<endl;
                cout<<"nombre"<<x.nom<<endl;
                cout<<"apellido"<<x.ap<<endl;
                cout<<"cedula"<<x.ced<<endl;
                cout<<"sueldo"<<x.s<<endl;
            }
            else{
                cout<<"pila vacia"<<endl;
            }
            break;
        }
        case 3:{
            mostrar(&pila_nueva);
            break;
        }
        case 4:{
            if(pila_nueva!=NULL){
                cout<<"la pila contiene elementos";
            }
            else{
                cout<<"pila vacia";
            }
            break;
        }
        default:{
            cout<<"opcion invalida";
            break;
        }
    }
}while(op!=5);
return 0;
}
void ingresar(pila1 *p1, docentes d){
pila1 aux;
aux=new(pila);
aux->d=d;
aux->sgte;
*p1=aux;
}
docentes extraer(pila1 *p1){
pila2 aux;
docentes doc;
aux=*p1;
if(!aux){
    return doc;
}
*p1=aux->sgte;
doc=aux->d;
delete(aux);
return doc;
}
void mostrar(pila1 *p1){
}
void veriifcar(pila1 *p1){
}
PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82
Joni
  • 67
  • 6

2 Answers2

3

estoy diseñando un programa en C++

Entonces te sugiero usar la sintaxis propia de C++:

  • true y false ya existen en C++, no hay que redeclararlos. Tienes disponible el tipo bool

    // Lineas comentadas:
    // #define true 1
    // #define false 0
    
  • No es necesario usar typedef con las estructuras

    struct pila{
      docentes d;
      pila *sgte;
    };
    
    pila pilaA, pilaB;
    
  • Tabula el código correcmtamente: con esto consigues que sea legible por los seres humanos. También sería de agradecer que hubiese saltos de línea antes de empezar las funciones:

    // Ilegible
    void mostrar(pila1 *p1);
    void veriifcar(pila1 *p1);
    int main(){
    pila1 pila_nueva=NULL;
    int op;
    
    // Legible
    void mostrar(pila1 *p1);
    void veriifcar(pila1 *p1);
    
    int main(){
      pila1 pila_nueva=NULL;
      int op;
    
  • No es lo mismo una pila que un nodo. Más información: Asignación de punteros en listas enlazadas:

    struct Nodo
    {
      Nodo* sgte;
      docentes data;
    };
    
    class Pila
    {
      Nodo* front;
    };
    
  • C++ es un lenguaje orientado a objetos. Esto quiere decir que las estructuras y clases, a diferencia de C, pueden tener propiedades y métodos. No es necesario tener funciones libres todo el rato:

    class Pila
    {
      Nodo* front;
    
    public:
      void Ingresar(docentes d);
      docentes Extraer();
      // ...
    };
    
    void Pila::Ingresar(docentes d)
    {
      // ...
    }
    

al momento de extraer los datos quiero que lo haga de forma invertida

Has programado una pila LIFO y, por lo que se entiende, pretendes que funcione como una FIFO.

Para cambiar el formato tienes que atacar el ingreso de valores... ahora, en vez de almacenar los nuevos elementos al principio tienes que ingresarlos al final:

struct Nodo
{
  Nodo* sgte;
  docentes data;

  Nodo(docentes d)
    : sgte(nullptr), data(d)
  { }
};

class Pila
{
  Nodo* front;
  Nodo* back; // <<--- Puntero al ultimo nodo

public:
  Pila()
    : front(nullptr), back(nullptr)
  { }

  ~Pila()
  {
    while( front != nullptr )
    {
      Nodo* temp = front;
      front = front->sgte;
      delete temp;
    }
  }

  void Ingresar(docentes d);
};

void Pila::Ingresar(docentes d)
{
  Nodo* nodo = new Nodo(d);
  if( front == nullptr )
  {
    front = nodo;
    back = nodo;
  }
  else
  {
    back->sgte = nodo;
    back = nodo;
  }
}

¿Y no se puede, simplemente, extraer los nodos en orden inverso?

No, para ello necesitarías una lista doblemente enlazada. Dado que cada nodo solo conoce al nodo que le sigue la lista solo puede ser recorrida en orden directo... nunca en inverso.

eferion
  • 49,291
  • 5
  • 30
  • 72
1

Estoy diseñando un programa en C++ con pila dinámica pero al momento de extraer los datos quiero que lo haga de forma invertida.

Pues no uses una pila. En una pila el orden de los datos es dependiente del orden en que fueron insertados, si es una pila de tipo FIFO apilas por encima y desapilas por debajo y si es LIFO apilas y desapilas por encima.

Detalles a tener en cuenta.

  • C++ dispone de un tipo de datos para variables booleanas: bool, que sólo puede obtener los valores true o false, así que no debes usar macros para definir esos símbolos.
  • En C++ la palabra clave struct no forma parte del tipo, así pues no es necesaria para definir variables de tipo struct (no necesitas hacer typedef struct nombre {} alias;).
  • No hay obligación de usar la cláusula using namespace std; pues es sólo es una ayuda a la escritura de código; si decides usar esta cláusula no lo hagas en el ámbito global, úsala en el ámbito más pequeño posible. Lee este hilo para saber por qué.
  • La manera de trabajar con cadenas de caracteres en C++ es usando objetos de tipo std::string (accesibles tras incluir la cabecera <string>) no con formaciones1 de caracteres.

La nomenclatura es importante.

Las variables deben tener un nombre que ayude, de un vistazo, a definir su cometido dentro del programa; nombres como p, d, x, p1, p2, op, pila1, pila2 son confusos.

Además el tipo docentes está en plural, dando a entender que contiene más de un dato, pero al examinarlo se ve que contiene información de un solo docente (no varios) con lo que el plural da una idea incorrecta del tipo.

Por otro lado, la palabra clave typedef se usa para definir alias de tipos ¿Qué sentido tiene definir dos alias diferentes para el mismo tipo?:

typedef pila *pila1;
typedef pila *pila2;

Para acabar, parece que trabajas con un tipo de dato llamado pila pero no tienes ninguna operación de apilar o desapilar, supongo que las operaciones de ingresar y extraer son los equivalentes de push y pop de una pila.

Los Nodos no son Listas.

Este es un error recurrente en StackOverflow en Español que genera mucha confusión.

En el código que has facilitado estás usando los nodos de tu pila como si fuesen la pila en si y eso es tan erróneo como decir que un escalón es una escalera, sinceramente ¿Te parecen lo mismo?:

Tu pregunta es sobre C++.

El lenguaje C++ es multiparadigma, así que a priori no estás limitado a un paradigma concreto; pero uno de los puntos fuertes del lenguaje es su soporte a la programación orientada a objetos así que te aconsejo que realmente crees un objeto lista en lugar de confiar en funciones sueltas.

Propuesta.

Teniendo en cuenta todo lo mencionado anteriormente, tu código podría tener este aspecto:

struct docentes{
    std::string nombre, apellido, cedula;
    float sueldo;
};

class pila{
    struct nodo{
        docente dato;
        nodo *siguiente = nullptr;
    };

    nodo *raiz = nullptr;

public:
    void ingresar(docente d);
    docente extraer();
    docente extraer_del_final();
    void mostrar();
    void veriifcar();
};

La clase pila dispone de un tipo interno en la zona privada que es el node; este tipo es inaccesible desde fuera favoreciendo el encapsulamiento: la propia clase gestiona sus nodos, desde fuera de la lista no hay motivos para trabajar con nodos, las funciones ya no reciben un puntero a pila por ese motivo.

Operación invertida.

Insisto en que no tiene ningún sentido desapilar datos del fondo de la pila, así que seguramente no quieres trabajar con pilas. Pero si quieres hacer esa operación tendrás que recorrer toda la pila hasta el final, devolver el dato allí almacenado y reenlazar el penúltimo nodo. Así que partiendo desde pila::raiz

docente pila::extraer_del_final()
{
    nodo *penultimo = nullptr;

    // Avanzar los nodos mientras el nodo actual tenga valor y...
    // mientras el nodo siguiente al actual tenga valor y...
    // mientras el nodo siguiente al siguiente al actual tenga valor.
    for (nodo *n = raíz; n && n->siguiente && n->siguiente->siguiente; n = n->siguiente)
        penultimo = n;

    auto resultado = penultimo->siguiente->dato;

    delete penultimo->siguiente;
    penultimo->siguiente = nullptr;

    return resultado;
}

El código anterior avanza un nodo temporal hasta el penúltimo nodo, guarda el dato contenido en el nodo siguiente, borra el nodo siguiente, reenlaza el penúltimo (haciendo que ahora sea el último) y devuelve el dato localizado. Ten en cuenta que es una operación O(n) mientras que devolver un dato del tope de la pila es una operación O(1).

PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82