0

Necesito eliminar un elemento de la pila pero conservando los nodos anteriores, tengo que pasar esos nodos a otra pila para eliminar el nodo que busco esto es lo que he hecho pero aun no me da. Hice el if para buscarlo por la cédula no logro detectar que está mal, y el código después de la condición es lo que se supone me ayuda a mover los elementos a una nueva pila.

void pop3(pila *top,pila *top2, pila *elimino, int cedaux){
int cont=0;
cout<<"Cedula  eliminado :"<<endl;
top2=top;
    while(top->sig!=NULL){
        if ((elimino->sig)->ci==cedaux){
            cout<<"CEDULA ENCONTRADA: "<<endl;
            cout<<"Cedula: "<<elimino->ci<<" Edad: "<<elimino->edad<<endl;
            top=(top->sig)->sig;
            elimino=elimino->sig;
            top2->sig=NULL;
            free(elimino);
            cout<<"CEDULA ELIMINADA: "<<endl;
        }
    top2=top;
    top=top->sig;
    top2->sig=NULL;
    elimino=top2;
    top2=elimino;

    }
    if(top->sig==NULL){
        cout<<"CEDULA NO ENCONTRADA: "<<endl;
    }
}

Si me podrían explicar el error muchas gracias. Aquí está el código completo:

#include <iostream>
using namespace std;
struct pila
     {
    int ci;
    int edad;
    pila *sig;
};
 // Funcion agregar nuevo nodo
   pila *ne()
   {  return((pila*)malloc(sizeof(struct pila)));
   }

 //Agregar datos 
   pila *push1(pila *top, pila *nuevo){
     int control=0;
     while(control==0){
       nuevo=ne();
       cout<<"ingresar CI: "<<endl;
       cin>>nuevo->ci;
       cout<<"ingresar EDAD: "<<endl;
       cin>>nuevo->edad;
       nuevo->sig=top;
       top=nuevo;
       cout<<"Para continuar tipee  0 de lo contrario otro numero : "<<endl;
       cin>>control;
    }
    return top;
  }
  //Eliminar pila
   void pop1(pila *top, pila *elimino){
     while(elimino!=NULL){
       elimino=top;
       cout<<"Cedula: "<<elimino->ci<<" Edad: "<<elimino->edad<<endl;
       top=top->sig;
       free(elimino);
     }
  }

  //Eliminar pila por cantidad
  void pop2(pila *top, pila *elimino, int c){
     int cont=0;
     cout<<"nodos eliminados :"<<endl;
     while(cont!=c){
         elimino=top;
         cout<<"Cedula: "<<elimino->ci<<" Edad: "<<elimino->edad<<endl;
         top=top->sig;
         free(elimino);
         cont++;
     }
   }

   //Eliminar no de la pila conservando los nodos anteriores
   void pop3(pila *top,pila *top2, pila *elimino, int cedaux){
      int cont=0;
      cout<<"Cedula  eliminado :"<<endl;
      top2=top;
      while(top->sig!=NULL){
         if ((elimino->sig)->ci==cedaux){
            cout<<"CEDULA ENCONTRADA: "<<endl;
            cout<<"Cedula: "<<elimino->ci<<" Edad: "<<elimino->edad<<endl;
            top=(top->sig)->sig;
            elimino=elimino->sig;
            top2->sig=NULL;
            free(elimino);
            cout<<"CEDULA ELIMINADA: "<<endl;
         }
      top2=top;
      top=top->sig;
      top2->sig=NULL;
      elimino=top2;
      top2=elimino;
      }

        if(top->sig==NULL){
          cout<<"CEDULA NO ENCONTRADA: "<<endl;
        }
    }

   int menupop(int b) {
       system("cls");
       cout<<"Indique opcion de insercón :"<<endl;
       cout<<"1 eliminar pila"<<endl;
       cout<<"2 eliminar pila por cantidad"<<endl;
       cout<<"3 extraer conservando"<<endl;
       //cout<<"4 al final"<<endl;
       cout<<"ingrese opcion: ";
       cin>>b;
       return b;
    }

   int main() {
       int b, c, pos,cedaux;
       pila *top;
       pila *nuevo;
       pila *top2;
       top=NULL;
       top=push1(top,nuevo);
       nuevo=top;
       b=menupop(b);
       switch(b){
       case 1: 
            cout<<"eliminando toda la pila"<<endl;
            pop1(top,nuevo);
       break;
       case 2:
            cout<<"eliminando nodos de pila"<<endl;
            cout<<"cuantos nodos a eliminar"<<endl;
            cin>>c;
            pop2(top,nuevo,c);
       break;
       case 3:
            cout<<"eliminando Cedula de pila"<<endl;
            cout<<"Cedula que desea eliminar"<<endl;
            cin>>cedaux;
            pop3(top,top2, nuevo,cedaux );
       break;
       }        
       return 0;
    }
PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82
Marbys
  • 33
  • 2
  • 6
  • ¿Podrías añadir la definición del tipo `pila`? – PaperBirdMaster Feb 25 '19 at 14:57
  • @Marbys, añade la definición del tipo pila como te indico PaperBirdMaster y respondeme lo siguiente, ¿Por qué debes pasar los otros nodos que no eliminas a la otra pila? ¿tiene que ser así si o si?, porque se puede eliminar un nodo sin tener que pasar los otros a otra pila y de hecho me parece más sencillo. – Mario Feb 25 '19 at 16:29
  • A que se refieren cuando me dicen que añada la definición del tipo pila ? ... si tiene que ser asi , tengo que eliminar un nodo cualquiera conservando los anteriores , creando una segunda pila @Mario . Eliminar los nodos sin crear una nueva pila ya lo hice y si es sencillo pero ahora el profesor me mando ese caso e hice lo que está arriba pero no logro eliminar sin perder los nodos anteriores – Marbys Feb 26 '19 at 02:13
  • agregue el código completo para que vean las operaciones – Marbys Feb 26 '19 at 02:39
  • 1
    @Marbys, **no tienes la estructura basica de tu pila**, razon por la cual te preguntan el tipo de pila y de lo que dice mario, esta totalmente mal, asi que no hagas caso de ese comentario. – Shassain Feb 26 '19 at 03:14

2 Answers2

1

Puedes guiarte por esto

   //Eliminar no de la pila conservando los nodos anteriores
   // top es el puntero al nodo superior de la pila, top2 es un nodo buffer
   void pop3(pila *top,pila *top2, int cedaux){
      cout<<"Cedula  eliminado :"<<endl;
      top2=top; // top2 sera el nodo actual
      if (top2 != NULL && top2->ci==cedaux) { // si el elemento en la pila buscado es el primero
          cout<<"CEDULA ENCONTRADA: "<<endl;
          top = top2->sig;
          free(top2);
          top2 = NULL;
          cout<<"CEDULA ELIMINADA: "<<endl;
      }
      pila *primero = top; // lo usaremos para recordar el primer elemento de la pila
      if(top!=NULL)
          top2 = top->sig; // top2 sera el nodo actual y top sera el nodo anterior
                           // [top] -> [top2] -> [x] -> [y] -> [z]
      while(top2!=NULL) {
         if (top2->ci==cedaux) {
            cout<<"CEDULA ENCONTRADA: "<<endl;
            cout<<"Cedula: "<<top2->ci<<" Edad: "<<top2->edad<<endl;
            top->sig = top2->sig;
            free(top2);
            top2 = top->sig;
            cout<<"CEDULA ELIMINADA: "<<endl;
         }
         top  = top2; // top recordara donde estaba top2
         top2 = top->sig; // top2 sera el nuevo nodo actual
                          // (ahora top esta encima de top2)
      }

      // como top originalmente apuntaba al nodo superior de la pila
      // hacemos que siga apuntando a ese
      top = primero;
    }
Junior Usca
  • 620
  • 3
  • 14
1

Si me podrían explicar el error muchas gracias.

Tienes varios errores: de diseño, de nomenclatura, de concepto y de uso del lenguaje.

Error de concepto.

Tu objetivo es, mediante una pila, eliminar un elemento conservando los anteriores. Esto está conceptualmente mal. La pila por diseño un contenedor al que se añaden o eliminan elementos de la parte superior, no elementos arbitrarios. Imagina una pila de papeles:



Cuando añades un papel, lo pones en la parte superior de la pila, al retirar un papel lo haces también de la parte superior. Si estás retirando de un lugar intermedio de la pila siento decirte que o no necesitas una pila o estás usando la pila mal.

Error de nomenclatura.

Tienes un objeto capaz de contener datos y apuntar a otro objeto del mismo tipo. Solemos nombrar este tipo de objetos Nodo; tú lo estás nombrando pila, lo cuál es tremendamente confuso. Para hacer las cosas más confusas, pasas nodos alrededor del programa nombrándolos pila, es como si estuvieras tratando nodos como pilas, lo cuál es tan erróneo como decir que un escalón es una escalera. Este error es recurrente en SO.es, echa un vistazo a este hilo para más detalles.

