#ifndef LINKEDLIST_H #define LINKEDLIST_H #include #include #include #include /** * @brief Codigos de error para operaciones de LinkedList */ enum class LinkedListErr { LINKEDLIST_OK, /**< Operacin exitosa */ LINKEDLIST_BAD_ALLOC, /**< Error al asignar memoria */ LINKEDLIST_OUT_OF_BOUNDS, /**< Índice fuera de rango */ LINKESLIST_INVALID_SIZE, /**< Tamaño inválido */ LINKEDLIST_NOT_FOUND, /**< Elemento no encontrado */ LINKEDLIST_EMPTY, /**< La lista está vacia */ }; /** * @brief Nodo de una lista enlazada * * @tparam T Tipo de dato almacenado en el nodo */ template class Node { public: T data; /**< Dato almacenado en el nodo */ Node *next; /**< Puntero al siguiente nodo */ }; /** * @brief Implementación de una lista enlazada simple * * Estructura de datos dinamica que almacena elementos de tipo T * utilizando nodos enlazados mediante punteros. * * @tparam T Tipo de dato almacenado en la lista */ template class LinkedList { private: size_t size; /**< Numero de elementos en la lista */ Node *head; /**< Primer nodo de la lista */ Node *tail; /**< Último nodo de la lista */ public: /** * @brief Constructor de la lista enlazada */ LinkedList(); /** * @brief Destructor de la lista * * Libera toda la memoria de los nodos. */ ~LinkedList(); /** * @brief Obtiene el elemento en una posicion específica * * @param index indice del elemento * @return std::expected Valor encontrado o error */ std::expected get(size_t index); /** * @brief Inserta un elemento al final de la lista * * @param value Valor a insertar * @return LinkedListErr Cdigo de estado de la operacion */ LinkedListErr append(const T& value); /** * @brief Inserta un elemento al inicio de la lista * * @param value Valor a insertar * @return LinkedListErr Codigo de estado */ LinkedListErr prepend(const T& value); /** * @brief Elimina y devuelve el ultimo elemento de la lista * * @return std::expected Elemento eliminado o error */ std::expected pop(); /** * @brief Elimina el elemento en una posicion especifica * * @param index Indice del elemento a eliminar * @return LinkedListErr Codigo de estado */ LinkedListErr remove(size_t index); /** * @brief Modifica el valor de un elemento en un indice * * @param index Índice del elemento * @param value Nuevo valor * @return LinkedListErr Código de estado */ LinkedListErr set(size_t index, const T& value); /** * @brief Busca un valor dentro de la lista * * @param value Valor a buscar * @return std::expected Índice del elemento o error */ std::expected find(const T& value); /** * @brief Imprime los elementos de la lista * * @return LinkedListErr Código de estado */ LinkedListErr print(); /** * @brief Verifica si la lista esta vacia * * @return true si la lista no contiene elementos */ bool is_empty(); /** * @brief Obtiene el numero de elementos de la lista * * @return size_t Tamaño de la lista */ size_t len(); }; template LinkedList::LinkedList() { size = 0; head = nullptr; tail = nullptr; } template LinkedList::~LinkedList() { Node *current = this->head; while (current != nullptr) { Node *temp = current; current = current->next; delete temp; } } template std::expected LinkedList::get(size_t index) { if (index >= this->size) { return std::unexpected(LinkedListErr::LINKEDLIST_OUT_OF_BOUNDS); } if (index == this->size - 1) { return tail->data; } Node *current = this->head; for (size_t i = 0; i < index ; i++) { current = current->next; } return current->data; } template LinkedListErr LinkedList::set(size_t index, const T& val) { if (index >= this->size) { return LinkedListErr::LINKEDLIST_OUT_OF_BOUNDS; } if (index == this->size - 1) { this->tail->data = val; } Node *current = this->head; for (size_t i = 0; i < index; i++) { current = current->next; } current->data = val; return LinkedListErr::LINKEDLIST_OK; } template LinkedListErr LinkedList::append(const T& value) { Node *new_node = nullptr; try { new_node = new Node; } catch(std::bad_alloc&) { return LinkedListErr::LINKEDLIST_BAD_ALLOC; } new_node->data = value; new_node->next = nullptr; if (this->head == nullptr && this->tail == nullptr) { this->head = new_node; this->tail = this->head; } else { this->tail->next = new_node; this->tail = this->tail->next; } this->size += 1; return LinkedListErr::LINKEDLIST_OK; } template LinkedListErr LinkedList::prepend(const T& value) { Node *new_node = nullptr; try { new_node = new Node; } catch(std::bad_alloc&) { return LinkedListErr::LINKEDLIST_BAD_ALLOC; } new_node->data = value; new_node->next = nullptr; if (this->head == nullptr && this->tail == nullptr) { this->head = new_node; this->tail = this->head; } else { new_node->next = this->head; this->head = new_node; } this->size += 1; return LinkedListErr::LINKEDLIST_OK; } template std::expected LinkedList::pop() { if (this->size == 0) { return std::unexpected(LinkedListErr::LINKEDLIST_EMPTY); } if (this->head->next == nullptr) { T return_val = this->head->data; delete this->head; this->head = nullptr; this->size--; return return_val; } Node* current = this->head; while (current->next->next != nullptr) { current = current->next; } T return_val = current->next->data; delete current->next; current->next = nullptr; this->size--; return return_val; } template LinkedListErr LinkedList::remove(size_t index) { if (index >= this->size) { return LinkedListErr::LINKEDLIST_OUT_OF_BOUNDS; } if (index == 0) { Node* tmp = this->head; this->head = this->head->next; delete tmp; this->size--; return LinkedListErr::LINKEDLIST_OK; } Node* current = this->head; for (size_t i = 1; i < index; ++i) { current = current->next; } Node* tmp = current->next; current->next = tmp->next; if(tmp == this->tail) { this->tail = current; } delete tmp; this->size--; return LinkedListErr::LINKEDLIST_OK; } template std::expected LinkedList::find(const T& value) { Node *current = this->head; size_t count = 0; while (current != nullptr) { if (current->data == value) { return count; } count++; current = current->next; } return std::unexpected(LinkedListErr::LINKEDLIST_NOT_FOUND); } template LinkedListErr LinkedList::print() { if (this->size == 0) { return LinkedListErr::LINKEDLIST_OK; } std::println("[LL]"); std::println(" |\n v"); Node *current = this->head; while (current != nullptr) { std::println("Node({})", current->data); std::println(" |"); std::println(" v"); current = current->next; } std::println("NULL"); return LinkedListErr::LINKEDLIST_OK; } template size_t LinkedList::len() { return this->size; } #endif // !