diff --git a/Data Structures/linkedList.h b/Data Structures/linkedList.h deleted file mode 100644 index b8738ea..0000000 --- a/Data Structures/linkedList.h +++ /dev/null @@ -1,382 +0,0 @@ -/** - * @file linkedList-doc.h - * @author Vakaris Michejenko (sleepicaffeine@gmail.com) - * @brief A header that defines multiple dynamic LinkedList classes - * @version 0.2 - * @date 2023-06-19 - * @copyright Copyright (c) 2023 - * @link https://github.com/SleepiCaffeine - */ -#ifndef LINKED_LIST_H -#define LINKED_LIST_H - -#include "node.h" -#include - -#ifndef LL_DEF -#define LL_DEF -/*! - * @class LL - * @brief Base linked list class. - * - * @details A base linked_list class, which acts like a Singly-Linked List. Supports insertion, removal, and dynamic types. - * - * @fn get_head() - * @fn set_head(C* const nd) - * @fn get_tail() - * @fn set_tail(C* const nd) - * - * @fn push_front(C* const nd) - * @fn push_front(const T dt) - * @fn push_back(C* const nd) - * @fn push_back(const T dt) - * @fn insert_node(C* const nd) - * @fn insert_node(const T dt) - * - * @fn pop_front() - * @fn pop_back() - * - * @fn length() - * @fn size() - * @tparam T typename - */ -template -struct linked_list { - -private: - C* head; - C* tail; - unsigned int len; - -public: - /** - * Creates a new Singly linked-list with a head and tail that points to NULL, and has a length of 0 - * @brief Default constructor. - * @see linked_list(std::nullptr_t) - * @see linked_list(C* const nd) - * @see linked_list(C* const nd) - */ - linked_list() - : linked_list(nullptr) {} - - linked_list(std::nullptr_t) - : head{nullptr}, tail{nullptr}, len{0} { } - - linked_list(C* const nd) - : head{nd}, len{1} { - if (nd->get_next() == nullptr) { - tail = nd; - return; - } - - C* currNode = new C(*nd); - while(currNode->get_next() != nullptr) { - ++len; - currNode = currNode->get_next(); - } - tail = currNode; - } - - linked_list(C* const hnd, C* const tnd) - : head{hnd}, tail{tnd}, len{1} { - if (head == nullptr) { - tail = nullptr; - len = 0; - return; - } - - C* currNode = new C(*hnd); - while(currNode != tnd) { - ++len; - currNode = currNode->get_next(); - } - } - - // Deep-Copy constructor - linked_list(const linked_list& list); - - // Destructor - ~linked_list(); - - // Param: - C* push_back(T dt); - C* push_back(C* const nd); - - C* push_front(T dt); - C* push_front(C* const nd); - - C* pop_back(); - C* pop_front(); - - C* get_head() const; /* hehehe */ - void set_head(C* const nd); - void set_head(T dt); - - C* get_tail() const; - void set_tail(C* const nd); - void set_tail(T dt); - - /** - * @brief Inserts the Node into the index provided - * @param nd Node to be inserted - * @param idx Index where the Node will be inserted - * @return Pointer to the Node that is behind the inserted Node - */ - C* insert_node(C* const nd, unsigned int idx); - - /** - * @brief Inserts a value into the index provided - * @param dt Value to be inserted into the list - * @param idx Index where the Node will be inserted - * @return Pointer to the Node that is behind the inserted Node - */ - C* insert_node(T dt, unsigned int idx); - - /** - * @brief Returns the length of the linked list - * @return Length of LL - */ - unsigned int length() const {return len;} - - /** - * @brief Returns the length of the linked list - * @return Length of LL - */ - unsigned int size() const {return len;} -}; - -template -linked_list::~linked_list() { - while (head) - head = head->get_next(); - - delete head; -} - -template -linked_list::linked_list(const linked_list& list) { - len = list.length(); - - if (list.get_head() == nullptr) - return; - - // Recreate the head - C* newHead = new C(); - newHead->set_data(list.get_head()->get_data()); - head = newHead; - - // Deep-copy the remaining chain - C* currNode = head; - C* sourceNode = list.get_head()->get_next(); - - while(sourceNode->get_next() != nullptr) { - // Create a new Node in the list - currNode->set_next(new C()); - // Set its value to source value - currNode->get_next()->set_data(sourceNode->get_data()); - // Set the destination to null - currNode->get_next()->set_next(nullptr); - // Move over by one Node in the list - currNode = currNode->get_next(); - // Move over by one Node in the source - sourceNode = sourceNode->get_next(); - } - - currNode->set_next(tail); - tail = new C(*sourceNode); -}; - -template -C* linked_list::push_front(T dt) { - if (!len) { - C* newNode = new C(dt); - head = newNode; - tail = newNode; - ++len; - return head; - } - - head = new C(head, dt); - ++len; - return head; -} - - -template -C* linked_list::push_front(C* const nd) { - if (!len) { - head = nd; - tail = nd; - ++len; - return head; - } - - auto oldHead = head; - nd->set_next(oldHead); - head = nd; - ++len; - return nd; -} - -template -C* linked_list::push_back(T dt) { - // If the list is empty, set both the head and tail to be the inserted node - if (!len) { - C* newNode = new C(dt); - head = newNode; - tail = newNode; - ++len; - return tail; - } - - C* newTail = new C(dt); - C* oldTail = new C(tail->get_data()); - oldTail->set_next(newTail); - - C* currNode = head; - - // Traverse the list - while (currNode->get_next()->get_next() != nullptr) - currNode = currNode->get_next(); - - // Add the Node to the end - currNode->set_next(oldTail); - ++len; - - tail = new C(nullptr, dt); - return tail; -} - -template -C* linked_list::push_back(C* const nd) { - // If the list is empty, then set both the head and the tail to the parameter node - if (!len) { - head = nd; - tail = nd; - ++len; - return tail; - } - - C* currNode = head; - C* oldTail = new C(tail->get_data()); - oldTail->set_next(nd); - - // Traverse the list - while (currNode->get_next() != tail) - currNode->get_next(); - - // Add the Node to the end - currNode->set_next(oldTail); - tail = new C(nd->get_next(), nd->get_data()); - ++len; - // Return the tail - return tail; -} - -template -C* linked_list::pop_back() { - if (len == 1) { - --len; - delete head; - delete tail; - return nullptr; - } - - C* currNode = head; - - // Traversing until the second-to-last list Node - while (currNode->get_next()->get_next() != nullptr) - currNode = currNode->get_next(); - - // Set last list member to null - currNode->set_next(nullptr); - tail = currNode; - - --len; - - // Return the new last member - return tail; -} - -template -C* linked_list::pop_front() { - if (len == 1) { - --len; - delete head; - delete tail; - return nullptr; - } - - head = head->get_next(); - --len; - return head; -} - -template -C* linked_list::insert_node(C* const nd, unsigned int idx) { - C* currentNode = head; - unsigned int counter = 0; - while (counter < idx - 1) { - currentNode = currentNode->get_next(); - ++counter; - } - C* nextAfter = currentNode->get_next(); - currentNode->set_next(nd); - nd->set_next(nextAfter); - - ++len; - - return nd; -} - -template -C* linked_list::insert_node(const T dt, unsigned int idx) { - C* currentNode = head; - unsigned int counter = 0; - while (counter < idx - 1) { - currentNode = currentNode->get_next(); - ++counter; - } - - currentNode->set_next(new C(currentNode->get_next(), dt)); - ++len; - - return currentNode->get_next(); -} - -template -C* linked_list::get_head() const { - return head; -} - -template -void linked_list::set_head(C* const nd) { - this->head = nd; -} - -template -void linked_list::set_head(T dt) { - this->pop_front(); - this->push_front(dt); -} - -template -C* linked_list::get_tail() const { - return tail; -} - -template -void linked_list::set_tail(C* const nd) { - this->pop_back(); - this->push_back(nd); -} - -template -void linked_list::set_tail(T dt) { - this->pop_back(); - this->push_back(dt); -} - -#endif // LL_DEF - -#endif // LINKED_LIST_H \ No newline at end of file diff --git a/Data Structures/sl_list.hpp b/Data Structures/sl_list.hpp new file mode 100644 index 0000000..0bf9d22 --- /dev/null +++ b/Data Structures/sl_list.hpp @@ -0,0 +1,578 @@ +/** + * @file sl_list.h + * @author Vakaris Michejenko (sleepicaffeine@gmail.com) + * @brief A header that defines a dynamic singly-linked list class + * @version 0.2 + * @date 2023-06-20 + * @copyright Copyright (c) 2023 + * @link https://github.com/SleepiCaffeine + */ +#ifndef SINGLY_LINKED_LIST_H +#define SINGLY_LINKED_LIST_H + +#include "node.hpp" +#include + +/*! + * @class sl_list + * @brief Singly-Linked List (sl_list) Class. + * + * @details A Singly-linked list data structure class, which supports insertion, removal, and dynamic types. Due to being Singly-linked it can only be used with node. See node.h on how to use them. + * + * @fn get_head() + * @fn set_head(node* const nd) + * @fn get_tail() + * @fn set_tail(node* const nd) + * + * @fn push_front(node* const nd) + * @fn push_front(const T dt) + * @fn push_back(node* const nd) + * @fn push_back(const T dt) + * @fn insert_node(node* const nd) + * @fn insert_node(const T dt) + * + * @fn pop_front() + * @fn pop_back() + * + * @fn length() + * @fn size() + * @fn upadate_len() + * @tparam T typename + */ +template +class sl_list { + +private: + node* head; /**< Pointer to the head (or root) node [node*]*/ + node* tail; /**< Pointer to the tail node [node*]*/ + unsigned int len; /**< List's length [unsigned int]*/ + +public: + /** + * Creates a new sl-list with a head and tail that points to NULL, and has a length of 0 + * @brief Default constructor. + * @see ~sl_list() + * @see sl_list(node* const nd) + * @see sl_list(const node& nd) + * @see sl_list(node* const hnd, node* const tnd) + */ + sl_list() + : sl_list{nullptr, nullptr} {} + + /** + * Creates a new sl-list with a head node + * @brief Constructor. + * @see sl_list() + * @see ~sl_list() + * @see sl_list(const node& nd) + * @see sl_list(node* const hnd, node* const tnd) + */ + sl_list(node* const nd) + : head{nd}, len{1} { + // If the head is the only node + if (nd->get_next() == nullptr) { + tail = nullptr; + return; + } + + // Traverse the list to get the correct length + node* currNode = new node(*nd); + while(currNode->get_next() != nullptr) { + ++len; + currNode = currNode->get_next(); + } + + // Set the tail to be the end node + tail = currNode; + } + + /** + * Creates a new sl-list with a head node, and a tail node + * @brief Constructor. + * @see sl_list() + * @see ~sl_list() + * @see sl_list(node* const nd) + * @see sl_list(const node& nd) + */ + sl_list(node* const hnd, node* const tnd) + : head{hnd}, tail{tnd}, len{1} { + // Added to avoid any future issues with poor definitions + if (hnd == nullptr || tnd == nullptr) { + head = nullptr; + tail = nullptr; + len = 0; + return; + } + + // Traverse the list until we reach the tail to get the correct length + node* currNode = new node(*hnd); + while(currNode != tnd) { + ++len; + currNode = currNode->get_next(); + } + } + + /** + * Constructs a new sl-list from another sl_list object + * @brief Copy constructor. + * @see sl_list() + * @see ~sl_list() + * @see sl_list(node* const nd) + * @see sl_list(const node& nd) + */ + sl_list(const sl_list& list); + + /** + * Destroys the sl_list object + * @brief Destructor. + * @see sl_list() + * @see sl_list(node* const nd) + * @see sl_list(const node& nd) + * @see sl_list(node* const hnd, node* const tnd) + */ + ~sl_list(); + + /** + * Adds a node with the provided value to the end of the list + * @param T node data + * @returns The list's new tail + * @see push_back(node* const nd) + * @see push_front(T dt) + * @see push_front(node* const nd) + * */ + node* push_back(T dt); + + /** + * Adds a node with the to the end of the list + * @param nd Node to be added + * @returns Thelist's new tail + * @see push_back(T dt) + * @see push_front(T dt) + * @see push_front(node* const nd) + * */ + node* push_back(node* const nd); + + /** + * Adds a node with the provided value to the front of the list + * @param T node data + * @returns The list's new head + * @see push_front(node* const nd) + * @see push_back(T dt) + * @see push_back(node* const nd) + * */ + node* push_front(T dt); + + /** + * Adds a node with the to the front of the list + * @param nd Node to be added + * @returns The list's new head + * @see push_front(T dt) + * @see push_back(T dt) + * @see push_back(node* const nd) + * */ + node* push_front(node* const nd); + + /** + * Removes a node from the end of the list + * @returns The list's new tail + * @see pop_front() + * */ + node* pop_back(); + + /** + * Removes a node from the front of the list + * @returns The list's new head + * @see pop_back() + * */ + node* pop_front(); + + /** + * Returns the head of the sl_list + * @returns Head node + * @see set_head(T dt) + * @see set_head(node* const nd) + * */ + node* get_head() const; + + /** + * Sets the provided node to be the list's head + * @note This may ruin the list, be careful. If you want to swap values, look at void sl_list::set_head(T dt) + * @param nd Node to be the new head + * @see set_head(T dt) + * @see get_head() + */ + void set_head(node* const nd); + + /** + * Changes the head's data to the provided node + * @param dt The head's new data + * @see set_head(node* const nd) + * @see get_head() + */ + void set_head(T dt); + + /** + * Returns the tail of the sl_list + * @returns Tail node + * @see set_tail(T dt) + * @see set_tail(node* const nd) + * */ + node* get_tail() const; + + /** + * Sets the tail of the sl_list to the provided node + * @note This may ruin the list, be careful. If you want to swap values, look at void sl_list::set_tail(T dt) + * @param nd Node to be set as the tail node + * @see set_tail(T dt) + * @see get_tail() + * */ + void set_tail(node* const nd); + + /** + * Sets the data of the tail of the sl_list to the provided data value + * @param dt The new data value the tail will store + * @see set_tail(node* const nd) + * @see get_tail() + * */ + void set_tail(T dt); + + /** + * Inserts the Node into the index provided + * @param nd Node to be inserted + * @param idx Index where the Node will be inserted + * @return Pointer to the Node that is behind the inserted Node + */ + node* insert_node(node* const nd, unsigned int idx); + + /** + * Inserts a value into the index provided + * @param dt Value to be inserted into the list + * @param idx Index where the Node will be inserted + * @return Pointer to the Node that is behind the inserted Node + */ + node* insert_node(T dt, unsigned int idx); + + /** + * Returns the length of the sl_list + * @return Length of the singly-linked list + * @see size() + */ + unsigned int length() { + update_len(); + return len; + } + + /** + * Returns the length of the sl_list + * @return Length of the singly-linked list + * @see length() + */ + unsigned int size() { + update_len(); + return len; + } + + /** + * Updates the length of the sl_list (Mainly kept to avoid bugs, will later implement other features to avoid using this) + */ + void update_len() { + len = 0; + node* currNode = new node(*(this->get_head())); + while (currNode != nullptr) { + currNode = currNode->get_next(); + ++len; + } + } +}; + +template +sl_list::~sl_list() { + while (head) + head = head->get_next(); + + delete head; +} + +template +sl_list::sl_list(const sl_list& list) { + len = list.length(); + + if (list.get_head() == nullptr) + return; + + // Recreate the head + node* newHead = new node(); + newHead->set_data(list.get_head()->get_data()); + head = newHead; + + // Deep-copy the remaining chain + node* currNode = head; + node* sourceNode = list.get_head()->get_next(); + + while(sourceNode->get_next() != nullptr) { + // Create a new Node in the list + currNode->set_next(new node()); + // Set its value to source value + currNode->get_next()->set_data(sourceNode->get_data()); + // Set the destination to null + currNode->get_next()->set_next(nullptr); + // Move over by one Node in the list + currNode = currNode->get_next(); + // Move over by one Node in the source + sourceNode = sourceNode->get_next(); + } + + currNode->set_next(tail); + tail = new node(*sourceNode); +}; + +template +node* sl_list::push_front(T dt) { + // If the list has a length of 0, set the list's head and tail to the same node + if (!len) { + node* newNode = new node(dt); + head = newNode; + tail = newNode; + ++len; + return head; + } + + if (len == 1) { + tail = head; + head = new node(dt); + head->set_next(tail); + ++len; + return head; + } + + // Create a new head object with the provided data and pointing to the head itself + head = new node(head, dt); + ++len; + return head; +} + +template +node* sl_list::push_front(node* const nd) { + // If the list has a length of 0, set the list's head and tail to the same node + if (!len) { + head = nd; + tail = nullptr; + ++len; + return head; + } + + if (len == 1) { + tail = head; + head = new node(*nd); + head->set_next(tail); + ++len; + return head; + } + + // Swap head and nd + auto oldHead = head; + nd->set_next(oldHead); + head = nd; + ++len; + return nd; +} + +template +node* sl_list::push_back(T dt) { + // If the list is empty, set both the head and tail to be the inserted node + if (!len) { + head = new node(dt); + tail = nullptr; + ++len; + return head; + } + + else if (len == 1) { + tail = new node(dt); + head->set_next(tail); + ++len; + return tail; + } + + node* currNode = head; + node* newTail = new node(dt); + node* oldTail = new node(newTail, tail->get_data()); + tail = newTail; + + // Traverse the list + while (currNode->get_next()->get_next() != nullptr) + currNode = currNode->get_next(); + + // Add the Node to the end + currNode->set_next(oldTail); + ++len; + + return tail; +} + +template +node* sl_list::push_back(node* const nd) { + // If the list is empty, then set both the head and the tail to the parameter node + if (!len) { + head = new node(*nd); + tail = nullptr; + ++len; + return head; + } + + else if (len == 1) { + tail = new node(*nd); + head->set_next(tail); + ++len; + return tail; + } + + node* currNode = head; + node* oldTail = new node(nd, tail->get_data()); + tail = nd; + + // Traverse the list + while (currNode->get_next()->get_next() != nullptr) + currNode = currNode->get_next(); + + // Add the Node to the end + currNode->set_next(oldTail); + ++len; + + // Return the tail + return tail; +} + +template +node* sl_list::pop_back() { + if (len <= 0) { + len = 0; + return nullptr; + } + + else if (len == 1) { + --len; + head = nullptr; + tail = nullptr; + return nullptr; + } + + node* currNode = head; + + // Traversing until the second-to-last list Node + while (currNode->get_next()->get_next() != nullptr) + currNode = currNode->get_next(); + + // Set last list member to null + currNode->set_next(nullptr); + tail = currNode; + + --len; + + // Return the new last member + return tail; +} + +template +node* sl_list::pop_front() { + if (len <= 0) { + len = 0; + return nullptr; + } + + if (len == 1) { + --len; + delete head; + delete tail; + return nullptr; + } + + head = head->get_next(); + --len; + return head; +} + +template +node* sl_list::insert_node(node* const nd, unsigned int idx) { + if (idx == 0) { + this->push_front(nd); + return head; + } + + else if (idx >= this->size()) { + throw std::invalid_argument("Provided index exceeds list length. Use push_back().\n"); + } + + node* currentNode = head; + unsigned int counter = 0; + while (counter < idx - 1) { + currentNode = currentNode->get_next(); + ++counter; + } + node* nextAfter = currentNode->get_next(); + currentNode->set_next(nd); + nd->set_next(nextAfter); + + ++len; + + return nd; +} + +template +node* sl_list::insert_node(const T dt, unsigned int idx) { + if (idx == 0) { + this->push_front(dt); + return head; + } + + else if (idx >= this->size()) { + throw std::invalid_argument("Provided index exceeds list length. Use push_back().\n"); + } + + node* currentNode = head; + unsigned int counter = 0; + while (counter < idx - 1) { + currentNode = currentNode->get_next(); + ++counter; + } + + currentNode->set_next(new node(currentNode->get_next(), dt)); + ++len; + + return currentNode->get_next(); +} + +template +node* sl_list::get_head() const { + return head; +} + +template +void sl_list::set_head(node* const nd) { + head = nd; +} + +template +void sl_list::set_head(T dt) { + this->pop_front(); + this->push_front(dt); +} + +template +node* sl_list::get_tail() const { + return tail; +} + +template +void sl_list::set_tail(node* const nd) { + this->pop_back(); + this->push_back(nd); +} + +template +void sl_list::set_tail(T dt) { + this->pop_back(); + this->push_back(dt); +} + +#endif // SINGLY_LINKED_LIST_H \ No newline at end of file