/*
** file: stack_queue.cpp
**
** stack + queue with singly linked lists
** UC: 21046 - EDAF @ UAb
** e-fólio A 2025-26
**
** Aluno: 2203810 - João Pires
*/

// Defina:
//   Em stack_queue.h as classes da estrutura de dados
//   Em stack_queue.cpp a implementação dos métodos das classes da estrutura de dados
// ** Não altere o nome das classes nem dos atributos obrigatórios! **

#include <iostream>
#include <cstdio>
#include "stack_queue.h"
using namespace std;

INode::INode(int value, INode *pnext) // Construtor do nó
{
   item = value;
   next = pnext;
}
//Stack
IStack::IStack() { n = 0; ptop = 0; }
IStack::~IStack() { clear(); }

bool IStack::empty() const { return n == 0; } // Verificar se a pilha está vazia
int IStack::size() const { return n; } // Número de elementos

void IStack::push(int item) { // Inserir no topo da pilha
   INode *newNode = new INode(item, ptop);
   ptop = newNode;
   n++;
}

void IStack::pop() { // Remover topo da pilha
   if (empty()) return;

   INode *nodeToDelete = ptop;
   ptop = ptop->next;
   delete nodeToDelete;
   n--;
}

int IStack::top() const { // Aceder ao topo da pilha assumindo que não está vazia
   return ptop->item;
}

void IStack::clear() { // Limpar a pilha
   while (!empty()) pop();
}

void IStack::print() const { // Imprimir do topo para a base
   printf("Pilha=");
   INode *current = ptop;
   while (current != 0) {
      printf(" %d", current->item);
      current = current->next;
   }
   printf("\n");
}
//QUEUE
IQueue::IQueue() { n = 0; pfirst = plast = 0; }
IQueue::~IQueue() { clear(); }

bool IQueue::empty() const { return n == 0; } // Verifica se a fila está vazia
int IQueue::size() const { return n; } // Número de elementos

void IQueue::enqueue(int item) { // Inserir no fim
   INode *newNode = new INode(item, 0);

   if (empty()) {
      pfirst = newNode;
      plast = newNode;
   } else {
      plast->next = newNode;
      plast = newNode;
   }
   n++;
}

void IQueue::dequeue() { // Remover da frente
   if (empty()) return;

   INode *nodeToDelete = pfirst;
   pfirst = pfirst->next;
   delete nodeToDelete;
   n--;

   if (n == 0) plast = 0; // Se ficou vazia, atualiza o plast
}

int IQueue::front() const { return pfirst->item; } // Aceder à frente
int IQueue::back() const { return plast->item; } // Aceder ao fim

void IQueue::clear() { // Limpar a fila
   while (!empty()) dequeue();
}

void IQueue::print() const { // Imprimir da frente para o fim
   printf("Fila=");
   INode *current = pfirst;
   while (current != 0) {
      printf(" %d", current->item);
      current = current->next;
   }
   printf("\n");
}

// EOF