From 6e9e3ecd4dfc24a9726c57e0c5a0349a38802253 Mon Sep 17 00:00:00 2001 From: Christopher Sanden Date: Fri, 21 Nov 2025 12:51:05 +0100 Subject: [PATCH] Pushing work to remote --- Exam/IKT203Exam/CMakeLists.txt | 2 - Exam/IKT203Exam/LibExample/CMakeLists.txt | 32 -- .../TCircularDoublyLinkedListTemplate.hpp | 454 --------------- .../LibExample/TDoublyLinkedListTemplate.hpp | 340 ----------- .../LibExample/TSingleLinkedListTemplate.hpp | 529 ------------------ Exam/IKT203Exam/LibExample/list.hpp | 309 ---------- Exam/IKT203Exam/LibExample/queue.hpp | 73 --- Exam/IKT203Exam/LibExample/stack.hpp | 79 --- .../Portfolio/Assignment-03/option1.cpp | 2 + Exam/IKT203Exam/deploy.ps1 | 58 -- TheAlgorithmicOrganizer/.idea/.gitignore | 8 + .../.idea/TheAlgoeithmicOrganizer.iml | 2 + TheAlgorithmicOrganizer/.idea/editor.xml | 343 ++++++++++++ .../.idea/material_theme_project_new.xml | 12 + TheAlgorithmicOrganizer/.idea/misc.xml | 7 + TheAlgorithmicOrganizer/.idea/modules.xml | 8 + TheAlgorithmicOrganizer/.idea/vcs.xml | 6 + 17 files changed, 388 insertions(+), 1876 deletions(-) delete mode 100644 Exam/IKT203Exam/LibExample/CMakeLists.txt delete mode 100644 Exam/IKT203Exam/LibExample/TCircularDoublyLinkedListTemplate.hpp delete mode 100644 Exam/IKT203Exam/LibExample/TDoublyLinkedListTemplate.hpp delete mode 100644 Exam/IKT203Exam/LibExample/TSingleLinkedListTemplate.hpp delete mode 100644 Exam/IKT203Exam/LibExample/list.hpp delete mode 100644 Exam/IKT203Exam/LibExample/queue.hpp delete mode 100644 Exam/IKT203Exam/LibExample/stack.hpp delete mode 100644 Exam/IKT203Exam/deploy.ps1 create mode 100644 TheAlgorithmicOrganizer/.idea/.gitignore create mode 100644 TheAlgorithmicOrganizer/.idea/TheAlgoeithmicOrganizer.iml create mode 100644 TheAlgorithmicOrganizer/.idea/editor.xml create mode 100644 TheAlgorithmicOrganizer/.idea/material_theme_project_new.xml create mode 100644 TheAlgorithmicOrganizer/.idea/misc.xml create mode 100644 TheAlgorithmicOrganizer/.idea/modules.xml create mode 100644 TheAlgorithmicOrganizer/.idea/vcs.xml diff --git a/Exam/IKT203Exam/CMakeLists.txt b/Exam/IKT203Exam/CMakeLists.txt index 4dd6f96..b77f5a3 100644 --- a/Exam/IKT203Exam/CMakeLists.txt +++ b/Exam/IKT203Exam/CMakeLists.txt @@ -21,8 +21,6 @@ endif() # The order matters here: we add LibExample first so that its library is # defined before the executables that need to link to it. -add_subdirectory(LibExample) -add_subdirectory(Submissions) add_subdirectory(Portfolio) # --- End of File --- \ No newline at end of file diff --git a/Exam/IKT203Exam/LibExample/CMakeLists.txt b/Exam/IKT203Exam/LibExample/CMakeLists.txt deleted file mode 100644 index ddcd46e..0000000 --- a/Exam/IKT203Exam/LibExample/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -# --- Step 1: Create the Library --- - -# Define a library target named "LibExample". -# We use INTERFACE because it only contains .hpp files (header-only). -# There are no .cpp files to compile here. -# TODO: Change to STATIC if you add .cpp files later. -add_library(LibExample INTERFACE) - -# --- Step 2: Add Header Files to the Library --- - -# This command explicitly lists the header files that belong to the library. -# This helps Visual Studio display them nicely in the Solution Explorer. -target_sources(LibExample - PUBLIC - list.hpp - TSingleLinkedListTemplate.hpp - TDoublyLinkedListTemplate.hpp - TCircularDoublyLinkedListTemplate.hpp - queue.hpp - stack.hpp -) - -# --- Step 3: Make Headers "Findable" --- - -# This is the most important command here. -# It tells any other project that links to "LibExample" to add this -# directory (CMAKE_CURRENT_SOURCE_DIR) to its list of include paths. -# This is what allows you to write #include "list.hpp" in your main.cpp. -# Note: CMAKE_CURRENT_SOURCE_DIR is a built-in variable that points to the directory -target_include_directories(LibExample INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) -#TODO: Change INTERFACE to PUBLIC if you add .cpp files later. - diff --git a/Exam/IKT203Exam/LibExample/TCircularDoublyLinkedListTemplate.hpp b/Exam/IKT203Exam/LibExample/TCircularDoublyLinkedListTemplate.hpp deleted file mode 100644 index 22a670f..0000000 --- a/Exam/IKT203Exam/LibExample/TCircularDoublyLinkedListTemplate.hpp +++ /dev/null @@ -1,454 +0,0 @@ -// Implantation of the Circular Doubly Linked List - -#ifndef TCIRCULARDOUBLYLINKEDLISTTEMPLATE_HPP -#define TCIRCULARDOUBLYLINKEDLISTTEMPLATE_HPP -#pragma once - -#include "TDoublyLinkedListTemplate.hpp" - -template -class TCircularDoublyLinkedList : public TDoublyLinkedList { -private: - - // Helper to remove a node, updating both next and prev pointers - void InternalRemoveNode(TNode* aNodeToDelete); - -protected: - // --- New Member Variable --- - TNode* cursor; // Points to the "current" node in the list. - -public: - using TSingleLinkedList::Append; - using TSingleLinkedList::Prepend; - - // --- Constructor & Destructor --- - TCircularDoublyLinkedList(bool aIsDataOwner); - virtual ~TCircularDoublyLinkedList() override; - - // --- New Cursor Management Methods --- - void ResetCursor(); - T GetCursorData() const; - void AdvanceCursor(int aSteps = 1); - void RewindCursor(int aSteps = 1); - int GetCursorIndex() const; - - - // --- Overridden Virtual Methods --- - // For maintaining the circular link - void Append(const T&) override; - void Prepend(const T&) override; - void Remove(const T&) override; - void RemoveAll(const T&) override; - T RemoveLast() override; - void Reverse() override; - void ReverseSublist(int, int) override; - void Merge(TSingleLinkedList& otherList) override; - - // For avoiding infinite loops - bool Contains(const T&) const override; - T Search(const T&, FCheckNode) const override; - void ForEach(FVisitNode) const override; - TNode* GetMiddle() const override; -}; - -// Constructor: Establishes the initial circular link where the head points to itself. -template -TCircularDoublyLinkedList::TCircularDoublyLinkedList(bool aIsDataOwner) - : TDoublyLinkedList(aIsDataOwner) { - // An empty circular list's dummy head points to itself. - this->head->SetNext(this->head); - this->head->SetPrev(this->head); - this->cursor = this->head; // Cursor also starts at the head. -} - -// Destructor: The parent destructors are virtual and will handle cleanup. -template -TCircularDoublyLinkedList::~TCircularDoublyLinkedList() { - // Before the parent destructors run, we must break the circular link. - // The parent's `nullptr`-terminated cleanup loop will now work correctly. - if (!this->IsEmpty()) { - // The tail is the node before the dummy head. - // Set its 'next' pointer to null instead of back to the head. - this->head->GetPrev()->SetNext(nullptr); - } - // Now, the chain is broken: head -> node1 -> ... -> tail -> nullptr - // The TDoublyLinkedList and TSingleLinkedList destructors will be called - // automatically after this, and they will now function correctly. -} - -// Moves the cursor to the first element in the list. -template -void TCircularDoublyLinkedList::ResetCursor() { - if (this->IsEmpty()) { - this->cursor = this->head; - } - else { - this->cursor = this->head->GetNext(); - } -} - -// Returns the data at the cursor's current position. -template -T TCircularDoublyLinkedList::GetCursorData() const { - // The cursor is only valid if it's not pointing to the dummy head. - if (!this->IsEmpty() && this->cursor != this->head) { - return this->cursor->GetData(); - } - return nullptr; -} - -// Moves the cursor forward, wrapping around if needed. -template -void TCircularDoublyLinkedList::AdvanceCursor(int aSteps) { - if (this->IsEmpty()) { - return; - } - - for (int i = 0; i < aSteps; ++i) { - this->cursor = this->cursor->GetNext(); - // If we move to the dummy head, we've wrapped around. Skip over it to the first element. - if (this->cursor == this->head) { - this->cursor = this->head->GetNext(); - } - } -} - -// Moves the cursor backward, wrapping around if needed. -template -void TCircularDoublyLinkedList::RewindCursor(int aSteps) { - if (this->IsEmpty()) { - return; - } - - for (int i = 0; i < aSteps; ++i) { - this->cursor = this->cursor->GetPrev(); - // If we move to the dummy head, we've wrapped around. Skip over it to the last element. - if (this->cursor == this->head) { - this->cursor = this->head->GetPrev(); - } - } -} - -// Gets the numerical index of the cursor's current position. -template -int TCircularDoublyLinkedList::GetCursorIndex() const { - if (this->IsEmpty() || this->cursor == this->head) { - return -1; - } - - int index = 0; - TNode* current = this->head->GetNext(); - - // Traverse the list safely, knowing it will eventually loop back to the head. - while (current != this->head) { - if (current == this->cursor) { - return index; - } - current = current->GetNext(); - index++; - } - - return -1; // Should not be reached if cursor is valid. -} - -// Appends a node to the end of the list (before the dummy head). -// Use the InternAppend from TDoublyLinkedList for basic logic, then adjust prev pointers. -template -void TCircularDoublyLinkedList::Append(const T& aData) { - // 1. Let the base class do ALL the standard work. - TDoublyLinkedList::Append(aData); - // 2. Now fix the circular links. - if(!this->IsEmpty()) { - this->head->SetPrev(this->tail); // Dummy head's prev points to new tail - this->tail->SetNext(this->head); // New tail's next points to dummy head - } -} - -// Prepends a node to the beginning of the list (after the dummy head). -// Use the Prepend from TDoublyLinkedList, this will handle all the logic. -template -void TCircularDoublyLinkedList::Prepend(const T& aData) { - TDoublyLinkedList::Prepend(aData); - // No need to adjust circular links, as TDoublyLinkedList::Prepend already does it. -} - - -template -void TCircularDoublyLinkedList::InternalRemoveNode(TNode* aNodeToDelete) { - if (aNodeToDelete == nullptr || aNodeToDelete == this->head) return; // Invalid input - - // 1. Update cursor if it points to the node being deleted - if (this->cursor == aNodeToDelete) { - this->cursor = aNodeToDelete->GetNext(); - } - - //2. Update tail if the last node is being removed - if (aNodeToDelete == this->tail) { - this->tail = aNodeToDelete->GetPrev(); - } - - // 3. Relink neighbors (this maintains the circle automatically) - TNode* prevNode = aNodeToDelete->GetPrev(); - TNode* nextNode = aNodeToDelete->GetNext(); - prevNode->SetNext(nextNode); - nextNode->SetPrev(prevNode); - - // 4. Delete data if owned, then delete the node - if (this->isDataOwner) { - delete aNodeToDelete->GetData(); - } - delete aNodeToDelete; - this->size--; - - // 5. If the list is now empty, ensure tail and cursor point to the head. - if (this->IsEmpty()) { - this->tail = this->head; - this->cursor = this->head; - } -} - -// Removes the first node with the given value. -template -void TCircularDoublyLinkedList::Remove(const T& aData) { - if (this->IsEmpty()) return; - - // Start searching from the first actual node - TNode* current = this->head->GetNext(); - // Traverse the entire circle once - for (int i = 0; i < this->size; ++i) { - if (current->GetData() == aData) { - TNode* prevNode = current->GetPrev(); - TNode* nextNode = current->GetNext(); - - // Update tail if the last node is being removed - if (current == this->tail) { - this->tail = prevNode; - } - - // Relink neighbors (this maintains the circle automatically) - prevNode->SetNext(nextNode); - nextNode->SetPrev(prevNode); - - if (this->isDataOwner) { - delete current->GetData(); - } - delete current; - this->size--; - return; - } - current = current->GetNext(); - } -} - -// Removes the last element from the list. -template -T TCircularDoublyLinkedList::RemoveLast() { - if (this->IsEmpty()) { - return nullptr; - } - - TNode* nodeToRemove = this->tail; - T dataToReturn = nodeToRemove->GetData(); - TNode* newTail = nodeToRemove->GetPrev(); - - // Relink the new tail to the head to maintain the circle - newTail->SetNext(this->head); - this->head->SetPrev(newTail); - - this->tail = newTail; // Update tail pointer - - delete nodeToRemove; - this->size--; - - if (this->IsEmpty()) { - this->tail = this->head; // Reset tail if list is now empty - } - - return dataToReturn; -} - -// Removes all occurrences of a given value using a safe, bounded loop. -template -void TCircularDoublyLinkedList::RemoveAll(const T& aData) { - if (this->IsEmpty()) return; - - TNode* current = this->head->GetNext(); - int initialSize = this->size; // Loop based on the original size - - for (int i = 0; i < initialSize; ++i) { - TNode* nextNode = current->GetNext(); // Get next node before potential deletion - - if (current->GetData() == aData) { - TNode* prevNode = current->GetPrev(); - - if (current == this->tail) { - this->tail = prevNode; - } - - prevNode->SetNext(nextNode); - nextNode->SetPrev(prevNode); - - if (this->isDataOwner) { - delete current->GetData(); - } - delete current; - this->size--; - } - current = nextNode; - } - if (this->IsEmpty()) { - this->tail = this->head; - } -} - -// Reverses the entire list by swapping the next/prev pointers of every node. -template -void TCircularDoublyLinkedList::Reverse() { - if (this->size <= 1) return; // Nothing to reverse - - // 1. Keep track of original head and tail nodes. - TNode* newFirstNode = this->tail; - - // 2. Iterate through all nodes, swapping next and prev pointers. - TNode* current = this->head; - // We must loop size + 1 times to include the dummy head in the pointer swap. - for (int i = 0; i < this->size + 1; ++i) { - current->SwapNextPrev(); - // The *new* prev pointer is the *original* next pointer, so this moves us forward. - current = current->GetPrev(); - } - - // 3. Correct the head and tail pointers. - this->tail = this->head->GetNext(); // The old head is the new tail. - this->head->SetNext(newFirstNode); // The dummy head now points to the old tail. - newFirstNode->SetPrev(this->head); // New first node's prev points to dummy head. -} - -// Reverses a portion of the list, ensuring circular links are maintained. -template -void TCircularDoublyLinkedList::ReverseSublist(int start, int end) { - if (start < 0 || end >= this->size || start >= end) { - return; - } - - // --- 1. Find boundary nodes --- - TNode* startNode = this->head->GetNext(); - for (int i = 0; i < start; ++i) { - startNode = startNode->GetNext(); - } - - TNode* endNode = startNode; - for (int i = start; i < end; ++i) { - endNode = endNode->GetNext(); - } - - TNode* startPrev = startNode->GetPrev(); - TNode* endNext = endNode->GetNext(); - - // --- 2. Reverse pointers for all nodes within the sublist --- - TNode* current = startNode; - for (int i = 0; i <= (end - start); ++i) { - TNode* temp = current->GetNext(); - current->SetNext(current->GetPrev()); - current->SetPrev(temp); - current = temp; - } - - // --- 3. Re-stitch the sublist (no nullptr checks needed) --- - startPrev->SetNext(endNode); - endNode->SetPrev(startPrev); - startNode->SetNext(endNext); - endNext->SetPrev(startNode); - - // Update tail pointer if it was part of the reversed segment - if (this->head->GetPrev() == endNode) { // Original startNode is now at the end - this->tail = startNode; - } -} - -// Merges another sorted list, creating a single, sorted circular list. -template -void TCircularDoublyLinkedList::Merge(TSingleLinkedList& otherList) { - // We can call the parent implementation to do the heavy lifting of merging. - TDoublyLinkedList::Merge(otherList); - - // The parent merge results in a null-terminated list. We just need to fix the ends. - if (!this->IsEmpty()) { - TNode* firstNode = this->head->GetNext(); - this->tail->SetNext(firstNode); - firstNode->SetPrev(this->tail); - } -} - -// Applies a function to each node using a safe loop for a circular list. -template -void TCircularDoublyLinkedList::ForEach(FVisitNode aVisitNode) const { - if (aVisitNode == nullptr || this->IsEmpty()) { - return; - } - - TNode* current = this->head->GetNext(); - int index = 0; - while (current != this->head) { - aVisitNode(current->GetData(), index); - current = current->GetNext(); - index++; - } -} - -// Checks if a value is in the list using a safe, non-infinite loop. -template -bool TCircularDoublyLinkedList::Contains(const T& aData) const { - if (this->IsEmpty()) { - return false; - } - - TNode* current = this->head->GetNext(); - while (current != this->head) { - if (current->GetData() == aData) { - return true; - } - current = current->GetNext(); - } - return false; -} - -// Searches for a value using a safe, non-infinite loop. -template -T TCircularDoublyLinkedList::Search(const T& aData, FCheckNode aCheckNode) const { - if (this->IsEmpty()) { - return nullptr; - } - - TNode* current = this->head->GetNext(); - while (current != this->head) { - if (aCheckNode != nullptr) { - if (aCheckNode(current->GetData(), aData)) { - return current->GetData(); - } - } - else { - if (current->GetData() == aData) { - return current->GetData(); - } - } - current = current->GetNext(); - } - return nullptr; -} - -// Finds the middle node by traversing to the size/2 index. -template -TNode* TCircularDoublyLinkedList::GetMiddle() const { - if (this->IsEmpty()) return nullptr; - - // The safest way for a list where we know the size. - int middleIndex = this->size / 2; - TNode* current = this->head->GetNext(); - for (int i = 0; i < middleIndex; ++i) { - current = current->GetNext(); - } - return current; -} - -#endif // TCIRCULARDOUBLYLINKEDLISTTEMPLATE_HPP diff --git a/Exam/IKT203Exam/LibExample/TDoublyLinkedListTemplate.hpp b/Exam/IKT203Exam/LibExample/TDoublyLinkedListTemplate.hpp deleted file mode 100644 index 3a2e438..0000000 --- a/Exam/IKT203Exam/LibExample/TDoublyLinkedListTemplate.hpp +++ /dev/null @@ -1,340 +0,0 @@ -// TDoublyLinkedList implements a doubly linked list data structure with basic functionalities. - -#ifndef TDOUBLYLINKEDLISTTEMPLEATE_HPP -#define TDOUBLYLINKEDLISTTEMPLEATE_HPP -#pragma once -#include "TSingleLinkedListTemplate.hpp" - -// Doubly Linked List inheriting from TSingleLinkedList -template -class TDoublyLinkedList : public TSingleLinkedList { -private: - // Internal helper to remove a node, updating both next and prev pointers - void InternalRemoveNode(TNode* aNodeToDelete); - -public: - using TSingleLinkedList::Append; - using TSingleLinkedList::Prepend; - - // --- Constructor & Destructor --- - // Constructor calls the base class's constructor to initialize common members. - TDoublyLinkedList(bool aIsDataOwner); - - // The destructor is also virtual, ensuring the correct cleanup chain. - virtual ~TDoublyLinkedList() override; - - - // --- Overridden Virtual Methods from TSingleLinkedList --- - // These methods provide new implementations to manage the 'prev' pointer - // and/or to improve performance. - virtual void Append(const T&) override; - virtual void Prepend(const T&) override; - virtual T GetAtIndex(int) override; - virtual void Remove(const T&) override; - virtual void Reverse() override; - virtual void Merge(TSingleLinkedList&) override; - virtual void RemoveAll(const T&) override; - virtual void ReverseSublist(int, int) override; - virtual T RemoveLast(); - - - // --- New Methods Unique to TDoublyLinkedList --- - // These methods leverage the 'prev' pointer for capabilities that are - // inefficient or impossible in a singly-linked list. - - void InsertBefore(TNode*, T&); - void ForEachReverse(FVisitNode) const; -}; - - -template -inline void TDoublyLinkedList::InternalRemoveNode(TNode* aNodeToDelete) -{ - if (aNodeToDelete == nullptr || aNodeToDelete == this->head) return; - TNode* prevNode = aNodeToDelete->GetPrev(); - TNode* nextNode = aNodeToDelete->GetNext(); - if (prevNode != nullptr) { - prevNode->SetNext(nextNode); - } - if (nextNode != nullptr) { - nextNode->SetPrev(prevNode); - } - if (aNodeToDelete == this->tail) { - this->tail = prevNode; - } - if (this->isDataOwner) { - delete aNodeToDelete->GetData(); - } - delete aNodeToDelete; - this->size--; -} - -// Constructor: Calls the base class constructor to perform initialization. -template -TDoublyLinkedList::TDoublyLinkedList(bool aIsDataOwner) - : TSingleLinkedList(aIsDataOwner) {} - -// Destructor: The base class destructor is virtual, so this is called automatically. -// No new resources were allocated, so the body can be empty. -template -TDoublyLinkedList::~TDoublyLinkedList() {} // No additional cleanup needed, the base class handles it. - -// Append: Overridden to correctly set the 'prev' pointer on the new node. -template -void TDoublyLinkedList::Append(const T& aData) { - TNode* oldTail = this->tail; - TNode* newNode = this->InternAppend(aData); - newNode->SetPrev(oldTail); // Set the new node's prev to the old tail -} - -// Prepend: Overridden to correctly set 'prev' pointers on the new node and its old neighbor. -template -void TDoublyLinkedList::Prepend(const T& aData) { - TNode* newNode = this->InternPrepend(aData); - newNode->SetPrev(this->head); // New node's prev points to dummy head - if (newNode->GetNext() != nullptr) { - newNode->GetNext()->SetPrev(newNode); // Old first node's prev points to new node - } -} - -// GetAtIndex: Re-introduces the performance optimization to search from the tail. -template -T TDoublyLinkedList::GetAtIndex(int aIndex) { - if (aIndex < 0 || aIndex >= this->size) { - return nullptr; // Index out of bounds - } - - TNode* current; - // Check which end is closer and traverse from there. - if (aIndex < this->size / 2) { - current = this->head->GetNext(); - for (int i = 0; i < aIndex; i++) { - current = current->GetNext(); - } - } - else { - current = this->tail; - for (int i = this->size - 1; i > aIndex; i--) { - current = current->GetPrev(); - } - } - return current->GetData(); -} - -// Remove: Removes all nodes matching the given value. -template -void TDoublyLinkedList::Remove(const T& aData) { - TNode* current = this->head->GetNext(); - while (current != nullptr) { - if (current->GetData() == aData) { - TNode* nodeToRemove = current; - current = current->GetNext(); // Move current forward before deletion - InternalRemoveNode(nodeToRemove); - } - else { - // No match, just advance current - current = current->GetNext(); - } - } -} - -// Reverse: Uses the much simpler algorithm of swapping prev/next pointers. -template -void TDoublyLinkedList::Reverse() { - if (this->size <= 1) return; - - // 1. Keep track of original head and tail nodes. - TNode* originalHeadNode = this->head->GetNext(); - TNode* originalTailNode = this->tail; - - // 2. Swap prev/next for every node. - TNode* current = originalHeadNode; - while (current != nullptr) { - current->SwapNextPrev(); - // The *new* prev pointer is the *original* next pointer, so this moves us forward. - current = current->GetPrev(); - } - - // 3. Correct the pointers for the new head and tail. - this->tail = originalHeadNode; // The old head is the new tail. - this->head->SetNext(originalTailNode); // The dummy head now points to the old tail. -} - -// RemoveLast: Removes the final element in O(1) time. -// Note: This returns the data, so the caller is now responsible for it. -// The data itself is not deleted, even if isDataOwner is true. -template -T TDoublyLinkedList::RemoveLast() { - if (this->IsEmpty()) { - return nullptr; - } - - TNode* nodeToRemove = this->tail; - T dataToReturn = nodeToRemove->GetData(); - - this->tail = this->tail->GetPrev(); - this->tail->SetNext(nullptr); - - delete nodeToRemove; - this->size--; - - return dataToReturn; -} - -// InsertBefore: Inserts a new node before a specified node in O(1) time. -template -void TDoublyLinkedList::InsertBefore(TNode* aNode, T& aData) { - if (aNode == nullptr || aNode == this->head) { - // Cannot insert before a null node or the dummy head - return; - } - - // If inserting before the first element, Prepend is easier. - if (aNode == this->head->GetNext()) { - Prepend(aData); - return; - } - - TNode* newNode = new TNode(aData); - TNode* prevNode = aNode->GetPrev(); - - // Link new node to its neighbors - newNode->SetPrev(prevNode); - newNode->SetNext(aNode); - - // Update neighbors to point to the new node - prevNode->SetNext(newNode); - aNode->SetPrev(newNode); - - this->size++; -} - -// ForEachReverse: Traverses the list backward from tail to head. -template -void TDoublyLinkedList::ForEachReverse(FVisitNode aVisitNode) const { - if (aVisitNode == nullptr) { - return; - } - TNode* current = this->tail; - int index = this->size - 1; - while (current != this->head) { - aVisitNode(current->GetData(), index); - current = current->GetPrev(); - index--; - } -} - -template -void TDoublyLinkedList::Merge(TSingleLinkedList& otherList) { - if (otherList.IsEmpty()) { - return; - } - - int otherSize = otherList.GetSize(); - // Call the now-public StealNodes to legally take ownership of the nodes. - TNode* p2 = otherList.StealNodes(); - - if (this->IsEmpty()) { - this->head->SetNext(p2); - if (p2) p2->SetPrev(this->head); - this->size = otherSize; - // Find the new tail by traversing. - TNode* newTail = this->head; - while (newTail->GetNext() != nullptr) { - newTail = newTail->GetNext(); - } - this->tail = newTail; - return; - } - - TNode* p1 = this->head->GetNext(); - TNode* currentTail = this->head; - - while (p1 != nullptr && p2 != nullptr) { - if (p1->GetData() <= p2->GetData()) { - currentTail->SetNext(p1); - p1->SetPrev(currentTail); - p1 = p1->GetNext(); - } - else { - currentTail->SetNext(p2); - p2->SetPrev(currentTail); - p2 = p2->GetNext(); - } - currentTail = currentTail->GetNext(); - } - - TNode* remainder = (p1 != nullptr) ? p1 : p2; - currentTail->SetNext(remainder); - if (remainder != nullptr) { - remainder->SetPrev(currentTail); - } - - this->size += otherSize; - // After merging, find the new tail by traversing from where we left off. - while (currentTail->GetNext() != nullptr) { - currentTail = currentTail->GetNext(); - } - this->tail = currentTail; -} - -// Remove: Removes all nodes matching the given value. -template -void TDoublyLinkedList::RemoveAll(const T& aValue) { - TNode* current = this->head->GetNext(); - while (current != nullptr) { - if (current->GetData() == aValue) { - TNode* nodeToRemove = current; - current = current->GetNext(); // Move current forward before deletion - InternalRemoveNode(nodeToRemove); - } - else { - // No match, just advance the pointer - current = current->GetNext(); - } - } -} - -// ReverseSublist: Reverses a portion of the list between two indices (inclusive). -template -void TDoublyLinkedList::ReverseSublist(int start, int end) { - if (start < 0 || end >= this->size || start >= end) return; - - // --- 1. Find boundary nodes --- - TNode* startNode = this->head->GetNext(); - TNode* endNode = startNode; - - for (int i = 0; i < start; ++i) { - startNode = startNode->GetNext(); - } - for (int i = start; i < end; ++i) { - endNode = endNode->GetNext(); - } - - TNode* startPrev = startNode->GetPrev(); - TNode* endNext = endNode->GetNext(); - - // --- 2. Reverse pointers for all nodes within the sublist --- - TNode* current = startNode; - while (current != endNext) { - TNode* temp = current->GetNext(); - current->SetNext(current->GetPrev()); - current->SetPrev(temp); - current = temp; // Move to the original next node - } - - // --- 3. Re-stitch the reversed sublist into the main list --- - startPrev->SetNext(endNode); - endNode->SetPrev(startPrev); - - startNode->SetNext(endNext); - if (endNext != nullptr) { - endNext->SetPrev(startNode); - } - else { - // If we reversed to the end, the original startNode is the new tail - this->tail = startNode; - } -} - -#endif // !TDOUBLYLINKEDLISTTEMPLEATE_HPP diff --git a/Exam/IKT203Exam/LibExample/TSingleLinkedListTemplate.hpp b/Exam/IKT203Exam/LibExample/TSingleLinkedListTemplate.hpp deleted file mode 100644 index f985a6d..0000000 --- a/Exam/IKT203Exam/LibExample/TSingleLinkedListTemplate.hpp +++ /dev/null @@ -1,529 +0,0 @@ -#ifndef TSINGLELINKEDLIST_HPP -#define TSINGLELINKEDLIST_HPP - -#pragma once - -#include // Required for the Clone function, and prevent delete on non-pointer types -#include "TDoublyLinkedListTemplate.hpp" -#include "TCircularDoublyLinkedListTemplate.hpp" - -template -class TDoublyLinkedList; // Forward declaration for friendship -template -class TCircularDoublyLinkedList; // Forward declaration for friendship - -// Callback type definitions -template -using FDataFactory = T(*)(TArgs); // <-- ADD THIS LINE - -template -using FCheckNode = bool(*)(const T, const T); - -template -using FVisitNode = void(*)(const T, int); - -template -class TNode { -private: - T data; // Data of type T (e.g., TSong*) - TNode* next; // Pointer to the next node - TNode* prev; // Pointer to the previous node, prepared for future use - - void SwapNextPrev(); // Swaps the next and prev pointers of this node -public: - // Constructor - - TNode(const T& aData); - - // Destructor - ~TNode(); - - // Getters - T GetData() const { return data; } - TNode* GetNext() const { return next; } - TNode* GetPrev() const { return prev; } - - // Setters - void SetNext(TNode* aNextNode) { next = aNextNode; } - void SetPrev(TNode* aPrevNode) { prev = aPrevNode; } - - // Add friendships here if needed - friend class TDoublyLinkedList; - friend class TCircularDoublyLinkedList; -}; - -// --- Method Implementations --- -// Constructor: Initializes the node with data from the factory function -template -TNode::TNode(const T& aData) : data(aData), next(nullptr), prev(nullptr) {} - -// Destructor: Deletes the data pointer -template -TNode::~TNode() { - //Do not delete data, data may exist outside the list - data = nullptr; // Set data to nullptr to avoid dangling pointer - next = nullptr; // Set next to nullptr to avoid dangling pointer - prev = nullptr; // Set prev to nullptr to avoid dangling pointer -} - -template -void TNode::SwapNextPrev() { - TNode* temp = next; - next = prev; - prev = temp; -} - -// --- End of TNode class --- - -// Singly Linked List TSingleLinkedList using TNode and dummy node -template -class TSingleLinkedList { -private: - // Helper to reset the list to empty state - void ResetList(); - -protected: - TNode* head; // Pointer to the dummy head node - TNode* tail; // Pointer to the tail node - int size; // Current size of the list - bool isDataOwner; // Indicates if the list owns the data - - // Internal implementations can be non-virtual - TNode* InternAppend(const T&); - TNode* InternPrepend(const T&); - - // Helper for RemoveAll to delete a node given its previous node - void InternalRemoveNode(TNode*, TNode*); - // Helper to get node at index (non-virtual, used internally) - TNode* GetNodeAtIndex(int aIndex) const; - -public: - // Constructor - TSingleLinkedList(bool); - // Virtual Destructor - virtual ~TSingleLinkedList(); - - // --- Core Operations (Virtual) --- - virtual void Append(const T&); - virtual void Prepend(const T&); - virtual T GetAtIndex(int); - virtual void Remove(const T&); - virtual void Reverse(); - virtual void RemoveAll(const T&); - virtual void ReverseSublist(int, int); - virtual TNode* GetMiddle() const; - virtual void Merge(TSingleLinkedList&); - - // --- Traversal functions that MUST now be virtual --- - virtual bool Contains(const T&) const; - virtual T Search(const T&, FCheckNode = nullptr) const; - virtual void ForEach(FVisitNode) const; - - // --- Non-Virtual Methods --- - template - T Append(FDataFactory, TArgs); - template - T Prepend(FDataFactory, TArgs); - int GetSize() const; - bool IsEmpty() const; - TSingleLinkedList Clone() const; - TNode* StealNodes(); -}; - -// Constructor: Initializes the dummy head node and list state -template -TSingleLinkedList::TSingleLinkedList(bool aIsDataOwner) - : head(new TNode(nullptr)), tail(head), size(0), isDataOwner(aIsDataOwner) { - // COMPILE-TIME SAFETY CHECK - // If the user tries to create a list of non-pointer types with ownership, - // stop compilation with a static_assert. - static_assert(std::is_pointer::value || !aIsDataOwner, - "isDataOwner can only be true if T is a pointer type (e.g., std::string*)."); -} - -// Virtual Destructor: Deletes all nodes and, if owner, the data -template -TSingleLinkedList::~TSingleLinkedList() { - TNode* current = head; - while (current != nullptr) { - TNode* nextNode = current->GetNext(); - if (isDataOwner && current->GetData() != nullptr) { - delete current->GetData(); // Delete data if the list owns it - } - delete current; // Free the node itself - current = nextNode; - } -} - -template -void TSingleLinkedList::InternalRemoveNode(TNode* aPrevNode, TNode* aNodeToDelete) { - if (aPrevNode == nullptr || aNodeToDelete == nullptr) return; - aPrevNode->SetNext(aNodeToDelete->GetNext()); - if (aNodeToDelete == this->tail) { - this->tail = aPrevNode; - } - if (this->isDataOwner) { - delete aNodeToDelete->GetData(); - } - delete aNodeToDelete; - this->size--; -} - - -// StealNodes: Detaches and returns the list's nodes, leaving it empty -// Uses ResetList to clear the list state -template -TNode* TSingleLinkedList::StealNodes() { - TNode* stolenHead = head->GetNext(); // First actual node - this->ResetList(); // Clear the list to empty state - return stolenHead; // Return the detached nodes -} - -// InternAppend: Handles the logic of adding a node to the end -template -TNode* TSingleLinkedList::InternAppend(const T& aData) { - TNode* newNode = new TNode(aData); - tail->SetNext(newNode); // Link the old tail to the new node - tail = newNode; // Update the tail pointer - size++; - return newNode; -} - -// Public Append method -template -void TSingleLinkedList::Append(const T& aData) { - InternAppend(aData); -} - -// InternPrepend: Handles the logic of adding a node to the beginning -template -TNode* TSingleLinkedList::InternPrepend(const T& aData) { - TNode* newNode = new TNode(aData); - newNode->SetNext(head->GetNext()); - head->SetNext(newNode); - if (tail == head) { // If the list was empty, new node is also the tail - tail = newNode; - } - size++; - return newNode; -} - -// Public Prepend method -template -void TSingleLinkedList::Prepend(const T& aData) { - InternPrepend(aData); -} - -// Append(): Creates a new node with the given factory and returns the new node's data. -template -template -T TSingleLinkedList::Append(FDataFactory aDataFactory, TArgs aArgs) { - if (aDataFactory == nullptr) { - return nullptr; // Return nullptr if no factory is provided - } - T newData = aDataFactory(aArgs); - this->Append(newData); // Call the existing virtual Append(T) method - return newData; -} - -// Prepend(): Creates a new node with the given factory and returns the new node's data. -template -template -T TSingleLinkedList::Prepend(FDataFactory aDataFactory, TArgs aArgs) { - if (aDataFactory == nullptr) { - return nullptr; // Return nullptr if no factory is provided - } - T newData = aDataFactory(aArgs); - this->Prepend(newData); // Call the existing virtual Prepend(T) method - return newData; -} - - -template -TNode* TSingleLinkedList::GetNodeAtIndex(int aIndex) const { - TNode* current = head->GetNext(); // Start at the first actual node - for (int i = 0; i < aIndex; ++i) { - current = current->GetNext(); - } - return current; -} - -// GetAtIndex: Returns the value at a specified index. -// This version iterates from the beginning only, as it cannot go backward. -template -T TSingleLinkedList::GetAtIndex(int aIndex) { - if (aIndex < 0 || aIndex >= size) { - return nullptr; // Index out of bounds - } - return GetNodeAtIndex(aIndex)->GetData(); -} - -// Remove: Removes the first node matching the given value. -// Requires tracking the previous node to relink the list. -template -void TSingleLinkedList::Remove(const T& aData) { - TNode* prev = head; - TNode* current = head->GetNext(); - - while (current != nullptr) { - if (current->GetData() == aData) { - // Match found, remove the node - InternalRemoveNode(prev, current); - return; // Only remove the first occurrence - } - } - prev = current; - current = current->GetNext(); -} - -// Reverse: Reverses the list using the classic iterative algorithm for singly-linked lists. -template -void TSingleLinkedList::Reverse() { - if (size <= 1) { - return; // Nothing to reverse - } - - // The original first node will become the new tail - tail = head->GetNext(); - - TNode* prevNode = nullptr; - TNode* currentNode = head->GetNext(); - TNode* nextNode = nullptr; - - while (currentNode != nullptr) { - nextNode = currentNode->GetNext(); // Store next node - currentNode->SetNext(prevNode); // Reverse the current node's pointer - prevNode = currentNode; // Move pointers one position ahead - currentNode = nextNode; - } - - // After the loop, prevNode is the new first node - head->SetNext(prevNode); -} - -// Contains: Checks if the list contains the given value, -// this is diffrent from Search as it only checks for existence -// This using search with a nullptr as the check function -template -bool TSingleLinkedList::Contains(const T& aData) const { - return Search(aData, nullptr) != nullptr; -} - -// Search: Finds a value using an optional custom comparison function -template -T TSingleLinkedList::Search(const T& aData, FCheckNode aCheckNode) const { - TNode* current = head->GetNext(); - while (current != nullptr) { - // Use the provided check function or default to direct comparison - if (aCheckNode != nullptr) { - if (aCheckNode(current->GetData(), aData)) { - return current->GetData(); - } - } - else { - if (current->GetData() == aData) { - return current->GetData(); - } - } - current = current->GetNext(); - } - return nullptr; // Not found -} - -// ForEach: Applies a function to each node in the list -template -void TSingleLinkedList::ForEach(FVisitNode aVisitNode) const { - if (aVisitNode == nullptr) { - return; - } - TNode* current = head->GetNext(); - int index = 0; - while (current != nullptr) { - aVisitNode(current->GetData(), index); - current = current->GetNext(); - index++; - } -} - -// GetSize: Returns the current number of elements in the list -template -int TSingleLinkedList::GetSize() const { - return size; -} - -// IsEmpty: Checks if the list has any elements -template -bool TSingleLinkedList::IsEmpty() const { - return size == 0; -} - -// RemoveAll: Removes all occurrences of a given value from the list. -template -void TSingleLinkedList::RemoveAll(const T& aData) { - TNode* prev = this->head; - TNode* current = this->head->GetNext(); - - while (current != nullptr) { - if (current->GetData() == aData) { - // Match found, remove the node - TNode* nodeToDelete = current; - current = current->GetNext(); // Advance current before deletion - InternalRemoveNode(prev, nodeToDelete); - // prev remains the same, as we just removed current - } - else { - // No match, advance both pointers - prev = current; - current = current->GetNext(); - } - } -} - -// Clone: Creates a deep copy of the list. -template -TSingleLinkedList TSingleLinkedList::Clone() const { - // Create a new list with the same ownership policy. - TSingleLinkedList newList(this->isDataOwner); - - TNode* current = this->head->GetNext(); - while (current != nullptr) { - T dataToCopy = current->GetData(); - - // This is the core of the deep copy logic. - if (this->isDataOwner && std::is_pointer::value && dataToCopy != nullptr) { - // If the list owns its pointer data, we must create a NEW object. - // This assumes the underlying type has a copy constructor. - // `std::remove_pointer_t` gets the type T points to (e.g., TSong from TSong*). - newList.Append(new std::remove_pointer_t(*dataToCopy)); - } - else { - // For value types (int, double) or non-owned pointers, just copy the value. - newList.Append(dataToCopy); - } - current = current->GetNext(); - } - return newList; -} - -// ReverseSublist: Reverses a portion of the list between two indices (inclusive). -template -void TSingleLinkedList::ReverseSublist(int aStart, int aEnd) { - // Validate indices - if (aStart < 0 || aEnd >= this->size || aStart >= aEnd) return; - - - // --- 1. Traverse to the nodes that define the sublist boundaries --- - // Use the helper to find the node *before* the sublist starts - TNode* startNodePrev = (aStart == 0) ? this->head : this->GetNodeAtIndex(aStart - 1); // Node before the start of the sublist - TNode* sublistHead = startNodePrev->GetNext(); // First node of the sublist - - // --- 2. Perform standard reversal on the sublist part only --- - TNode* prevNode = nullptr; - TNode* currentNode = sublistHead; - TNode* nextNode = nullptr; - for (int i = 0; i <= (aEnd - aStart); ++i) { - nextNode = currentNode->GetNext(); - currentNode->SetNext(prevNode); - prevNode = currentNode; - currentNode = nextNode; - } - - // --- 3. Stitch the reversed sublist back into the main list --- - // 'prevNode' is now the new head of the reversed sublist. - // 'sublistHead' is now the tail of the reversed sublist. - startNodePrev->SetNext(prevNode); - sublistHead->SetNext(currentNode); - - // Update the main tail pointer if the reversal included the original tail. - if (aEnd == this->size - 1) { - this->tail = sublistHead; - } -} - -// GetMiddle: Finds the middle node of the list using the fast/slow pointer algorithm. -template -TNode* TSingleLinkedList::GetMiddle() const { - if (this->IsEmpty()) { - return nullptr; - } - - TNode* slow = this->head->GetNext(); - TNode* fast = this->head->GetNext(); - - // The loop condition ensures 'fast' and 'fast->GetNext()' are valid. - // When 'fast' reaches the end, 'slow' will be at the midpoint. - while (fast != nullptr && fast->GetNext() != nullptr) { - slow = slow->GetNext(); - fast = fast->GetNext()->GetNext(); - } - - return slow; -} - -template -void TSingleLinkedList::ResetList() { - // Clear the list to an empty state - this->head->SetNext(nullptr); - this->tail = this->head; - this->size = 0; -} - -template -void TSingleLinkedList::Merge(TSingleLinkedList& aOtherList) { - // If the other list is empty, there's nothing to do. - if (aOtherList.IsEmpty()) { - return; - } - - // If this list is empty, take ownership of the other list's nodes. - if (this->IsEmpty()) { - this->head->SetNext(aOtherList.head->GetNext()); - this->tail = aOtherList.tail; - this->size = aOtherList.size; - - // Clear the other list - aOtherList.head->SetNext(nullptr); - aOtherList.tail = aOtherList.head; - aOtherList.size = 0; - return; - } - - // Pointers to the current nodes in each list - TNode* p1 = this->head->GetNext(); - TNode* p2 = aOtherList.head->GetNext(); - - // Use the dummy head of `this` list to start building the merged result. - TNode* tail = this->head; - - // --- Main Loop: Traverse both lists and pick the smaller node --- - while (p1 != nullptr && p2 != nullptr) { - if (p1->GetData() <= p2->GetData()) { - tail->SetNext(p1); - p1 = p1->GetNext(); - } - else { - tail->SetNext(p2); - p2 = p2->GetNext(); - } - tail = tail->GetNext(); - } - - // --- Append the Remainder --- - tail->SetNext(p1 != nullptr ? p1 : p2); - - // --- Update the Tail Pointer --- - while (tail->GetNext() != nullptr) { - tail = tail->GetNext(); - } - this->tail = tail; - - // --- Update Size --- - this->size += aOtherList.size; - - // --- Clear the Other List --- - aOtherList.ResetList(); -} - -// --- End of TSingleLinkedList class --- - -#endif // !TSINGLELINKEDLIST_HPP \ No newline at end of file diff --git a/Exam/IKT203Exam/LibExample/list.hpp b/Exam/IKT203Exam/LibExample/list.hpp deleted file mode 100644 index ef61d9b..0000000 --- a/Exam/IKT203Exam/LibExample/list.hpp +++ /dev/null @@ -1,309 +0,0 @@ -#pragma once -#include // For std::runtime_error -#include // For std::to_string - -// Linked List using TNode class with constructor and destructor -template -class TNode { -private: - T data; // Data of type T (e.g., TSong*) - TNode* next; // Pointer to the next node - TNode* prev; // Pointer to the previous node -public: - // Constructor - - TNode(T aData); - - // Destructor - ~TNode(); - - // Getters - T GetData() const { return data; } - TNode* GetNext() const { return next; } - TNode* GetPrev() const { return prev; } - - // Setters - void SetNext(TNode* aNextNode) { next = aNextNode; } - void SetPrev(TNode* aPrevNode) { prev = aPrevNode; } -}; - -// --- Method Implementations --- -// Constructor: Initializes the node with data from the factory function -template -TNode::TNode(T aData) : data(aData), next(nullptr), prev(nullptr) {} - -// Destructor: Deletes the data pointer -template -TNode::~TNode() { - //Do not delete data, data may exist outside the list - data = nullptr; // Set data to nullptr to avoid dangling pointer - next = nullptr; // Set next to nullptr to avoid dangling pointer - prev = nullptr; // Set prev to nullptr to avoid dangling pointer -} - -// --- End of TNode class --- - -// Type defined function for data factory -template -using FDataFactory = T(*)(TArgs); - -// Type defined functions for TLinkedList -template -using FCheckNode = bool(*)(const T, const T); - -template -using FVisitNode = void(*)(const T, int); - -// Linked List TLinkedList using TNode and dummy node -template -class TLinkedList { -private: - TNode* head; // Pointer to the dummy head node - TNode* tail; // Pointer to the tail node - int size; // Current size of the list - bool isDataOwner; // Indicates if the list owns the data and should delete it - - void InternAppend(T); - void InternPrepend(T); - -public: - // Constructor - TLinkedList(bool); - // Destructor - ~TLinkedList(); - - // Core Linked List Operations - template - T Append(FDataFactory, TArgs); - void Append(T); - - template - T Prepend(FDataFactory, TArgs); - void Prepend(T aValue); - - T GetAtIndex(int aIndex); - void Remove(const T aValue); - - // Finding and Checking Operations - bool Contains(const T aValue) const; - T Search(const T aValue, FCheckNode checkNode = nullptr) const; - - // Loop Operations - void ForEach(FVisitNode aVisitNode) const; - - // Helper Functions - int GetSize() const; - bool IsEmpty() const; - void Reverse(); -}; - -// --- Method Implementations --- -// Constructor: Initializes the dummy head node and tail -template -TLinkedList::TLinkedList(bool aIsDataOwner) : size(0) { - isDataOwner = aIsDataOwner; - head = new TNode(nullptr); // Create a dummy head node - tail = head; // Initially, tail is the same as head -} - -// Destructor: Deletes all nodes in the list -template -TLinkedList::~TLinkedList() { - TNode* current = head; - while (current != nullptr) { - TNode* nextNode = current->GetNext(); - if (isDataOwner && current->GetData() != nullptr) { - delete current->GetData(); // Delete the data if the list owns it - } - delete current; // Free the current node - current = nextNode; // Move to the next node - } -} - -template -void TLinkedList::InternAppend(T aData) { - TNode* newNode = new TNode(aData); - newNode->SetPrev(tail); // Set the prev pointer of the new node - tail->SetNext(newNode); // Update the next pointer of the current tail - tail = newNode; // Update the tail to the new node - size++; -} - -template -void TLinkedList::InternPrepend(T aData) { - TNode* newNode = new TNode(aData); - newNode->SetNext(head->GetNext()); - if (head->GetNext() != nullptr) { - head->GetNext()->SetPrev(newNode); // Update the prev pointer of the first node - } - head->SetNext(newNode); - newNode->SetPrev(head); // Set the prev pointer of the new node - if (tail == head) { - tail = newNode; - } - size++; -} - - -// Append(): Adds a new node with the given factory and returns the new node's data -template -template -T TLinkedList::Append(FDataFactory aDataFactory, TArgs aArgs) { - if(aDataFactory == nullptr) { - return nullptr; // Return nullptr if no factory is provided - } - T newData = aDataFactory(aArgs); - InternAppend(newData); - return newData; -} - -template -void TLinkedList::Append(T aValue) { - InternAppend(aValue); -} - -// Prepend(): Adds a new node with the given factory to the beginning of the list -template -template -T TLinkedList::Prepend(FDataFactory aDataFactory, TArgs aArgs) { - if (aDataFactory == nullptr) { - return nullptr; // Return nullptr if no factory is provided - } - T newData = aDataFactory(aArgs); - InternPrepend(newData); - return newData; -} - -template -void TLinkedList::Prepend(T aValue) { - InternPrepend(aValue); -} - -// GetAtIndex(): Returns the value at the specified index -template -T TLinkedList::GetAtIndex(int aIndex) { - if (aIndex < 0 || aIndex >= size) { - return nullptr; // Return nullptr if index is out of bounds - } - TNode* current; - if (aIndex < size / 2) { - current = head->GetNext(); - for (int i = 0; i < aIndex; i++) { - current = current->GetNext(); - } - } - else { - current = tail; - for (int i = size - 1; i > aIndex; i--) { - current = current->GetPrev(); - } - } - return current->GetData(); // Return the data directly -} - -// Remove(): Removes the first node with the given value -template -void TLinkedList::Remove(const T aValue) { - TNode* current = head->GetNext(); - while (current != nullptr) { - if (current->GetData() == aValue) { - TNode* nodeToDelete = current; - if (current->GetPrev() != nullptr) { - current->GetPrev()->SetNext(current->GetNext()); - } - if (current->GetNext() != nullptr) { - current->GetNext()->SetPrev(current->GetPrev()); - } - if (nodeToDelete == tail) { - tail = current->GetPrev(); - } - - if (isDataOwner && nodeToDelete->GetData() != nullptr) { - delete nodeToDelete->GetData(); // Delete the data if the list owns it - } - delete nodeToDelete; - size--; - return; - } - current = current->GetNext(); - } -} - -// Contains(): Checks if the list contains the given value -template -bool TLinkedList::Contains(const T aValue) const { - TNode* current = head->GetNext(); - while (current != nullptr) { - if (current->GetData() == aValue) { - return true; - } - current = current->GetNext(); - } - return false; -} - -// Search(): Searches for a node with the given value using an optional check function -template -T TLinkedList::Search(const T aValue, FCheckNode checkNode) const { - TNode* current = head->GetNext(); - while (current != nullptr) { - if (checkNode == nullptr) { - if (current->GetData() == aValue) { - return current->GetData(); - } - } else { - if (checkNode(current->GetData(), aValue)) { - return current->GetData(); - } - } - current = current->GetNext(); - } - return nullptr; -} - -// ForEach(): Applies a function to each node in the list -template -void TLinkedList::ForEach(FVisitNode aVisitNode) const { - if (aVisitNode == nullptr) { - return; // Return if no visit function is provided - } - TNode* current = head->GetNext(); - int index = 0; - while (current != nullptr) { - aVisitNode(static_cast(current->GetData()), index); // Cast to const T - current = current->GetNext(); - index++; - } -} - -// Reverse(): Reverses the order of the nodes in the list -template -void TLinkedList::Reverse() { - TNode* current = head->GetNext(); - TNode* temp = nullptr; // Temporary pointer for swapping - - // Handle an empty or single-node list - if (current == nullptr || current->GetNext() == nullptr) { - return; - } - - // Iterate and swap next and prev pointers - while (current != nullptr) { - temp = current->GetPrev(); // Store prev pointer - current->SetPrev(current->GetNext()); // Set prev to next - current->SetNext(temp); // Set next to temp (which holds original prev) - current = current->GetPrev(); // Move to the original next node - } - - // Update head and tail - TNode* newHeadNext = tail; // The original tail becomes the new head->next - tail = head->GetNext(); // The original first node is now the tail - tail->SetNext(nullptr); // Ensure the new tail has no next pointer - head->SetNext(newHeadNext); // Set the head's next to the new first node -} - -template -int TLinkedList::GetSize() const { - return size; -} -// --- End of TLinkedList class --- \ No newline at end of file diff --git a/Exam/IKT203Exam/LibExample/queue.hpp b/Exam/IKT203Exam/LibExample/queue.hpp deleted file mode 100644 index 16b76fa..0000000 --- a/Exam/IKT203Exam/LibExample/queue.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once -#include // For std::runtime_error - -template -class TQueue { - private: - T data[MAX_SIZE]; // A static array of T with MAX_SIZE elements - int frontIndex; // The index of the front element - int rearIndex; // The index of the rear element - int count; // Current number of elements in the queue - public: - // Constructor - TQueue(); - // No destructor is needed since we aren't using 'new' - // --- Core Queue Operations --- - void Enqueue(const T& aElement); - T Dequeue(); - T GetFront() const; - // --- Helper Functions --- - int size() const; - bool IsEmpty() const; - bool IsFull() const; -}; -// --- Method Implementations --- -// Constructor: Initializes the front and rear indices -template -TQueue::TQueue() : frontIndex(0), rearIndex(-1), count(0) { - // No memory allocation is needed -} -// enqueue(): Adds an element to the rear of the queue -template -void TQueue::Enqueue(const T& aElement) { - if (IsFull()) { - throw std::runtime_error("Queue overflow: cannot enqueue to a full queue."); - } - rearIndex = (rearIndex + 1) % MAX_SIZE; // Circular increment - data[rearIndex] = aElement; - count++; -} -// dequeue(): Removes and returns the front element -template -T TQueue::Dequeue() { - if (IsEmpty()) { - throw std::runtime_error("Queue underflow: cannot dequeue from an empty queue."); - } - T frontElement = data[frontIndex]; - frontIndex = (frontIndex + 1) % MAX_SIZE; // Circular increment - count--; - return frontElement; -} -// getFront(): Returns the front element without removing it -template -T TQueue::GetFront() const { - if (IsEmpty()) { - throw std::runtime_error("Queue is empty: cannot get front."); - } - return data[frontIndex]; -} -// size(): Returns the current number of elements -template -int TQueue::size() const { - return count; -} -// isEmpty(): Checks if the queue is empty -template -bool TQueue::IsEmpty() const { - return count == 0; -} -// isFull(): Checks if the queue is full -template -bool TQueue::IsFull() const { - return count == MAX_SIZE; -} \ No newline at end of file diff --git a/Exam/IKT203Exam/LibExample/stack.hpp b/Exam/IKT203Exam/LibExample/stack.hpp deleted file mode 100644 index d88f08d..0000000 --- a/Exam/IKT203Exam/LibExample/stack.hpp +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once -#include // For std::runtime_error - -// The template now takes a type 'T' and an integer 'MAX_SIZE' -template -class TStack { -private: - T data[MAX_SIZE]; // A static array of T with MAX_SIZE elements - int topIndex; // The index of the top element (-1 if empty) - -public: - // Constructor - TStack(); - - // No destructor is needed since we aren't using 'new' - - // --- Core Stack Operations --- - void Push(const T& aElement); - T Pop(); - T Peek() const; - - // --- Helper Functions --- - int GetSize() const; - bool IsEmpty() const; - bool IsFull() const; -}; - -// --- Method Implementations --- - -// Constructor: Just initializes the top index -template -TStack::TStack() : topIndex(-1) { - // No memory allocation is needed -} - -// push(): Adds an element to the top -template -void TStack::Push(const T& aElement) { - if (IsFull()) { - throw std::runtime_error("Stack overflow: cannot push to a full stack."); - } - data[++topIndex] = aElement; -} - -// pop(): Removes and returns the top element -template -T TStack::Pop() { - if (IsEmpty()) { - throw std::runtime_error("Stack underflow: cannot pop from an empty stack."); - } - return data[topIndex--]; -} - -// peek(): Returns the top element without removing it -template -T TStack::Peek() const { - if (IsEmpty()) { - throw std::runtime_error("Stack is empty: cannot peek."); - } - return data[topIndex]; -} - -// size(): Returns the current number of elements -template -int TStack::GetSize() const { - return topIndex + 1; -} - -// isEmpty(): Checks if the stack is empty -template -bool TStack::IsEmpty() const { - return topIndex == -1; -} - -// isFull(): Checks if the stack is full -template -bool TStack::IsFull() const { - return topIndex == MAX_SIZE - 1; -} \ No newline at end of file diff --git a/Exam/IKT203Exam/Portfolio/Assignment-03/option1.cpp b/Exam/IKT203Exam/Portfolio/Assignment-03/option1.cpp index c3ad44d..ee045a1 100644 --- a/Exam/IKT203Exam/Portfolio/Assignment-03/option1.cpp +++ b/Exam/IKT203Exam/Portfolio/Assignment-03/option1.cpp @@ -1,6 +1,8 @@ #include "option1.h" #include +#include "SharedLib.h" + // Entry point for Category 3, Option 1. // Demonstrates: // 1) Building a BST of 200 employees from DATA/random_names.txt diff --git a/Exam/IKT203Exam/deploy.ps1 b/Exam/IKT203Exam/deploy.ps1 deleted file mode 100644 index f7bc35f..0000000 --- a/Exam/IKT203Exam/deploy.ps1 +++ /dev/null @@ -1,58 +0,0 @@ -# This block defines the parameters the script can accept from the command line. -param ( - # The full path to the build directory where the .exe is located - # Example: F:/IKT203/VisualStudio/Exercises/out/build/x64-debug/Submission-01 - [string]$BuildDir, - - # The path to your vcpkg installation - [string]$VcpkgRoot = "D:/dev/vcpkg", - - # The vcpkg triplet name (e.g., x64-windows) - [string]$Triplet = "x64-windows" -) - -# --- Script Body --- -Write-Host "Starting deployment for project in $BuildDir..." -ForegroundColor Green - -# Define the source paths using the parameters. -# Path to the main Qt DLLs (e.g., .../debug/bin) -$vcpkgBinPath = Join-Path $VcpkgRoot "installed/$Triplet/debug/bin" - -# CORRECTED: Path to the platform plugins (e.g., .../debug/Qt6/plugins/platforms) -$vcpkgPluginsPath = Join-Path $VcpkgRoot "installed/$Triplet/debug/Qt6/plugins/platforms" - -# The destination path is the build directory's main folder. -$destinationPath = $BuildDir - -# Check if the destination directory exists. -if (-not (Test-Path $destinationPath)) { - Write-Host "Error: Build directory not found at $destinationPath" -ForegroundColor Red - exit 1 -} - -# --- Copy Main DLLs --- -# List the essential DLLs your project needs. -$qtDlls = @( - "Qt6Cored.dll", - "Qt6Guid.dll", - "Qt6Widgetsd.dll" -) - -Write-Host "Copying main Qt DLLs to $destinationPath" -foreach ($dll in $qtDlls) { - $sourceDll = Join-Path $vcpkgBinPath $dll - Copy-Item -Path $sourceDll -Destination $destinationPath -Force -} - -# --- Copy Platform Plugin --- -# Create the "platforms" subdirectory if it doesn't exist. -$pluginDestPath = Join-Path $destinationPath "platforms" -if (-not (Test-Path $pluginDestPath)) { - New-Item -ItemType Directory -Path $pluginDestPath -} - -Write-Host "Copying platform plugin to $pluginDestPath" -$sourcePlugin = Join-Path $vcpkgPluginsPath "qwindowsd.dll" -Copy-Item -Path $sourcePlugin -Destination $pluginDestPath -Force - -Write-Host "Deployment complete!" -ForegroundColor Green diff --git a/TheAlgorithmicOrganizer/.idea/.gitignore b/TheAlgorithmicOrganizer/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/TheAlgorithmicOrganizer/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/TheAlgorithmicOrganizer/.idea/TheAlgoeithmicOrganizer.iml b/TheAlgorithmicOrganizer/.idea/TheAlgoeithmicOrganizer.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/TheAlgorithmicOrganizer/.idea/TheAlgoeithmicOrganizer.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/TheAlgorithmicOrganizer/.idea/editor.xml b/TheAlgorithmicOrganizer/.idea/editor.xml new file mode 100644 index 0000000..9cf688e --- /dev/null +++ b/TheAlgorithmicOrganizer/.idea/editor.xml @@ -0,0 +1,343 @@ + + + + + \ No newline at end of file diff --git a/TheAlgorithmicOrganizer/.idea/material_theme_project_new.xml b/TheAlgorithmicOrganizer/.idea/material_theme_project_new.xml new file mode 100644 index 0000000..554b701 --- /dev/null +++ b/TheAlgorithmicOrganizer/.idea/material_theme_project_new.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/TheAlgorithmicOrganizer/.idea/misc.xml b/TheAlgorithmicOrganizer/.idea/misc.xml new file mode 100644 index 0000000..0b76fe5 --- /dev/null +++ b/TheAlgorithmicOrganizer/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/TheAlgorithmicOrganizer/.idea/modules.xml b/TheAlgorithmicOrganizer/.idea/modules.xml new file mode 100644 index 0000000..910b840 --- /dev/null +++ b/TheAlgorithmicOrganizer/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/TheAlgorithmicOrganizer/.idea/vcs.xml b/TheAlgorithmicOrganizer/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/TheAlgorithmicOrganizer/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file