Skip to content

Pilas cpp

RDLL edited this page Aug 16, 2023 · 3 revisions

Pilas

Son una estructura líneal que puede ser dinámica o estática, para que sea dinámica se requiere de otra estructura llamada lista.

Tiene la carácteristica de que el último elemento que entra es el primer elemento que sale (LIFO), como en una pila de platos, donde los vamos sacando de arriba hacia abajo.

#include <iostream>

using namespace std;

const int n = 10;

typedef struct pil{
    int tope = 0;    
    int datos[n];
    void push(int a){
        if(tope < n){
            datos[tope] = a;
            ++tope;
            cout << a << " insertado en la pila";
        }else{
            cout << "No se puede insertar " << a << " ,pila llena";
        }
        cout << endl;
    }
    void pop(){
        int a;
        if (tope == n)
            --tope;
        if(tope >= 0){
             a = datos[tope];
            --tope;
            cout << a << " eliminado de la pila";
        }else{
            cout << "No se pueden eliminar elementos, pila vacia";
        }
        cout << endl;
    }
    void llena(){
        if(tope == n)
            cout << "Pila llena";
        else
            cout << "Pila con " << n - tope << " elementos vacios";
        cout << endl;
    }
    void vacia(){
        if(tope < 0)
            cout << "Pila vacia";
        else
            cout << "Pila con " << tope << " elementos";
        cout << endl;
    }
}PILA;

int main(){
    PILA pila;
    for(int i = 0; i < n; i++)
        pila.push(i+1);
    pila.llena();
    for(int i = 0; i < n; i++)
        pila.pop();
    pila.vacia();
    cout << endl;
    return 0;
}

Analizando la pila

typedef struct pil{
    int tope = 0;    
    int datos[n];
    void push(int a);
    void pop();
    void llena();
    void vacia();
}PILA;

Tenemos los miembros tope, el arreglo datos y las funciones push, pop, llena y vacia.

tope nos ayuda a saber la última posición en donde fue insertado un dato, conforme se vayan ingresando datos, tope va creciendo, al llegar al tamaño del arreglo datos se dejan de ingresar datos.

Después tenemos las funciones que nos dejan interactuar con los miembros.

Funcion push

void push(int a){
        if(tope < n){
            datos[tope] = a;
            ++tope;
            cout << a << " insertado en la pila";
        }else{
            cout << "No se puede insertar " << a << " ,pila llena";
        }
        cout << endl;
    }

La función recibe un parámetro de tipo entero, que es el dato a insertar dentro del arreglo.

La función verifica si el tope es menor al tamaño máximo que permite el arreglo datos, en caso de que así sea, agrega el parámetro a al arreglo y aumenta el tope, después muestra un mensaje de que todo salió bien. En caso contrario, no agrega nada y muestra el mensaje que no se pudo insertar el valor.

Función pop

void pop(){
        int a;
        if(tope > 0){
            --tope;
             a = datos[tope];
            --tope;
            cout << a << " eliminado de la pila";
        }else{
            cout << "No se pueden eliminar elementos, pila vacia";
            tope = 0;
        }
        cout << endl;
    }

Esta función no recibe parámetros, tiene la variable auxiliar a, que nos sirve para guardar y mostrar el valor que se elimino, se disminuye el tope en 1, ya que al ingresar valores este se aumenta y queda un indice arriba, se verifica que el tope sea mayor a 0 y se elimina el valor, que en realidad se ignora, y se disminuye el tope.

Cuando la pila esta vacía se muestra que no se pueden insertar elementos y tope se reinicia.

Funciones llena y vacia

Estas funciones solo verifican que la pila este llena o vacia, es parecida a la implementación que tienen las funciones push y pop, también se pueden modificar para que devuelvan 0 o 1, y las funciones push y pop las llamen.

void llena(){
    if(tope == n)
        cout << "Pila llena";
    else
        cout << "Pila con " << n - tope << " elementos vacios";
    cout << endl;
}
void vacia(){
    if(tope < 0)
        cout << "Pila vacia";
    else
        cout << "Pila con " << tope << " elementos";
    cout << endl;
}

Creando nuestros propios headers

Si vemos el código al inicio, se ve demasiado largo, para solucionar ese problema y también por comodidad de nosotros y de otras personas involucradas en el proyecto, nos conviene dividir nuestro código en archivos diferentes, un archivo para el código principal, uno para las funciones, estructuras, clases, etc. y demás que vayamos a utilizar, de esta manera todo se ve mas ordenado y en caso de modificar algo, no tenemos que estar buscando a tráves de una gran cantidad de código además de ser más fácil de modificar y de leer.

Entonces tendríamos nuestro código principal main.cpp

Main

#include <iostream>
#include "pila.hpp"
using namespace std;

int main(){
    PILA pila;
    for(int i = 0; i < n; i++)
        pila.push(i+1);
    pila.llena();
    for(int i = 0; i < n; i++)
        pila.pop();
    pila.vacia();
    cout << endl;
    return 0;
}

Hay un header llamado pila.hpp, bueno esta será la cabecera que crearemos y que tendra la declaración de nuestra estructura, recordar que de aquí en adelante, se trabajara de esta manera.

Header propio

#ifndef __PILA_HPP
#define __PILA_HPP

#include <iostream>

using namespace std;

const int n = 10;

typedef struct pil{
    int tope = 0;
    int datos[n];
    void push(int a);
    void pop();
    void llena();
    void vacia();
}PILA;

#endif

Tenemos las instrucciones del preprocesador #ifndef y #endif.

La primera nos sirve para verificar si la macro _PILA_HPP no existe, en caso de que no exista, la crea, esto nos sirve para evitar que si nuestra librería esta siendo llamada por otra librería que se ejecuta en el código principal, sea declarada o llamada dos veces.

#endif nos sirve para indicar que termino la comprobación.

Archivo de implementación

Y finalmente tendremos el archivo de implementación donde estará el funcionamiento de las funciones.

#include "pil.hpp"

void PILA::push(int a){
    if(tope < n){
        datos[tope] = a;
        ++tope;
        cout << a << " insertado en la PILAa";
    }else
        cout << "No se puede insertar " << a << " ,PILAa llena";
    cout << endl;
}

void PILA::pop(){
    int a;
    if (tope == n)
        --tope;
    if(tope >= 0){
        a = datos[tope];
        --tope;
        cout << a << " eliminado de la PILAa";
    }else 
        cout << "No se pueden eliminar elementos, PILAa vacia";
    cout << endl;
}

void PILA::llena(){
    if(tope == n)
        cout << "Pila llena";
    else
        cout << "Pila con " << tope + 1 << " elementos vacios";
    cout << endl;
}

void PILA::vacia(){
    if(tope == n)
            cout << "Pila llena";
        else
            cout << "Pila con " << tope + 1 << " elementos vacios";
        cout << endl;    
}

Y nuevamente incluimos la librería que creamos, esto es para que el archivo de implementación sepa de donde las tiene que sacar, y es la razón por la cuál incluimos #ifndef, que aunque si se esta declarando dos veces, en realidad se invoca una sola vez.

Introducción Estructuras Colas Listas Arboles Objetos