2026-03-15 20:31:36 -06:00
|
|
|
#ifndef STACK_H
|
|
|
|
|
#define STACK_H
|
|
|
|
|
|
2026-03-15 20:57:13 -06:00
|
|
|
#include <cstdint>
|
|
|
|
|
#include <expected>
|
2026-03-15 21:26:09 -06:00
|
|
|
#include <format>
|
2026-03-15 21:09:23 -06:00
|
|
|
#include <new>
|
2026-03-15 21:37:15 -06:00
|
|
|
#include <print>
|
2026-03-15 20:57:13 -06:00
|
|
|
|
2026-03-17 16:31:31 -06:00
|
|
|
/// @brief Default initial size for the stack
|
2026-03-15 20:57:13 -06:00
|
|
|
#define DEFAULT_STACK_SIZE 4
|
|
|
|
|
|
2026-03-17 16:31:31 -06:00
|
|
|
/**
|
|
|
|
|
* @brief Error codes for stack operations
|
|
|
|
|
*/
|
2026-03-15 20:57:13 -06:00
|
|
|
enum class StackErr {
|
2026-03-17 16:31:31 -06:00
|
|
|
ok, ///< Operation successful
|
|
|
|
|
bad_alloc, ///< Memory allocation failed
|
|
|
|
|
empty, ///< Stack is empty
|
2026-03-15 20:57:13 -06:00
|
|
|
};
|
|
|
|
|
|
2026-03-17 16:31:31 -06:00
|
|
|
/**
|
|
|
|
|
* @brief Generic stack implementation
|
|
|
|
|
*
|
|
|
|
|
* @tparam T Type of elements stored in the stack
|
|
|
|
|
* @note T must be formattable with std::format
|
|
|
|
|
*/
|
2026-03-15 20:57:13 -06:00
|
|
|
template<typename T>
|
2026-03-15 21:26:09 -06:00
|
|
|
requires std::formattable<T, char>
|
2026-03-15 20:31:36 -06:00
|
|
|
class Stack {
|
2026-03-15 20:57:13 -06:00
|
|
|
private:
|
2026-03-17 16:31:31 -06:00
|
|
|
uint64_t len; ///< Current number of elements
|
|
|
|
|
uint64_t cap; ///< Current capacity
|
|
|
|
|
T *data; ///< Pointer to data array
|
2026-03-15 20:57:13 -06:00
|
|
|
|
|
|
|
|
public:
|
2026-03-17 16:31:31 -06:00
|
|
|
/**
|
|
|
|
|
* @brief Construct a new Stack object
|
|
|
|
|
*/
|
2026-03-15 20:57:13 -06:00
|
|
|
Stack();
|
2026-03-17 16:31:31 -06:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Destroy the Stack object
|
|
|
|
|
*/
|
2026-03-15 20:57:13 -06:00
|
|
|
~Stack();
|
|
|
|
|
|
2026-03-17 16:31:31 -06:00
|
|
|
/**
|
|
|
|
|
* @brief Remove and return the top element
|
|
|
|
|
*
|
|
|
|
|
* @return std::expected<T, StackErr> Top element or error
|
|
|
|
|
*/
|
2026-03-15 20:57:13 -06:00
|
|
|
std::expected<T, StackErr> pop();
|
2026-03-15 20:31:36 -06:00
|
|
|
|
2026-03-17 16:31:31 -06:00
|
|
|
/**
|
|
|
|
|
* @brief Get the top element without removing it
|
|
|
|
|
*
|
|
|
|
|
* @return std::expected<T, StackErr> Top element or error
|
|
|
|
|
*/
|
2026-03-15 20:57:13 -06:00
|
|
|
std::expected<T, StackErr> peek();
|
|
|
|
|
|
2026-03-17 16:31:31 -06:00
|
|
|
/**
|
|
|
|
|
* @brief Push a new element onto the stack
|
|
|
|
|
*
|
|
|
|
|
* @param val Value to push
|
|
|
|
|
* @return StackErr Result of the operation
|
|
|
|
|
*/
|
2026-03-15 20:57:13 -06:00
|
|
|
StackErr push(T val);
|
|
|
|
|
|
2026-03-17 16:31:31 -06:00
|
|
|
/**
|
|
|
|
|
* @brief Get current size of the stack
|
|
|
|
|
*
|
|
|
|
|
* @return uint64_t Number of elements
|
|
|
|
|
*/
|
2026-03-17 15:49:55 -06:00
|
|
|
uint64_t size();
|
|
|
|
|
|
2026-03-17 16:31:31 -06:00
|
|
|
/**
|
|
|
|
|
* @brief Print stack contents to console
|
|
|
|
|
*/
|
2026-03-15 20:57:13 -06:00
|
|
|
void print();
|
2026-03-15 20:31:36 -06:00
|
|
|
};
|
|
|
|
|
|
2026-03-17 15:49:55 -06:00
|
|
|
template <typename T>
|
|
|
|
|
requires std::formattable<T, char>
|
|
|
|
|
uint64_t Stack<T>::size() {
|
|
|
|
|
return this->len;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-15 20:57:13 -06:00
|
|
|
template <typename T>
|
2026-03-15 21:26:09 -06:00
|
|
|
requires std::formattable<T, char>
|
2026-03-15 20:57:13 -06:00
|
|
|
Stack<T>::Stack() {
|
2026-03-17 15:36:27 -06:00
|
|
|
this->data = new T[DEFAULT_STACK_SIZE];
|
|
|
|
|
this->cap = DEFAULT_STACK_SIZE;
|
|
|
|
|
this->len = 0;
|
2026-03-15 20:57:13 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2026-03-15 21:26:09 -06:00
|
|
|
requires std::formattable<T, char>
|
2026-03-15 20:57:13 -06:00
|
|
|
Stack<T>::~Stack() {
|
|
|
|
|
delete[] this->data;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-15 21:09:23 -06:00
|
|
|
template <typename T>
|
2026-03-15 21:26:09 -06:00
|
|
|
requires std::formattable<T, char>
|
2026-03-15 21:09:23 -06:00
|
|
|
StackErr Stack<T>::push(T value) {
|
2026-03-17 16:31:31 -06:00
|
|
|
/// Resize if needed
|
2026-03-15 21:09:23 -06:00
|
|
|
if (this->len >= this->cap) {
|
|
|
|
|
uint64_t new_capacity = this->cap * 2;
|
|
|
|
|
T *tmp;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
tmp = new T[new_capacity];
|
|
|
|
|
} catch (const std::bad_alloc& e) {
|
|
|
|
|
return StackErr::bad_alloc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < this->len; i++) {
|
|
|
|
|
tmp[i] = this->data[i];
|
|
|
|
|
}
|
2026-03-15 20:57:13 -06:00
|
|
|
|
2026-03-15 21:09:23 -06:00
|
|
|
delete[] this->data;
|
|
|
|
|
this->data = tmp;
|
2026-03-15 21:37:15 -06:00
|
|
|
this->cap = new_capacity;
|
2026-03-15 21:09:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->data[this->len] = value;
|
|
|
|
|
this->len++;
|
|
|
|
|
|
|
|
|
|
return StackErr::ok;
|
|
|
|
|
}
|
2026-03-15 20:57:13 -06:00
|
|
|
|
2026-03-15 21:26:09 -06:00
|
|
|
template <typename T>
|
|
|
|
|
requires std::formattable<T, char>
|
|
|
|
|
std::expected<T, StackErr> Stack<T>::pop() {
|
2026-03-17 16:31:31 -06:00
|
|
|
/// Check empty stack
|
2026-03-15 21:26:09 -06:00
|
|
|
if (this->len == 0) {
|
|
|
|
|
return std::unexpected(StackErr::empty);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
T return_val = this->data[this->len - 1];
|
2026-03-17 15:49:55 -06:00
|
|
|
this->len--;
|
2026-03-15 21:26:09 -06:00
|
|
|
|
2026-03-17 16:31:31 -06:00
|
|
|
/// Shrink if too much unused space
|
2026-03-15 21:26:09 -06:00
|
|
|
if (this->cap / 4 > this->len) {
|
|
|
|
|
uint64_t new_capacity = this->cap / 2;
|
|
|
|
|
T *tmp;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
tmp = new T[new_capacity];
|
|
|
|
|
} catch (const std::bad_alloc& e) {
|
|
|
|
|
return std::unexpected(StackErr::bad_alloc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < this->len; i++) {
|
|
|
|
|
tmp[i] = this->data[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete[] this->data;
|
|
|
|
|
this->data = tmp;
|
2026-03-15 21:37:15 -06:00
|
|
|
this->cap = new_capacity;
|
2026-03-15 21:26:09 -06:00
|
|
|
}
|
2026-03-17 15:49:55 -06:00
|
|
|
|
2026-03-17 15:36:27 -06:00
|
|
|
return return_val;
|
2026-03-15 21:26:09 -06:00
|
|
|
}
|
|
|
|
|
|
2026-03-15 21:28:17 -06:00
|
|
|
template <typename T>
|
|
|
|
|
requires std::formattable<T, char>
|
|
|
|
|
std::expected<T, StackErr> Stack<T>::peek() {
|
2026-03-17 16:31:31 -06:00
|
|
|
/// Check empty stack
|
2026-03-15 21:28:17 -06:00
|
|
|
if (this->len == 0) {
|
|
|
|
|
return std::unexpected(StackErr::empty);
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-17 15:36:27 -06:00
|
|
|
return this->data[this->len - 1];
|
2026-03-15 21:28:17 -06:00
|
|
|
}
|
|
|
|
|
|
2026-03-15 21:37:15 -06:00
|
|
|
template <typename T>
|
|
|
|
|
requires std::formattable<T, char>
|
|
|
|
|
void Stack<T>::print() {
|
|
|
|
|
std::println("Stack:");
|
|
|
|
|
std::println("Length: {}.", this->len);
|
|
|
|
|
std::println("Capacity: {}.", this->cap);
|
|
|
|
|
|
2026-03-17 15:36:27 -06:00
|
|
|
std::println("{:^22}", "Datos");
|
|
|
|
|
std::println("{:^22}", "|");
|
|
|
|
|
std::println("{:^22}", "v");
|
2026-03-15 21:37:15 -06:00
|
|
|
|
2026-03-17 15:36:27 -06:00
|
|
|
for (uint64_t i = 0; i < this->cap; i++) {
|
2026-03-15 21:37:15 -06:00
|
|
|
if (i < this->len) {
|
2026-03-17 15:36:27 -06:00
|
|
|
std::println("[{:^20}]", this->data[i]);
|
2026-03-15 21:37:15 -06:00
|
|
|
} else {
|
2026-03-17 15:36:27 -06:00
|
|
|
std::println("[{:^20}]", "EMPTY");
|
2026-03-15 21:37:15 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-17 16:31:31 -06:00
|
|
|
#endif // STACK_H
|