Errores de diseño.

Tú código está muy desorganizado, cuesta de seguir y de entender. Deberías modularizar (separar cada una de las cosas que quieres hacer en funciones) siguiendo principios de responsabilidad única (cada función debe hacer una sola cosa).

C++ es un lenguaje multiparadigma, por lo que no necesariamente deberás programar con el paradigma orientado a objetos, pero precisamente un contenedor de datos (en tu caso, presuntamente, una pila) se ofrece al uso de este tipo de paradigma, que además fomentará el encapsulamiento.

Uso del lenguaje.

En C++ se usan los operadores new y delete para alojar y liberar memoria respectivamente. No deberías estar usando malloc y free (lee este hilo para más detalles).

C++ además ofrece el tipo de datos referencia, que evita el abuso de punteros en muchas situaciones. Si realmente no pudieras evitar usar punteros (no es tu caso) no deberías usar punteros en crudo.

Propuesta.

Para abordar todos los errores mencionados, tu código debe ser reescrito al completo. No abordaremos tu error de concepto respecto a pilas porque es el tema de la pregunta, pero podemos empezar por definir un objeto Pila con un tipo anidado Nodo:

struct Pila
{
    void Push(int ci, int edad);
    void Pop(int ci);
private:
    struct Nodo
    {
        int ci = 0, edad = 0;
        Nodo *siguiente = nullptr;
    };

    Nodo *buscar_anterior(int ci)
    Nodo *top = nullptr;
};

Esta propuesta ofrece una pila a la que se le pueden añadir datos (Push) y de la que eliminas datos en base a un identificador (Pop(int)), para borrar un nodo en medio de la pila nos ayudamos de una función auxiliar buscar_anterior:

Nodo *Pila::buscar_anterior(int ci)
{
    for (auto nodo = top; nodo && nodo->siguiente; nodo = nodo->siguiente)
        if (nodo->siguiente->ci == ci)
            return nodo;

    return nullptr;
}

Esta función busca el nodo anterior al que queremos eliminar, así podremos eliminarlo:

void Pila::Pop(int ci)
{
    if (top)
    {
        if (top->ci == ci)
        {
            auto nodo = top;
            top = top->siguiente;
            delete nodo;
        }
        else if (auto nodo = buscar_anterior(ci))
        {
            auto borrar = nodo->siguiente;
            nodo->siguiente = borrar->siguiente;
            delete borrar;
        }
    }
}

Puedes ver un ejemplo de uso en Wandbox. Ten en cuenta que no está liberando la memoria dinámica.

PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82
  • muchas gracias por tus observaciones . – Marbys Feb 26 '19 at 22:06
  • muchas gracias por tus observaciones .1) Era un ejercicio propuesto en la universidad el cual lo hice hoy y si se puede modificar o eliminar un elemento sin perder los anteriores tenia que crear otra pila. 2) tengo entendido que la estructura la puedo llamar como quiera la llame PILA por que es lo que estamos trabajando no necesariamente tiene que llamarse nodo lo importante es que el programado lo entienda y lo deje en comentarios para que los demás lo entiendan . 3) están separadas en funciones ( NO ES UN CÓDIGO TERMINADO) con fines pedagógicos . – Marbys Feb 26 '19 at 22:17
  • 1
    4) si puedo usar new y delete , pero también puedo usar las que fueron implementadas en el salón como malloc y free y hacen el mismo trabajo. igual lo tendré en consideración para futuros códigos gracias. 5) y ultimo por suerte no tuve que reescribirlo ya qué el código hace el requerimiento y si pude crear otra pila y mover los nodos sin perder ninguno. Asi que Problema resuelto muchas gracias por tus apreciaciones. – Marbys Feb 26 '19 at 22:17
  • 1) No es cierto. Para añadir o eliminar elementos de un contenedor de datos sin perder los anteriores, no necesitas crear otro contenedor de datos. 2) Puedes nombrar como quieras a las cosas, mas no todos los nombres tienen sentido. Puedes llamar "elefante" a tu "silla", pero no por ello será un "elefante" y no ayudará a que se entienda lo que quieres decir (más bien al contrario) 3) Tus funciones son confusas, con código de más y mezclan responsabilidades, no son nada pedagógicas. 4) `malloc` y `free` no son de [tag:c++], sólo debes usarlas si tienes buenos motivos para ello, y no los tienes. – PaperBirdMaster Feb 27 '19 at 06:52