How do I extract data from the end of a dynamic stack?

3

I'm designing a C ++ program with a dynamic stack but when I extract the data I want it to be inverted, they can help me. This is my code:

#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){
}
    
asked by Joni 17.10.2018 в 10:38
source

2 answers

1
  

I'm designing a program in C ++ with a dynamic stack but when I extract the data I want it to be inverted.

Well, do not use a stack . In a stack, the order of the data is dependent on the order in which they were inserted, if it is a stack of FIFO type, you stack it above and unstack it below, and if it is LIFO, you stack and unstack it above.

Details to take into account.

  • C ++ has a data type for Boolean variables: bool , which can only get the values true or false , so you should not use macros to define those symbols.
  • In C ++ the keyword struct is not part of the type, so it is not necessary to define variables of type struct (you do not need to do typedef struct nombre {} alias; ).
  • There is no obligation to use the using namespace std; clause since it is only an aid to the writing of code; If you decide to use this clause do not do it in the global scope, use it in the smallest possible scope. Read this thread to find out why.
  • The way to work with character strings in C ++ is using objects of type std::string (accessible after including header <string> ) not with formations 1 of characters.

The nomenclature is important.

Variables must have a name that helps, at a glance, to define their role within the program; names like p , d , x , p1 , p2 , op , pila1 , pila2 are confusing.

In addition, the type docentes is in the plural, implying that it contains more than one data, but when examining it it is seen that it contains information from a single teacher (not several), so the plural gives an incorrect idea of the type .

On the other hand, the keyword typedef is used to define aliases of types What is the point of defining two different aliases for the same type?:

typedef pila *pila1;
typedef pila *pila2;

To finish, it seems that you work with a data type called pila but you do not have any stacking or unstacking operation, I guess the input and extract operations are the equivalent of push and < em> pop from a stack.

Nodes are not Lists.

This is a recurring error in StackOverflow in Spanish that generates a lot of confusion.

In the code that you have provided, you are using the nodes of your stack as if they were the stack itself and that is as wrong as saying that a step is a ladder, sincerely Do you think the same ?:

Your question is about C ++.

The C ++ language is multi-paradigm, so a priori you are not limited to a specific paradigm; but one of the strengths of the language is its support for the object-oriented programming so I advise you to you really believe a ready object instead of relying on loose functions.

Proposal.

Keeping in mind all of the above, your code might look like this:

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();
};

Class pila has an internal type in the private zone that is node ; This type is inaccessible from the outside favoring the encapsulation : the class itself manages its nodes, from outside from the list there are no reasons to work with nodes, the functions no longer receive a stack pointer for that reason.

Operation reversed.

I insist that it does not make any sense to unstack data from the bottom of the stack, so you probably do not want to work with batteries. But if you want to do that operation you will have to go through the whole stack until the end, return the data stored there and re-link the second last node. So starting from 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;
}

The previous code advances a temporary node to the penultimate node, saves the data contained in the next node, deletes the next node, resets the second last node (making it now the last node) and returns the localized data. Note that it is a O (n) operation, while returning a data from the top of the stack is a O (1) operation.

    
answered by 17.10.2018 / 14:45
source
3
  

I'm designing a program in C ++

Then I suggest using the C ++ own syntax:

  • true and false already exist in C ++, you do not have to redeclare them. You have the type bool available

    // Lineas comentadas:
    // #define true 1
    // #define false 0
    
  • It is not necessary to use typedef with structures

    struct pila{
      docentes d;
      pila *sgte;
    };
    
    pila pilaA, pilaB;
    
  • Tabulate the code correctly: with this you get it readable by human beings. It would also be appreciated if there were line breaks before starting the functions:

    // 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;
    
  • A stack is not the same as a node. More information: Assigning pointers in linked lists :

    struct Nodo
    {
      Nodo* sgte;
      docentes data;
    };
    
    class Pila
    {
      Nodo* front;
    };
    
  • C ++ is an object-oriented language. This means that structures and classes, unlike C, can have properties and methods. It is not necessary to have free functions all the time:

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

When I extract the data, I want it to be inverted

You have programmed a LIFO stack and, by what is understood, you intend it to function as a FIFO.

To change the format you have to attack the entry of values ... now, instead of storing the new elements at the beginning you have to enter them at the end:

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;
  }
}

And can not you simply extract the nodes in reverse order?

No, for this you would need a double linked list. Since each node only knows the node that follows the list, it can only be traversed in direct order ... never in reverse.

    
answered by 17.10.2018 в 11:14