Compare commits

...

11 Commits

Author SHA1 Message Date
Christopher Sanden
f0a4fa60b8 merging exam branch 2025-11-21 12:52:41 +01:00
Christopher Sanden
6e9e3ecd4d Pushing work to remote 2025-11-21 12:51:05 +01:00
Christopher Sanden
a014e4ca73 Cleaning up and adding comments 2025-11-20 15:24:00 +01:00
Christopher Sanden
e77d7ff21e Cleaning up and adding comments 2025-11-18 13:23:54 +01:00
Christopher Sanden
d1fa8eda6b finished 2025-11-17 17:34:30 +01:00
Christopher Sanden
1e00ba3521 finished 2025-11-17 17:02:46 +01:00
Christopher Sanden
b8aa672431 Not finished, but no more time for improvements 2025-11-14 12:13:21 +01:00
Christopher Sanden
58772c0488 Adding final assignment updates 2025-11-13 15:15:01 +01:00
Christopher Sanden
ae8a53e16b Added final assignment 2025-11-13 12:44:46 +01:00
Christopher Sanden
730987913e part 3 complete 2025-11-08 14:51:28 +01:00
Christopher Sanden
4c6e3d0905 Adding 4th assignment - Simple Search 2025-11-01 17:29:11 +01:00
69 changed files with 13527 additions and 2085 deletions

View File

@@ -21,8 +21,6 @@ endif()
# The order matters here: we add LibExample first so that its library is # The order matters here: we add LibExample first so that its library is
# defined before the executables that need to link to it. # defined before the executables that need to link to it.
add_subdirectory(LibExample)
add_subdirectory(Submissions)
add_subdirectory(Portfolio) add_subdirectory(Portfolio)
# --- End of File --- # --- End of File ---

View File

@@ -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.

View File

@@ -1,454 +0,0 @@
// Implantation of the Circular Doubly Linked List
#ifndef TCIRCULARDOUBLYLINKEDLISTTEMPLATE_HPP
#define TCIRCULARDOUBLYLINKEDLISTTEMPLATE_HPP
#pragma once
#include "TDoublyLinkedListTemplate.hpp"
template <typename T>
class TCircularDoublyLinkedList : public TDoublyLinkedList<T> {
private:
// Helper to remove a node, updating both next and prev pointers
void InternalRemoveNode(TNode<T>* aNodeToDelete);
protected:
// --- New Member Variable ---
TNode<T>* cursor; // Points to the "current" node in the list.
public:
using TSingleLinkedList<T>::Append;
using TSingleLinkedList<T>::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<T>& otherList) override;
// For avoiding infinite loops
bool Contains(const T&) const override;
T Search(const T&, FCheckNode<T>) const override;
void ForEach(FVisitNode<T>) const override;
TNode<T>* GetMiddle() const override;
};
// Constructor: Establishes the initial circular link where the head points to itself.
template <typename T>
TCircularDoublyLinkedList<T>::TCircularDoublyLinkedList(bool aIsDataOwner)
: TDoublyLinkedList<T>(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 <typename T>
TCircularDoublyLinkedList<T>::~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 <typename T>
void TCircularDoublyLinkedList<T>::ResetCursor() {
if (this->IsEmpty()) {
this->cursor = this->head;
}
else {
this->cursor = this->head->GetNext();
}
}
// Returns the data at the cursor's current position.
template <typename T>
T TCircularDoublyLinkedList<T>::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 <typename T>
void TCircularDoublyLinkedList<T>::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 <typename T>
void TCircularDoublyLinkedList<T>::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 <typename T>
int TCircularDoublyLinkedList<T>::GetCursorIndex() const {
if (this->IsEmpty() || this->cursor == this->head) {
return -1;
}
int index = 0;
TNode<T>* 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 <typename T>
void TCircularDoublyLinkedList<T>::Append(const T& aData) {
// 1. Let the base class do ALL the standard work.
TDoublyLinkedList<T>::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 <typename T>
void TCircularDoublyLinkedList<T>::Prepend(const T& aData) {
TDoublyLinkedList<T>::Prepend(aData);
// No need to adjust circular links, as TDoublyLinkedList::Prepend already does it.
}
template <typename T>
void TCircularDoublyLinkedList<T>::InternalRemoveNode(TNode<T>* 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<T>* prevNode = aNodeToDelete->GetPrev();
TNode<T>* 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 <typename T>
void TCircularDoublyLinkedList<T>::Remove(const T& aData) {
if (this->IsEmpty()) return;
// Start searching from the first actual node
TNode<T>* current = this->head->GetNext();
// Traverse the entire circle once
for (int i = 0; i < this->size; ++i) {
if (current->GetData() == aData) {
TNode<T>* prevNode = current->GetPrev();
TNode<T>* 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 <typename T>
T TCircularDoublyLinkedList<T>::RemoveLast() {
if (this->IsEmpty()) {
return nullptr;
}
TNode<T>* nodeToRemove = this->tail;
T dataToReturn = nodeToRemove->GetData();
TNode<T>* 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 <typename T>
void TCircularDoublyLinkedList<T>::RemoveAll(const T& aData) {
if (this->IsEmpty()) return;
TNode<T>* current = this->head->GetNext();
int initialSize = this->size; // Loop based on the original size
for (int i = 0; i < initialSize; ++i) {
TNode<T>* nextNode = current->GetNext(); // Get next node before potential deletion
if (current->GetData() == aData) {
TNode<T>* 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 <typename T>
void TCircularDoublyLinkedList<T>::Reverse() {
if (this->size <= 1) return; // Nothing to reverse
// 1. Keep track of original head and tail nodes.
TNode<T>* newFirstNode = this->tail;
// 2. Iterate through all nodes, swapping next and prev pointers.
TNode<T>* 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 <typename T>
void TCircularDoublyLinkedList<T>::ReverseSublist(int start, int end) {
if (start < 0 || end >= this->size || start >= end) {
return;
}
// --- 1. Find boundary nodes ---
TNode<T>* startNode = this->head->GetNext();
for (int i = 0; i < start; ++i) {
startNode = startNode->GetNext();
}
TNode<T>* endNode = startNode;
for (int i = start; i < end; ++i) {
endNode = endNode->GetNext();
}
TNode<T>* startPrev = startNode->GetPrev();
TNode<T>* endNext = endNode->GetNext();
// --- 2. Reverse pointers for all nodes within the sublist ---
TNode<T>* current = startNode;
for (int i = 0; i <= (end - start); ++i) {
TNode<T>* 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 <typename T>
void TCircularDoublyLinkedList<T>::Merge(TSingleLinkedList<T>& otherList) {
// We can call the parent implementation to do the heavy lifting of merging.
TDoublyLinkedList<T>::Merge(otherList);
// The parent merge results in a null-terminated list. We just need to fix the ends.
if (!this->IsEmpty()) {
TNode<T>* 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 <typename T>
void TCircularDoublyLinkedList<T>::ForEach(FVisitNode<T> aVisitNode) const {
if (aVisitNode == nullptr || this->IsEmpty()) {
return;
}
TNode<T>* 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 <typename T>
bool TCircularDoublyLinkedList<T>::Contains(const T& aData) const {
if (this->IsEmpty()) {
return false;
}
TNode<T>* 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 <typename T>
T TCircularDoublyLinkedList<T>::Search(const T& aData, FCheckNode<T> aCheckNode) const {
if (this->IsEmpty()) {
return nullptr;
}
TNode<T>* 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 <typename T>
TNode<T>* TCircularDoublyLinkedList<T>::GetMiddle() const {
if (this->IsEmpty()) return nullptr;
// The safest way for a list where we know the size.
int middleIndex = this->size / 2;
TNode<T>* current = this->head->GetNext();
for (int i = 0; i < middleIndex; ++i) {
current = current->GetNext();
}
return current;
}
#endif // TCIRCULARDOUBLYLINKEDLISTTEMPLATE_HPP

View File

@@ -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 <typename T>
class TDoublyLinkedList : public TSingleLinkedList<T> {
private:
// Internal helper to remove a node, updating both next and prev pointers
void InternalRemoveNode(TNode<T>* aNodeToDelete);
public:
using TSingleLinkedList<T>::Append;
using TSingleLinkedList<T>::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<T>&) 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>*, T&);
void ForEachReverse(FVisitNode<T>) const;
};
template<typename T>
inline void TDoublyLinkedList<T>::InternalRemoveNode(TNode<T>* aNodeToDelete)
{
if (aNodeToDelete == nullptr || aNodeToDelete == this->head) return;
TNode<T>* prevNode = aNodeToDelete->GetPrev();
TNode<T>* 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 <typename T>
TDoublyLinkedList<T>::TDoublyLinkedList(bool aIsDataOwner)
: TSingleLinkedList<T>(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 <typename T>
TDoublyLinkedList<T>::~TDoublyLinkedList() {} // No additional cleanup needed, the base class handles it.
// Append: Overridden to correctly set the 'prev' pointer on the new node.
template <typename T>
void TDoublyLinkedList<T>::Append(const T& aData) {
TNode<T>* oldTail = this->tail;
TNode<T>* 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 <typename T>
void TDoublyLinkedList<T>::Prepend(const T& aData) {
TNode<T>* 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 <typename T>
T TDoublyLinkedList<T>::GetAtIndex(int aIndex) {
if (aIndex < 0 || aIndex >= this->size) {
return nullptr; // Index out of bounds
}
TNode<T>* 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 <typename T>
void TDoublyLinkedList<T>::Remove(const T& aData) {
TNode<T>* current = this->head->GetNext();
while (current != nullptr) {
if (current->GetData() == aData) {
TNode<T>* 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 <typename T>
void TDoublyLinkedList<T>::Reverse() {
if (this->size <= 1) return;
// 1. Keep track of original head and tail nodes.
TNode<T>* originalHeadNode = this->head->GetNext();
TNode<T>* originalTailNode = this->tail;
// 2. Swap prev/next for every node.
TNode<T>* 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 <typename T>
T TDoublyLinkedList<T>::RemoveLast() {
if (this->IsEmpty()) {
return nullptr;
}
TNode<T>* 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 <typename T>
void TDoublyLinkedList<T>::InsertBefore(TNode<T>* 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<T>* newNode = new TNode<T>(aData);
TNode<T>* 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 <typename T>
void TDoublyLinkedList<T>::ForEachReverse(FVisitNode<T> aVisitNode) const {
if (aVisitNode == nullptr) {
return;
}
TNode<T>* current = this->tail;
int index = this->size - 1;
while (current != this->head) {
aVisitNode(current->GetData(), index);
current = current->GetPrev();
index--;
}
}
template <typename T>
void TDoublyLinkedList<T>::Merge(TSingleLinkedList<T>& otherList) {
if (otherList.IsEmpty()) {
return;
}
int otherSize = otherList.GetSize();
// Call the now-public StealNodes to legally take ownership of the nodes.
TNode<T>* 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<T>* newTail = this->head;
while (newTail->GetNext() != nullptr) {
newTail = newTail->GetNext();
}
this->tail = newTail;
return;
}
TNode<T>* p1 = this->head->GetNext();
TNode<T>* 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<T>* 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 <typename T>
void TDoublyLinkedList<T>::RemoveAll(const T& aValue) {
TNode<T>* current = this->head->GetNext();
while (current != nullptr) {
if (current->GetData() == aValue) {
TNode<T>* 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 <typename T>
void TDoublyLinkedList<T>::ReverseSublist(int start, int end) {
if (start < 0 || end >= this->size || start >= end) return;
// --- 1. Find boundary nodes ---
TNode<T>* startNode = this->head->GetNext();
TNode<T>* endNode = startNode;
for (int i = 0; i < start; ++i) {
startNode = startNode->GetNext();
}
for (int i = start; i < end; ++i) {
endNode = endNode->GetNext();
}
TNode<T>* startPrev = startNode->GetPrev();
TNode<T>* endNext = endNode->GetNext();
// --- 2. Reverse pointers for all nodes within the sublist ---
TNode<T>* current = startNode;
while (current != endNext) {
TNode<T>* 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

View File

@@ -1,529 +0,0 @@
#ifndef TSINGLELINKEDLIST_HPP
#define TSINGLELINKEDLIST_HPP
#pragma once
#include <type_traits> // Required for the Clone function, and prevent delete on non-pointer types
#include "TDoublyLinkedListTemplate.hpp"
#include "TCircularDoublyLinkedListTemplate.hpp"
template <typename T>
class TDoublyLinkedList; // Forward declaration for friendship
template <typename T>
class TCircularDoublyLinkedList; // Forward declaration for friendship
// Callback type definitions
template <typename T, typename TArgs>
using FDataFactory = T(*)(TArgs); // <-- ADD THIS LINE
template <typename T>
using FCheckNode = bool(*)(const T, const T);
template <typename T>
using FVisitNode = void(*)(const T, int);
template <typename T>
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<T>;
friend class TCircularDoublyLinkedList<T>;
};
// --- Method Implementations ---
// Constructor: Initializes the node with data from the factory function
template <typename T>
TNode<T>::TNode(const T& aData) : data(aData), next(nullptr), prev(nullptr) {}
// Destructor: Deletes the data pointer
template <typename T>
TNode<T>::~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 <typename T>
void TNode<T>::SwapNextPrev() {
TNode* temp = next;
next = prev;
prev = temp;
}
// --- End of TNode class ---
// Singly Linked List TSingleLinkedList using TNode<T> and dummy node
template <typename T>
class TSingleLinkedList {
private:
// Helper to reset the list to empty state
void ResetList();
protected:
TNode<T>* head; // Pointer to the dummy head node
TNode<T>* 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<T>* InternAppend(const T&);
TNode<T>* InternPrepend(const T&);
// Helper for RemoveAll to delete a node given its previous node
void InternalRemoveNode(TNode<T>*, TNode<T>*);
// Helper to get node at index (non-virtual, used internally)
TNode<T>* 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<T>* GetMiddle() const;
virtual void Merge(TSingleLinkedList<T>&);
// --- Traversal functions that MUST now be virtual ---
virtual bool Contains(const T&) const;
virtual T Search(const T&, FCheckNode<T> = nullptr) const;
virtual void ForEach(FVisitNode<T>) const;
// --- Non-Virtual Methods ---
template <typename TArgs>
T Append(FDataFactory<T, TArgs>, TArgs);
template <typename TArgs>
T Prepend(FDataFactory<T, TArgs>, TArgs);
int GetSize() const;
bool IsEmpty() const;
TSingleLinkedList<T> Clone() const;
TNode<T>* StealNodes();
};
// Constructor: Initializes the dummy head node and list state
template <typename T>
TSingleLinkedList<T>::TSingleLinkedList(bool aIsDataOwner)
: head(new TNode<T>(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<T>::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 <typename T>
TSingleLinkedList<T>::~TSingleLinkedList() {
TNode<T>* current = head;
while (current != nullptr) {
TNode<T>* 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 <typename T>
void TSingleLinkedList<T>::InternalRemoveNode(TNode<T>* aPrevNode, TNode<T>* 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 <typename T>
TNode<T>* TSingleLinkedList<T>::StealNodes() {
TNode<T>* 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 <typename T>
TNode<T>* TSingleLinkedList<T>::InternAppend(const T& aData) {
TNode<T>* newNode = new TNode<T>(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 <typename T>
void TSingleLinkedList<T>::Append(const T& aData) {
InternAppend(aData);
}
// InternPrepend: Handles the logic of adding a node to the beginning
template <typename T>
TNode<T>* TSingleLinkedList<T>::InternPrepend(const T& aData) {
TNode<T>* newNode = new TNode<T>(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 <typename T>
void TSingleLinkedList<T>::Prepend(const T& aData) {
InternPrepend(aData);
}
// Append(): Creates a new node with the given factory and returns the new node's data.
template <typename T>
template <typename TArgs>
T TSingleLinkedList<T>::Append(FDataFactory<T, TArgs> 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 <typename T>
template <typename TArgs>
T TSingleLinkedList<T>::Prepend(FDataFactory<T, TArgs> 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 <typename T>
TNode<T>* TSingleLinkedList<T>::GetNodeAtIndex(int aIndex) const {
TNode<T>* 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 <typename T>
T TSingleLinkedList<T>::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 <typename T>
void TSingleLinkedList<T>::Remove(const T& aData) {
TNode<T>* prev = head;
TNode<T>* 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 <typename T>
void TSingleLinkedList<T>::Reverse() {
if (size <= 1) {
return; // Nothing to reverse
}
// The original first node will become the new tail
tail = head->GetNext();
TNode<T>* prevNode = nullptr;
TNode<T>* currentNode = head->GetNext();
TNode<T>* 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 <typename T>
bool TSingleLinkedList<T>::Contains(const T& aData) const {
return Search(aData, nullptr) != nullptr;
}
// Search: Finds a value using an optional custom comparison function
template <typename T>
T TSingleLinkedList<T>::Search(const T& aData, FCheckNode<T> aCheckNode) const {
TNode<T>* 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 <typename T>
void TSingleLinkedList<T>::ForEach(FVisitNode<T> aVisitNode) const {
if (aVisitNode == nullptr) {
return;
}
TNode<T>* 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 <typename T>
int TSingleLinkedList<T>::GetSize() const {
return size;
}
// IsEmpty: Checks if the list has any elements
template <typename T>
bool TSingleLinkedList<T>::IsEmpty() const {
return size == 0;
}
// RemoveAll: Removes all occurrences of a given value from the list.
template <typename T>
void TSingleLinkedList<T>::RemoveAll(const T& aData) {
TNode<T>* prev = this->head;
TNode<T>* current = this->head->GetNext();
while (current != nullptr) {
if (current->GetData() == aData) {
// Match found, remove the node
TNode<T>* 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 <typename T>
TSingleLinkedList<T> TSingleLinkedList<T>::Clone() const {
// Create a new list with the same ownership policy.
TSingleLinkedList<T> newList(this->isDataOwner);
TNode<T>* 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<T>::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<T>` gets the type T points to (e.g., TSong from TSong*).
newList.Append(new std::remove_pointer_t<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 <typename T>
void TSingleLinkedList<T>::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<T>* startNodePrev = (aStart == 0) ? this->head : this->GetNodeAtIndex(aStart - 1); // Node before the start of the sublist
TNode<T>* sublistHead = startNodePrev->GetNext(); // First node of the sublist
// --- 2. Perform standard reversal on the sublist part only ---
TNode<T>* prevNode = nullptr;
TNode<T>* currentNode = sublistHead;
TNode<T>* 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 <typename T>
TNode<T>* TSingleLinkedList<T>::GetMiddle() const {
if (this->IsEmpty()) {
return nullptr;
}
TNode<T>* slow = this->head->GetNext();
TNode<T>* 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 <typename T>
void TSingleLinkedList<T>::ResetList() {
// Clear the list to an empty state
this->head->SetNext(nullptr);
this->tail = this->head;
this->size = 0;
}
template <typename T>
void TSingleLinkedList<T>::Merge(TSingleLinkedList<T>& 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<T>* p1 = this->head->GetNext();
TNode<T>* p2 = aOtherList.head->GetNext();
// Use the dummy head of `this` list to start building the merged result.
TNode<T>* 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

View File

@@ -1,309 +0,0 @@
#pragma once
#include <stdexcept> // For std::runtime_error
#include <string> // For std::to_string
// Linked List using TNode<T> class with constructor and destructor
template <typename T>
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 <typename T>
TNode<T>::TNode(T aData) : data(aData), next(nullptr), prev(nullptr) {}
// Destructor: Deletes the data pointer
template <typename T>
TNode<T>::~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 <typename T, typename TArgs>
using FDataFactory = T(*)(TArgs);
// Type defined functions for TLinkedList
template <typename T>
using FCheckNode = bool(*)(const T, const T);
template <typename T>
using FVisitNode = void(*)(const T, int);
// Linked List TLinkedList using TNode<T> and dummy node
template <typename T>
class TLinkedList {
private:
TNode<T>* head; // Pointer to the dummy head node
TNode<T>* 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 <typename TArgs>
T Append(FDataFactory<T, TArgs>, TArgs);
void Append(T);
template <typename TArgs>
T Prepend(FDataFactory<T, TArgs>, 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<T> checkNode = nullptr) const;
// Loop Operations
void ForEach(FVisitNode<T> aVisitNode) const;
// Helper Functions
int GetSize() const;
bool IsEmpty() const;
void Reverse();
};
// --- Method Implementations ---
// Constructor: Initializes the dummy head node and tail
template <typename T>
TLinkedList<T>::TLinkedList(bool aIsDataOwner) : size(0) {
isDataOwner = aIsDataOwner;
head = new TNode<T>(nullptr); // Create a dummy head node
tail = head; // Initially, tail is the same as head
}
// Destructor: Deletes all nodes in the list
template <typename T>
TLinkedList<T>::~TLinkedList() {
TNode<T>* current = head;
while (current != nullptr) {
TNode<T>* 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 <typename T>
void TLinkedList<T>::InternAppend(T aData) {
TNode<T>* newNode = new TNode<T>(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 <typename T>
void TLinkedList<T>::InternPrepend(T aData) {
TNode<T>* newNode = new TNode<T>(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 <typename T>
template <typename TArgs>
T TLinkedList<T>::Append(FDataFactory<T, TArgs> aDataFactory, TArgs aArgs) {
if(aDataFactory == nullptr) {
return nullptr; // Return nullptr if no factory is provided
}
T newData = aDataFactory(aArgs);
InternAppend(newData);
return newData;
}
template <typename T>
void TLinkedList<T>::Append(T aValue) {
InternAppend(aValue);
}
// Prepend(): Adds a new node with the given factory to the beginning of the list
template <typename T>
template <typename TArgs>
T TLinkedList<T>::Prepend(FDataFactory<T, TArgs> aDataFactory, TArgs aArgs) {
if (aDataFactory == nullptr) {
return nullptr; // Return nullptr if no factory is provided
}
T newData = aDataFactory(aArgs);
InternPrepend(newData);
return newData;
}
template <typename T>
void TLinkedList<T>::Prepend(T aValue) {
InternPrepend(aValue);
}
// GetAtIndex(): Returns the value at the specified index
template <typename T>
T TLinkedList<T>::GetAtIndex(int aIndex) {
if (aIndex < 0 || aIndex >= size) {
return nullptr; // Return nullptr if index is out of bounds
}
TNode<T>* 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 <typename T>
void TLinkedList<T>::Remove(const T aValue) {
TNode<T>* current = head->GetNext();
while (current != nullptr) {
if (current->GetData() == aValue) {
TNode<T>* 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 <typename T>
bool TLinkedList<T>::Contains(const T aValue) const {
TNode<T>* 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 <typename T>
T TLinkedList<T>::Search(const T aValue, FCheckNode<T> checkNode) const {
TNode<T>* 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 <typename T>
void TLinkedList<T>::ForEach(FVisitNode<T> aVisitNode) const {
if (aVisitNode == nullptr) {
return; // Return if no visit function is provided
}
TNode<T>* current = head->GetNext();
int index = 0;
while (current != nullptr) {
aVisitNode(static_cast<const T>(current->GetData()), index); // Cast to const T
current = current->GetNext();
index++;
}
}
// Reverse(): Reverses the order of the nodes in the list
template <typename T>
void TLinkedList<T>::Reverse() {
TNode<T>* current = head->GetNext();
TNode<T>* 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<T>* 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 <typename T>
int TLinkedList<T>::GetSize() const {
return size;
}
// --- End of TLinkedList class ---

View File

@@ -1,73 +0,0 @@
#pragma once
#include <stdexcept> // For std::runtime_error
template <typename T, int MAX_SIZE>
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 <typename T, int MAX_SIZE>
TQueue<T, MAX_SIZE>::TQueue() : frontIndex(0), rearIndex(-1), count(0) {
// No memory allocation is needed
}
// enqueue(): Adds an element to the rear of the queue
template <typename T, int MAX_SIZE>
void TQueue<T, MAX_SIZE>::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 <typename T, int MAX_SIZE>
T TQueue<T, MAX_SIZE>::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 <typename T, int MAX_SIZE>
T TQueue<T, MAX_SIZE>::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 <typename T, int MAX_SIZE>
int TQueue<T, MAX_SIZE>::size() const {
return count;
}
// isEmpty(): Checks if the queue is empty
template <typename T, int MAX_SIZE>
bool TQueue<T, MAX_SIZE>::IsEmpty() const {
return count == 0;
}
// isFull(): Checks if the queue is full
template <typename T, int MAX_SIZE>
bool TQueue<T, MAX_SIZE>::IsFull() const {
return count == MAX_SIZE;
}

View File

@@ -1,79 +0,0 @@
#pragma once
#include <stdexcept> // For std::runtime_error
// The template now takes a type 'T' and an integer 'MAX_SIZE'
template <typename T, int MAX_SIZE>
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 <typename T, int MAX_SIZE>
TStack<T, MAX_SIZE>::TStack() : topIndex(-1) {
// No memory allocation is needed
}
// push(): Adds an element to the top
template <typename T, int MAX_SIZE>
void TStack<T, MAX_SIZE>::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 <typename T, int MAX_SIZE>
T TStack<T, MAX_SIZE>::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 <typename T, int MAX_SIZE>
T TStack<T, MAX_SIZE>::Peek() const {
if (IsEmpty()) {
throw std::runtime_error("Stack is empty: cannot peek.");
}
return data[topIndex];
}
// size(): Returns the current number of elements
template <typename T, int MAX_SIZE>
int TStack<T, MAX_SIZE>::GetSize() const {
return topIndex + 1;
}
// isEmpty(): Checks if the stack is empty
template <typename T, int MAX_SIZE>
bool TStack<T, MAX_SIZE>::IsEmpty() const {
return topIndex == -1;
}
// isFull(): Checks if the stack is full
template <typename T, int MAX_SIZE>
bool TStack<T, MAX_SIZE>::IsFull() const {
return topIndex == MAX_SIZE - 1;
}

View File

@@ -1,5 +1,6 @@
// Option 1 (Standard): Console Text Editor. // Option 1 (Standard): Console Text Editor.
// // Implements the user-facing console loop for the text editor.
// Handles line editing, undo/redo logic, and print job queue operations.
#include "option1.h" #include "option1.h"
#include <iostream> #include <iostream>
@@ -16,6 +17,9 @@ bool running = true;
int lastIndex = 0; int lastIndex = 0;
std::string deletedLine; std::string deletedLine;
// Undo the last text modification.
// Reverses INSERT/DELETE actions by applying the inverse operation.
// Moves reversed action into redoStack.
void Undo() void Undo()
{ {
if (!undoStack.IsEmpty()) { if (!undoStack.IsEmpty()) {
@@ -29,6 +33,10 @@ void Undo()
redoStack.Push(action); redoStack.Push(action);
} }
} }
// Redo the last undone modification.
// Re-applies an action previously undone.
// Pushes the executed action back into undoStack.
void Redo() void Redo()
{ {
if (!redoStack.IsEmpty()) { if (!redoStack.IsEmpty()) {
@@ -43,7 +51,9 @@ void Redo()
} }
} }
// Main menu loop for the Console Text Editor.
// Provides editing operations, queueing print jobs,
// and demonstrating FIFO behavior through job processing.
int RunApp() int RunApp()
{ {
// Implement the Console Text Editor application logic here // Implement the Console Text Editor application logic here
@@ -62,31 +72,56 @@ int RunApp()
} }
case 3: { case 3: {
std::cout << "----------Current document----------" << std::endl; std::cout << "----------Current document----------" << std::endl;
for (int i = 0; i < document.GetSize(); i++) for (int i = 0; i < document.GetSize(); i++) {
std::cout << i + 1 << ". " << document.GetAtIndex(i) << std::endl; std::cout << document.GetAtIndex(i) << std::endl;
std::cout << "------------------------------------\n\n"; }
std::cout << std::endl;
break; break;
} }
// Build a single print job containing the entire document.
// Snapshot is stored as a single string and enqueued.
case 4: { case 4: {
for (int i = 0; i < document.GetSize(); ++i) std::cout << "----------Add print job----------" << std::endl;
printQueue.Enqueue(document.GetAtIndex(i));
std::cout << "----------Printing queue-----------" << std::endl;
while (!printQueue.IsEmpty())
std::cout << printQueue.Dequeue() << std::endl;
std::cout << "------------------------------------\n\n";
if (document.GetSize() == 0) {
std::cout << "Document is empty - nothing added to print queue." << std::endl;
break; break;
} }
case 5: { std::string job;
for (int i = 0; i < document.GetSize(); i++) {
job += document.GetAtIndex(i) + "\n";
}
printQueue.Enqueue(job);
std::cout << "Print job added to queue." << std::endl;
break;
}
// Dequeue and print the next print job.
// Demonstrates FIFO (First-In-First-Out) queue behavior.
case 5: {
if (printQueue.IsEmpty()) {
std::cout << "No prints jobs in queue." << std::endl;
break;
}
std::string job = printQueue.Dequeue();
std::cout << "----------Printing job-----------" << std::endl;
std::cout << job << std::endl;
std::cout << "------------------------------------\n\n";
break;
}
case 6: {
std::cout << "----------UNDO----------" <<std::endl; std::cout << "----------UNDO----------" <<std::endl;
Undo(); Undo();
break; break;
} }
case 6: { case 7: {
std::cout << "----------REDO----------" <<std::endl; std::cout << "----------REDO----------" <<std::endl;
Redo(); Redo();
break; break;

View File

@@ -1,4 +1,7 @@
// option1.h : Option 1 (Standard): Console Text Editor. // Option 1: Console Text Editor
// Uses a doubly linked list for storing document lines,
// two stacks for undo/redo operations,
// and a queue for print-job management.
#pragma once #pragma once

View File

@@ -1,43 +1,38 @@
// Option 1 (Standard): Console Text Editor.
//
#include <iostream> #include <iostream>
#include <string> #include <string>
#include "option1.h" #include "option1.h"
#include <limits> #include <limits>
#include "SharedLib.h" #include "SharedLib.h"
#include "TLinkedList.h" #include "TLinkedList.h"
#include "TPerson.h" #include "TPerson.h"
// Assignment specific helpers in option1.h // Entry point for Category 2, Option 1 (Cruise Ship Manifest).
// Steps:
// 1) Load names from DATA/random_names.txt into employee and guest lists
// 2) Merge-sort both lists alphabetically (lastName, firstName)
// 3) Convert guests to an array and quick-sort by cabinSize, then lastName
// 4) Allow the user to search (binary search) by surname in the chosen list
int RunApp() int RunApp()
{ {
/* Path to the names data file // Path to the names data file.
This is MY absolute path -- change to your local path for this to read properly // IMPORTANT: working directory must be set so that "DATA/random_names.txt" resolves correctly.
something like "C:\Users\Username\FolderYouSavedTheSubmissionIn\Exam\IKT203Exam\DATA\random_names.txt" const std::string filename = "DATA/random_names.txt";
Double slash is needed for string to pass the correct file path */
const std::string filename = "C:\\Users\\csand\\IKT203\\Exam\\IKT203Exam\\DATA\\random_names.txt";
pack("Reading names and grouping them."); pack("Reading names and grouping them.");
// Call the utility function with the name callback // Call the utility function with the name callback
readNamesFromFile(filename, onNameRead); readNamesFromFile(filename, onNameRead);
pack("Finished reading names."); pack("Finished reading names.");
/////////////////////////// Merge sorting /////////////////////////// /////////////////////////// Merge sorting ///////////////////////////
// Sort both employee and guest linked lists alphabetically
// using the linked-list merge sort implementation in TLinkedList.
e.Sort(); e.Sort();
g.Sort(); g.Sort();
pack("Sorting."); pack("Sorting.");
// Attempt at "beautifying" the terminal output somewhat // Attempt at "beautifying" the terminal output somewhat
pack("Employees merge sorted alphabetically."); pack("Employees merge sorted alphabetically.");
TPerson* employeeAlphaSort[e.GetSize()]; const int employeeSize = e.GetSize();
auto** employeeAlphaSort = new TPerson*[employeeSize];
printline(); printline();
for (int i = 0; i < e.GetSize(); i++) { for (int i = 0; i < e.GetSize(); i++) {
std::cout << "[" << i << "] " << e.GetAtIndex(i).lastName << ", " << e.GetAtIndex(i).firstName std::cout << "[" << i << "] " << e.GetAtIndex(i).lastName << ", " << e.GetAtIndex(i).firstName
@@ -45,8 +40,9 @@ int RunApp()
employeeAlphaSort[i] = new TPerson(e.GetAtIndex(i)); employeeAlphaSort[i] = new TPerson(e.GetAtIndex(i));
} }
printline(); printline();
pack("Guests merger sorted alphabetically."); pack("Guests merge sorted alphabetically.");
TPerson* guestAlphaSort[g.GetSize()]; const int guestSize = g.GetSize();
auto** guestAlphaSort = new TPerson*[guestSize];
printline(); printline();
for (int i = 0; i < g.GetSize(); i++) { for (int i = 0; i < g.GetSize(); i++) {
std::cout << "[" << i << "] " << g.GetAtIndex(i).lastName << ", " << g.GetAtIndex(i).firstName std::cout << "[" << i << "] " << g.GetAtIndex(i).lastName << ", " << g.GetAtIndex(i).firstName
@@ -55,15 +51,15 @@ int RunApp()
} }
printline(); printline();
/////////////////////////// Quick sorting /////////////////////////// /////////////////////////// Quick sorting ///////////////////////////
// Build an array of guests and quick-sort it by:
// 1) cabinSize (ascending), then 2) lastName.
// This array is used to optimise cabin assignment.
// creating array from guest linked list // creating array from guest linked list
auto** guestList = new TPerson*[guestCount]; auto** guestList = new TPerson*[guestCount];
for (int i = 0; i < guestCount; i++) { for (int i = 0; i < guestCount; i++) {
guestList[i] = new TPerson(g.GetAtIndex(i)); guestList[i] = new TPerson(g.GetAtIndex(i));
} }
// Quicksorting the guestlist array
Utils::QuickSort(guestList, 0, guestCount - 1); Utils::QuickSort(guestList, 0, guestCount - 1);
pack("Guests quick sorted by 1) cabinsize, 2) lastname."); pack("Guests quick sorted by 1) cabinsize, 2) lastname.");
@@ -74,19 +70,16 @@ int RunApp()
} }
printline(); printline();
/////////////////////////// Binary search /////////////////////////// /////////////////////////// Binary search ///////////////////////////
// Let the user choose whether to search employees or guests,
// then perform binary search on the corresponding alphabetically
// sorted array and print all matches with that surname.
int choice; int choice;
std::string target; std::string target;
std::cout << "What list do you want to search through: \n [1] Employee\n [2] Guest" << std::endl; std::cout << "What list do you want to search through: \n [1] Employee\n [2] Guest" << std::endl;
std::cin >> choice; std::cin >> choice;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Enter surname to search: " << std::endl; std::cout << "Enter name to search for: " << std::endl;
std::getline(std::cin, target); std::getline(std::cin, target);
switch (choice) { switch (choice) {
@@ -100,21 +93,31 @@ switch (choice) {
} }
} }
/////////////////////////// Cleanup before exit /////////////////////////// /////////////////////////// Cleanup before exit ///////////////////////////
for (int i = 0; i < guestCount; i++) { // Delete all dynamically allocated TPerson objects from:
// - alphabetical employee array
// - alphabetical guest array
// - quick-sorted guestList array
// Then clear the linked lists to avoid memory leaks.
for (int i = 0; i < employeeSize; ++i)
delete employeeAlphaSort[i];
delete[] employeeAlphaSort;
for (int i = 0; i < guestSize; ++i)
delete guestAlphaSort[i];
delete[] guestAlphaSort;
for (int i = 0; i < guestCount; ++i)
delete guestList[i]; delete guestList[i];
}
delete[] guestList; delete[] guestList;
while (e.GetSize() > 0) while (e.GetSize() > 0)
e.Remove(0); e.Remove(0);
while (g.GetSize() > 0) while (g.GetSize() > 0)
g.Remove(0); g.Remove(0);
pack("Cleaned up memory"); pack("Cleaned up memory");
return 0; return 0;
} }

View File

@@ -1,4 +1,6 @@
// option1.h : Option 1 (Standard): Console Text Editor. // Option 1 (Standard): Cruise Ship Manifest.
// Uses linked lists, merge sort, quick sort, and binary search
// to manage guest and employee manifests from random_names.txt.
#pragma once #pragma once
@@ -7,8 +9,13 @@
#include "TLinkedList.h" #include "TLinkedList.h"
#include "TPerson.h" #include "TPerson.h"
// Global lists and counters used across the assignment:
// - 'e' stores EMPLOYEE records
// - 'g' stores GUEST records
// - guestCount / employCount track how many were loaded
inline TLinkedList g, e; inline TLinkedList g, e;
inline int guestCount, employCount = 0; inline int guestCount = 0;
inline int employCount = 0;
@@ -42,9 +49,13 @@ static bool NameReadCallback(const int aIndex, const int aTotalCount, const std:
} }
*/ */
// *Inspired* by the provided NameReadCallback given above // Callback used by readNamesFromFile.
// - Creates a TPerson with status (EMPLOYEE or GUEST)
// - First 1500 entries are EMPLOYEE, the rest are GUEST
// - Appends each person to the appropriate linked list and updates counters
static bool onNameRead(const int aIndex, const int aTotalCount, const std::string& aFirstName, const std::string& aLastName) static bool onNameRead(const int aIndex, const int aTotalCount, const std::string& aFirstName, const std::string& aLastName)
{ {
// Determine status based on index: first 1500 are employees, rest are guests.
const ENumStatus status = (aIndex < 1500) ? EMPLOYEE : GUEST; const ENumStatus status = (aIndex < 1500) ? EMPLOYEE : GUEST;
const TPerson p(aFirstName, aLastName, status); const TPerson p(aFirstName, aLastName, status);
@@ -64,7 +75,10 @@ static bool onNameRead(const int aIndex, const int aTotalCount, const std::strin
return true; return true;
} }
// Binary-search helper:
// - Performs binary search on a sorted array of TPerson* (alphabetical by last name)
// - 'target' is the surname entered by the user
// - Expands left/right from the first match to find and print all matches
inline void SearchAndPrint(TPerson** targetArray, int arraySize, const std::string& target) inline void SearchAndPrint(TPerson** targetArray, int arraySize, const std::string& target)
{ {
int index = Utils::BinarySearch(targetArray, 0, arraySize - 1, target); int index = Utils::BinarySearch(targetArray, 0, arraySize - 1, target);
@@ -77,10 +91,12 @@ inline void SearchAndPrint(TPerson** targetArray, int arraySize, const std::stri
int left = index - 1; int left = index - 1;
int right = index + 1; int right = index + 1;
// Move left while neighbouring entries share the same first or last name
while (left >= 0 && (targetArray[left]->firstName == target || targetArray[left]->lastName == target)) { while (left >= 0 && (targetArray[left]->firstName == target || targetArray[left]->lastName == target)) {
--left; --left;
} }
// Move right while neighbouring entries share the same first or last name
while (right < arraySize && (targetArray[right]->firstName == target || targetArray[right]->lastName == target)) { while (right < arraySize && (targetArray[right]->firstName == target || targetArray[right]->lastName == target)) {
++right; ++right;
} }

View File

@@ -10,7 +10,8 @@ add_executable(Assignment-03
TBST.cpp TBST.cpp
TBST.h TBST.h
TEmployee.h TEmployee.h
TTreeQueue.cpp TAVL.cpp
TAVL.h
) )
# Conditionally add the correct source file # Conditionally add the correct source file

View File

@@ -0,0 +1,243 @@
#include "TAVL.h"
#include <iostream>
#include <unordered_set>
#include "TTreeQueue.h"
#include "Utils.h"
// Private helpers
int TAVL::getHeight(const AVLNode *node)
{
return node ? node->height : 0;
}
int TAVL::getBalance(const AVLNode *node)
{
if (!node)
return 0;
return getHeight(node->left) - getHeight(node->right);
}
AVLNode *TAVL::rotateRight(AVLNode *y)
{
if (!y || !y->left)
return y;
AVLNode* x = y->left;
AVLNode* n2 = x ? x->right : nullptr;
x->right = y;
y->left = n2;
x->height = 1 + std::max(getHeight(x->left), getHeight(x->right));
y->height = 1 + std::max(getHeight(y->left), getHeight(y->right));
return x;
}
AVLNode *TAVL::rotateLeft(AVLNode *x)
{
if (!x || !x->right)
return x;
AVLNode* y = x->right;
AVLNode* n2 = y ? y->left : nullptr;
y->left = x;
x->right = n2;
x->height = 1 + std::max(getHeight(x->left), getHeight(x->right));
y->height = 1 + std::max(getHeight(y->left), getHeight(y->right));
return y;
}
// Recursive AVL insert:
// - Insert key as in a normal BST.
// - Update node height.
// - Compute balance factor and apply the appropriate rotation if unbalanced.
AVLNode *TAVL::insert(AVLNode *n, const int key)
{
if (!n)
return new AVLNode(key);
if (key < n->key)
n->left = insert(n->left, key);
else if (key > n->key)
n->right = insert(n->right, key);
else
return n; // Ignore duplicates
n->height = 1 + std::max(getHeight(n->left), getHeight(n->right));
const int balance = getBalance(n);
if (balance > 1 && key < n->left->key)
{
//std::cout << "L-L rotation on [" << n->key << "]" << std::endl; <--- uncomment for terminal output of rotations
return rotateRight(n);
}
if (balance < -1 && key > n->right->key)
{
//std::cout << "R-R rotation on [" << n->key << "]" << std::endl; <--- uncomment for terminal output of rotations
return rotateLeft(n);
}
if (balance > 1 && key > n->left->key)
{
//std::cout << "L-R rotation on [" << n->key << "]" << std::endl; <--- uncomment for terminal output of rotations
n->left = rotateLeft(n->left);
return rotateRight(n);
}
if (balance < -1 && key < n->right->key)
{
//std::cout << "R-L rotation on [" << n->key << "]" << std::endl; <--- uncomment for terminal output of rotations
n->right = rotateRight(n->right);
return rotateLeft(n);
}
return n;
}
void TAVL::preorder(const AVLNode* node)
{
if (!node)
return;
std::cout << "[" << node->key << "] ";
preorder(node->left);
preorder(node->right);
}
void TAVL::inorder(const AVLNode* node)
{
if (!node)
return;
inorder(node->left);
std::cout << "[" << node->key << "] ";
inorder(node->right);
}
void TAVL::postorder(const AVLNode *node)
{
if (!node)
return;
postorder(node->left);
postorder(node->right);
std::cout << "[" << node->key << "] ";
}
void TAVL::levelorder(const AVLNode* node)
{
if (!node)
return;
TTreeQueue<AVLNode> q;
q.Enqueue(const_cast<AVLNode*>(node));
while (!q.IsEmpty()) {
const AVLNode* cur = q.Dequeue();
std::cout << "[" << cur->key << "] ";
if (cur->left)
q.Enqueue(cur->left);
if (cur->right)
q.Enqueue(cur->right);
}
}
// Public functions
///<summary> Insert node </summary
///<param name="key"> Node key value (int) </param>
/// <returns> None </returns>
void TAVL::Insert(const int key)
{
root = insert(root, key);
}
///<summary> Inorder callback </summary
///<param name=""> AVLNode *node </param>
/// <returns> Bool </returns>
bool TAVL::Inorder(const AVLNode *node)
{
if (!node)
return true;
inorder(node);
std::cout << std::endl;
return true;
}
///<summary> Postorder callback </summary
///<param name=""> AVLNode *node </param>
/// <returns> Bool </returns>
bool TAVL::Postorder(const AVLNode *node)
{
if (!node)
return true;
postorder(node);
std::cout << std::endl;
return true;
}
///<summary> Preorder callback </summary
///<param name=""> AVLNode *node </param>
/// <returns> Bool </returns>
bool TAVL::Preorder(const AVLNode *node)
{
if (!node)
return true;
preorder(node);
std::cout << std::endl;
return true;
}
///<summary> LevelOrder callback </summary
///<param name=""> AVLNode *node </param>
/// <returns> Bool </returns>
bool TAVL::LevelOrder(const AVLNode *node)
{
if (!node)
return true;
levelorder(node);
std::cout << std::endl;
return true;
}
///<summary> Prints the desired sorting order </summary
///<param name="cb"> Callback for the desired ordering algorithm (e.g. PrintOrder(LevelOrder) will print the Level Order algorithm to the terminal)</param>
/// <returns>None</returns>
void TAVL::PrintOrder(FOrderTraversal cb)
{
if (!cb)
return;
cb(root);
}
// Helper to build an AVL tree with 'count' unique random keys
// in the range [minRange, maxRange]. Used only for demonstration in RunApp()
///<summary> Populates AVL tree </summary
///<param name="avl"> The AVL tree to be populated</param>
///<param name"count">How many elements to be populated into the tree</param>
///<param name"minRange">Lower bounds of key value range (e.g., the lower limit of element value)</param>
///<param name"maxRange">Upper bounds of key value range (e.g., higher limit og element value)</param>
/// <returns>None</returns>
void TAVL::Populate(TAVL* avl, const int count, const int minRange, const int maxRange)
{
std::unordered_set<int> AVLset;
for (int i = 0; i < count; i++) {
int val = Utils::RandomInt(minRange, maxRange);
while (AVLset.count(val))
val = Utils::RandomInt(minRange, maxRange);
//std::cout << "Inserting [" << val << "]" << std::endl; <----- Uncomment for terminal output of insertions
avl->Insert(val);
AVLset.insert(val);
}
}

View File

@@ -0,0 +1,51 @@
#ifndef IKT203_COURSE_ASSIGNMENTS_TAVL_H
#define IKT203_COURSE_ASSIGNMENTS_TAVL_H
// Node used in the AVL tree.
// Stores only an integer key and height (no TEmployee data).
struct AVLNode {
int key;
AVLNode* left;
AVLNode* right;
int height;
explicit AVLNode(const int k) : key(k), left(nullptr), right(nullptr), height(1) {}
};
typedef bool (*FOrderTraversal)(const AVLNode* AVLNode);
// Self-balancing AVL tree used to demonstrate rotations and traversals.
// Only stores integer keys; no payload data is required for this assignment.
class TAVL {
private:
AVLNode* root;
static int getHeight(const AVLNode* node);
static int getBalance(const AVLNode *node);
static AVLNode* rotateRight(AVLNode* y);
static AVLNode* rotateLeft(AVLNode* x);
static AVLNode* insert(AVLNode* n, int key);
static void inorder(const AVLNode* node);
static void preorder(const AVLNode* node);
static void postorder(const AVLNode* node);
static void levelorder(const AVLNode* node);
public:
TAVL() : root(nullptr) {};
~TAVL() = default;
void Insert(int key);
static bool Inorder(const AVLNode* node);
static bool Postorder(const AVLNode *node);
static bool Preorder(const AVLNode *node);
static bool LevelOrder(const AVLNode *node);
void PrintOrder(FOrderTraversal);
static void Populate(TAVL* AVLtree, int count, int minRange, int maxRange);
};
#endif //IKT203_COURSE_ASSIGNMENTS_TAVL_H

View File

@@ -1,48 +1,58 @@
#include "TBST.h" #include "TBST.h"
#include <iostream> #include <iostream>
#include "TTreeQueue.h" #include "TTreeQueue.h"
void TBST::destroy(Node *node) void TBST::destroy(BSTNode *node)
{ {
if (!node) if (!node)
return; return;
destroy(node->left); destroy(node->left);
destroy(node->right); destroy(node->right);
// TBST owns the TEmployee* stored in each node, so delete it here.
delete node->data; delete node->data;
delete node; delete node;
} }
///<summary> Insert node </summary
///<param name="key"> Node key value (int) </param>
///<param name="data"> Employee data (TEmployee) </param>
/// <returns> None </returns>
void TBST::Insert(const int key, TEmployee *data) void TBST::Insert(const int key, TEmployee *data)
{ {
root = insert(root, key, data); root = insert(root, key, data);
} }
Node* TBST::insert(Node* node, const int key, TEmployee *data) BSTNode* TBST::insert(BSTNode* node, const int key, TEmployee *data)
{ {
if (node == nullptr) { if (node == nullptr) {
auto* n = new Node{key, data, nullptr, nullptr}; auto* n = new BSTNode{key, data, nullptr, nullptr};
return n; return n;
} }
if (key < node->key) if (key < node->key)
node->left = insert(node->left, key, data); node->left = insert(node->left, key, data);
else if (key > node->key) else if (key > node->key)
node->right = insert(node->right, key, data); node->right = insert(node->right, key, data);
else else {
std::cout << "Error with node insertion" << std::endl; // Duplicate key: do not modify the existing node.
// 'data' was allocated by the caller, so we must delete it here
// to avoid a memory leak.
std::cout << "Duplicate key [" << key << "], ignoring insert." << std::endl;
delete data;
}
return node; return node;
} }
///<summary> Search for node </summary
///<param name="key"> Node key value (int) </param>
/// <returns> TEmployee </returns>
TEmployee *TBST::Search(int key) const TEmployee *TBST::Search(int key) const
{ {
const Node* result = search(root, key); const BSTNode* result = search(root, key);
return result ? result->data : nullptr; return result ? result->data : nullptr;
} }
Node* TBST::search(Node* node, const int key) BSTNode* TBST::search(BSTNode* node, const int key)
{ {
if (node == nullptr) if (node == nullptr)
return nullptr; return nullptr;
@@ -54,12 +64,15 @@ Node* TBST::search(Node* node, const int key)
return search(node->right, key); return search(node->right, key);
} }
///<summary> Delete node </summary
///<param name="key"> Node key value (int) </param>
/// <returns> None </returns>
void TBST::Delete(const int key) void TBST::Delete(const int key)
{ {
root = remove(root, key); root = remove(root, key);
} }
Node *TBST::remove(Node *node, const int key) BSTNode *TBST::remove(BSTNode *node, const int key)
{ {
if (node == nullptr) if (node == nullptr)
return nullptr; return nullptr;
@@ -76,21 +89,24 @@ Node *TBST::remove(Node *node, const int key)
} }
// Right child only // Right child only
if (node->left == nullptr) { if (node->left == nullptr) {
Node* child = node->right; BSTNode* child = node->right;
delete node->data; delete node->data;
delete node; delete node;
return child; return child;
} }
// Left child only // Left child only
if (node->right == nullptr) { if (node->right == nullptr) {
Node* child = node->left; BSTNode* child = node->left;
delete node->data; delete node->data;
delete node; delete node;
return child; return child;
} }
// Two children // Two children:
// 1) Find the smallest node in the right subtree (inorder successor)
// 2) Copy its key + data into the current node
// 3) Remove the successor node from the right subtree
else { else {
Node* minRight = findMin(node->right); BSTNode* minRight = findMin(node->right);
node->key = minRight->key; node->key = minRight->key;
node->data = minRight->data; node->data = minRight->data;
node->right = remove(minRight->right, minRight->key); node->right = remove(minRight->right, minRight->key);
@@ -99,16 +115,16 @@ Node *TBST::remove(Node *node, const int key)
return node; return node;
} }
Node* TBST::findMin(Node* node) BSTNode* TBST::findMin(BSTNode* node)
{ {
while (node && node->left) while (node && node->left)
node = node->left; node = node->left;
return node; return node;
} }
/// Traversals // Traversals
/// Private helpers // Private helpers
void TBST::preorder(const Node* node) void TBST::preorder(const BSTNode* node)
{ {
if (!node) if (!node)
return; return;
@@ -117,7 +133,7 @@ void TBST::preorder(const Node* node)
preorder(node->right); preorder(node->right);
} }
void TBST::inorder(const Node* node) void TBST::inorder(const BSTNode* node)
{ {
if (!node) if (!node)
return; return;
@@ -126,7 +142,7 @@ void TBST::inorder(const Node* node)
inorder(node->right); inorder(node->right);
} }
void TBST::postorder(const Node *node) void TBST::postorder(const BSTNode *node)
{ {
if (!node) if (!node)
return; return;
@@ -135,48 +151,52 @@ void TBST::postorder(const Node *node)
std::cout << "[" << node->key << "] "; std::cout << "[" << node->key << "] ";
} }
void TBST::levelorder(const Node* node) void TBST::levelorder(const BSTNode* node)
{ {
if (!node) if (!node)
return; return;
TTreeQueue q; TTreeQueue<BSTNode> q;
q.Enqueue(const_cast<Node*>(node)); q.Enqueue(const_cast<BSTNode*>(node));
while (!q.IsEmpty()) { while (!q.IsEmpty()) {
const Node* cur = q.Dequeue(); const BSTNode* cur = q.Dequeue();
std::cout << "[" << cur->key << "] "; std::cout << "[" << cur->key << "] ";
if (cur->left) if (cur->left)
q.Enqueue(cur->left); q.Enqueue(cur->left);
if (cur->right) if (cur->right)
q.Enqueue(cur->right); q.Enqueue(cur->right);
} }
} }
///<summary> Inorder sorting </summary
/// <returns> None </returns>
void TBST::Inorder() const void TBST::Inorder() const
{ {
inorder(root); inorder(root);
std::cout << std::endl; std::cout << std::endl;
} }
///<summary> Preorder sorting </summary
/// <returns> None </returns>
void TBST::Preorder() const void TBST::Preorder() const
{ {
preorder(root); preorder(root);
std::cout << std::endl; std::cout << std::endl;
} }
///<summary> Postorder sorting </summary
/// <returns> None </returns>
void TBST::Postorder() const void TBST::Postorder() const
{ {
postorder(root); postorder(root);
std::cout << std::endl; std::cout << std::endl;
} }
///<summary> LevelOrder sorting </summary
/// <returns> None </returns>
void TBST::LevelOrder() const void TBST::LevelOrder() const
{ {
levelorder(root); levelorder(root);
std::cout << std::endl; std::cout << std::endl;
} }

View File

@@ -2,36 +2,32 @@
#define IKT203_COURSE_ASSIGNMENTS_TBST_H #define IKT203_COURSE_ASSIGNMENTS_TBST_H
#include "TEmployee.h" #include "TEmployee.h"
// Node in the Binary Search Tree.
struct Node { // Owns a single TEmployee* which is deleted by TBST::destroy/remove.
int key; struct BSTNode {
TEmployee* data; int key; // employee ID
Node* left; TEmployee* data; // employee record
Node* right; BSTNode* left;
BSTNode* right;
}; };
// Standard Binary Search Tree for TEmployee* keyed by employee ID.
// Responsibilities:
// - Owns all TEmployee objects it contains.
// - Provides insert, search, delete, and four traversal methods.
class TBST { class TBST {
private: private:
Node* root; BSTNode* root;
static Node* insert(Node* node, int key, TEmployee* data); static BSTNode* insert(BSTNode* node, int key, TEmployee* data);
static BSTNode* search(BSTNode* node, int key);
static Node* search(Node* node, int key); static BSTNode* remove(BSTNode* node, int key);
static void inorder(const BSTNode* node);
static Node* remove(Node* node, int key); static void preorder(const BSTNode* node);
static void postorder(const BSTNode* node);
static void inorder(const Node* node); static void levelorder(const BSTNode* node);
static void destroy(BSTNode* node);
static void preorder(const Node* node); static BSTNode* findMin(BSTNode* node);
static void postorder(const Node* node);
static void levelorder(const Node* node);
static void destroy(Node* node);
static Node* findMin(Node* node);
public: public:
TBST() = default; TBST() = default;
@@ -40,13 +36,9 @@ class TBST {
void Insert(int key, TEmployee* data); void Insert(int key, TEmployee* data);
[[nodiscard]] TEmployee* Search(int key) const; [[nodiscard]] TEmployee* Search(int key) const;
void Delete(int key); void Delete(int key);
void Inorder() const; void Inorder() const;
void Preorder() const; void Preorder() const;
void Postorder() const; void Postorder() const;
void LevelOrder() const; void LevelOrder() const;
}; };
#endif //IKT203_COURSE_ASSIGNMENTS_TBST_H #endif //IKT203_COURSE_ASSIGNMENTS_TBST_H

View File

@@ -3,7 +3,8 @@
#include <string> #include <string>
#include <utility> #include <utility>
// Simple employee record used in Category 3.
// 'id' is set later by IdGenerator and used as the BST key.
struct TEmployee { struct TEmployee {
std::string firstName; std::string firstName;
std::string lastName; std::string lastName;

View File

@@ -1,37 +0,0 @@
#include "TTreeQueue.h"
#include <stdexcept>
void TTreeQueue::Enqueue(Node* n)
{
if (n == nullptr)
return;
if (IsFull())
throw std::overflow_error("Queue Overflow");
queue[tail] = n;
tail = (tail + 1) % MAX_SIZE;
count++;
}
Node* TTreeQueue::Dequeue()
{
if (IsEmpty())
throw std::underflow_error("Empty Queue");
Node* n = queue[head];
if (n == nullptr)
return nullptr;
head = (head + 1) % MAX_SIZE;
count--;
return n;
}
bool TTreeQueue::IsEmpty() const
{
return count == 0;
}
bool TTreeQueue::IsFull() const
{
return count == MAX_SIZE;
}

View File

@@ -2,13 +2,15 @@
#define TQUEUE_H #define TQUEUE_H
#define MAX_SIZE 200 #define MAX_SIZE 200
#include <stdexcept>
#include "TBST.h" #include "TBST.h"
// Fixed-size circular queue used by the BST and AVL level-order traversals.
// Stores raw pointers to tree nodes (T*). Does not own the nodes.
template <typename T>
struct TTreeQueue { struct TTreeQueue {
Node* queue[MAX_SIZE]; T* queue[MAX_SIZE];
int head = 0; int head = 0;
int tail = 0; int tail = 0;
int count = 0; int count = 0;
@@ -17,10 +19,38 @@ struct TTreeQueue {
TTreeQueue() = default; TTreeQueue() = default;
~TTreeQueue() = default; ~TTreeQueue() = default;
void Enqueue(Node* n); void Enqueue(T* n)
Node* Dequeue(); {
[[nodiscard]] bool IsEmpty() const; if (n == nullptr)
[[nodiscard]] bool IsFull() const; return; // ignore null pointers, nothing to enqueue
if (IsFull())
throw std::overflow_error("Queue Overflow");
queue[tail] = n;
tail = (tail + 1) % MAX_SIZE;
count++;
}
T* Dequeue()
{
if (IsEmpty())
throw std::underflow_error("Empty Queue");
T* n = queue[head];
if (n == nullptr)
return nullptr;
head = (head + 1) % MAX_SIZE;
count--;
return n;
}
bool IsEmpty() const
{
return count == 0;
}
bool IsFull() const
{
return count == MAX_SIZE;
}
}; };

View File

@@ -1,16 +1,27 @@
#include "option1.h" #include "option1.h"
#include <limits> #include <limits>
#include "SharedLib.h"
// Entry point for Category 3, Option 1.
// Demonstrates:
// 1) Building a BST of 200 employees from DATA/random_names.txt
// 2) Running all BST traversals
// 3) Searching and deleting by employee ID
// 4) Building and printing an AVL tree with random integer keys
int RunApp() { int RunApp() {
//Reading names from file for BST population
bst = new TBST(); bst = new TBST();
/* Path to the names data file
This is MY absolute path -- change to your local path for this to read properly // Read 200 employees from the names file and populate the BST.
something like "C:\Users\Username\FolderYouSavedTheSubmissionIn\Exam\IKT203Exam\DATA\random_names.txt" // IMPORTANT: Working directory must be the Portfolio/Assignment-03 folder
Double slash is needed for string to pass the correct file path */ // so that "DATA/random_names.txt" resolves correctly.
const std::string filename = "C:\\Users\\csand\\IKT203\\Exam\\IKT203Exam\\DATA\\random_names.txt"; const std::string filename = "DATA/random_names.txt";
readNamesFromFile(filename, onNameRead); readNamesFromFile(filename, onNameRead);
// --- BST traversals ---
// These calls demonstrate all four traversal orders on the employee BST.
// Comment out this block if the console output becomes too noisy.
pack("Inorder traversal (sorted by ID)"); pack("Inorder traversal (sorted by ID)");
bst->Inorder(); bst->Inorder();
@@ -23,6 +34,8 @@ int RunApp() {
pack("Postorder traversal"); pack("Postorder traversal");
bst->Postorder(); bst->Postorder();
// --- BST search demo ---
// Ask the user for an ID, search in the BST, and print the matching employee (if any).
pack("Search function"); pack("Search function");
std::cout << "\nInput the ID you want to search for\n" << std::endl; std::cout << "\nInput the ID you want to search for\n" << std::endl;
int choice; int choice;
@@ -33,6 +46,9 @@ int RunApp() {
else else
std::cout << "ID not found" << std::endl; std::cout << "ID not found" << std::endl;
// --- BST delete demo ---
// Ask the user for an ID, delete it from the BST if it exists,
// then print the new inorder traversal to show the updated structure.
pack("Remove function"); pack("Remove function");
std::cout << "\nInput the ID you want to remove\n" << std::endl; std::cout << "\nInput the ID you want to remove\n" << std::endl;
std::cin >> choice; std::cin >> choice;
@@ -44,8 +60,36 @@ int RunApp() {
else else
std::cout << "ID not found\n" << std::endl; std::cout << "ID not found\n" << std::endl;
bst->Inorder(); bst->Inorder();
// End of BST block
// --- AVL demo ---
// Build an AVL tree using random integers in [1, 200].
// This tree only stores keys (no TEmployee data) and is used
// to demonstrate balancing and traversals.
pack("AVL");
avl = new TAVL;
TAVL::Populate(avl, 100, 1, 200);
pack("Inorder");
avl->PrintOrder(TAVL::Inorder);
pack("Postorder");
avl->PrintOrder(TAVL::Postorder);
pack("Preorder");
avl->PrintOrder(TAVL::Preorder);
pack("Levelorder");
avl->PrintOrder(TAVL::LevelOrder);
// End of AVL block
// --- Cleanup ---
// TBST destructor deletes all TEmployee objects it owns.
// Here we delete the tree objects themselves to avoid leaks.
pack ("Cleaning up"); pack ("Cleaning up");
delete bst; delete bst;
delete avl;
return 0; return 0;
} }

View File

@@ -3,23 +3,24 @@
#ifndef OPTION1_H #ifndef OPTION1_H
#define OPTION1_H #define OPTION1_H
#include <iostream> #include <iostream>
#include <TTreeQueue.h>
#include <unordered_set> #include <unordered_set>
#include "TAVL.h"
#include "TBST.h" #include "TBST.h"
#include "TEmployee.h" #include "TEmployee.h"
#include "Utils.h" #include "Utils.h"
#include "../../Submissions/Submission-04/BankAccount.h"
/// To keep track of used ID values to ensure // Global state for Category 3, Option 1:
/// all unique IDs // - bst: owns all TEmployee objects (deleted in TBST destructor)
// - avl: separate AVL tree used only to demonstrate balancing on int keys
inline std::unordered_set<int> usedIds; inline std::unordered_set<int> usedIds;
static TBST* bst; static TBST* bst;
static TAVL* avl;
int RunApp(); int RunApp();
// Assign a unique random employee ID in the range [1, 1000].
// Uses 'usedIds' to avoid duplicates so the BST always has unique keys.
inline void IdGenerator(TEmployee* employee) inline void IdGenerator(TEmployee* employee)
{ {
int id = Utils::RandomInt(1, 1000); int id = Utils::RandomInt(1, 1000);
@@ -30,6 +31,11 @@ inline void IdGenerator(TEmployee* employee)
usedIds.insert(id); usedIds.insert(id);
employee->id = id; employee->id = id;
} }
// Callback used by readNamesFromFile.
// - Creates a new TEmployee from the given name.
// - Stops after 200 employees (as required by the assignment).
// - Generates a unique ID and inserts the employee into the BST.
static bool onNameRead(const int index, const int aTotalCount, const std::string& aFirstName, const std::string& aLastName) static bool onNameRead(const int index, const int aTotalCount, const std::string& aFirstName, const std::string& aLastName)
{ {
const auto e = new TEmployee(aFirstName, aLastName); const auto e = new TEmployee(aFirstName, aLastName);
@@ -48,6 +54,7 @@ inline void printline()
std::cout << "----------------------------------------" << std::endl; std::cout << "----------------------------------------" << std::endl;
} }
// Helper to visually separate different demos (traversals, search, etc.) in the console output.
inline void pack(const std::string& line) inline void pack(const std::string& line)
{ {
std::cout << "\n\n\n" << std::endl; std::cout << "\n\n\n" << std::endl;
@@ -56,4 +63,6 @@ inline void pack(const std::string& line)
printline(); printline();
} }
#endif // OPTION1_H #endif // OPTION1_H

View File

@@ -3,10 +3,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
# "ON" = build Option 1, "OFF" = build Option 2. # "ON" = build Option 1, "OFF" = build Option 2.
option(BUILD_ASSIGNMENT_04_OPTION_1 "Build Assignment Option 1 (Standard)" OFF) option(BUILD_ASSIGNMENT_04_OPTION_1 "Build Assignment Option 1 (Standard)" ON)
add_executable(Assignment-04 add_executable(Assignment-04
main.cpp main.cpp
option1.cpp
) )
if(BUILD_ASSIGNMENT_04_OPTION_1) if(BUILD_ASSIGNMENT_04_OPTION_1)

View File

@@ -28,16 +28,18 @@ To force an update (e.g., in Visual Studio):
#include <iostream> #include <iostream>
#include <string_view> #include <string_view>
#include "option1.h"
static constexpr std::string_view AssignmentName = "Category 4: Graphs & Dijkstra's Algorithm"; static constexpr std::string_view AssignmentName = "Category 4: Graphs & Dijkstra's Algorithm";
#if ASSIGNMENT_04_OPTION == 1
static constexpr std::string_view AssignmentOption = "Option 1 (Standard): Data Center Network Monitor."; static constexpr std::string_view AssignmentOption = "Option 1 (Standard): Data Center Network Monitor.";
/*
#if ASSIGNMENT_04_OPTION == 1
#include "option1.h" #include "option1.h"
#elif ASSIGNMENT_04_OPTION == 2 #elif ASSIGNMENT_04_OPTION == 2
static constexpr std::string_view AssignmentOption = "Option 2 (Advanced): Inter-city Logistics Router."; static constexpr std::string_view AssignmentOption = "Option 2 (Advanced): Inter-city Logistics Router.";
#include "option2.h" #include "option2.h"
#endif #endif
*/
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {

View File

@@ -1,6 +1,274 @@
#include "option1.h" #include "option1.h"
#include <iostream> #include <iostream>
#include "SharedLib.h"
#include <algorithm>
constexpr float INF = 1e9f;
// Global graph storage and lookup table used by the ReadGraph callbacks.
// These are populated automatically when readGraphFromFile(...) is executed.
Graph g;
std::unordered_map<std::string, int> nameToIndex;
std::string filename = "DATA/network_graph.txt"; // Remember to set working directory for this path to work
//////////////////////////////// Callbacks ////////////////////////////////
// Callback: called once for each node read from network_graph.txt.
// Responsible for registering the vertex in the graph and recording its index.
bool onNodeRead(const int aIndex, const int aTotalCount, const std::string& aNode)
{
const int idx = g.AddVertex(aNode);
nameToIndex[aNode] = idx;
return true;
}
// Callback: called for each edge (connection) read from the file.
// Translates node names into vertex indices and adds an undirected weighted edge.
bool onEdgeRead(const int aIndex, const int aTotalCount, const std::string& aFromNode, const std::string& aToNode, const float aWeight)
{
const int fromIdx = nameToIndex[aFromNode];
const int toIdx = nameToIndex[aToNode];
g.AddUndirectedEdge(fromIdx, toIdx, aWeight);
return true;
}
//////////////////////////////// Dijkstra algorithm ////////////////////////////////
// Computes the shortest path between src and dst using Dijkstra's algorithm.
// Uses the custom MinHeap class as the priority queue.
// Output: 'outPath' contains vertex indices from src -> dst in order.
// Returns INF if no path exists.
float Dijkstra(const Graph& graph, int src, int dst, std::vector<int>& outPath)
{
const int n = graph.GetVertexCount();
std::vector<float> dist(n, INF);
std::vector<int> prev(n, -1);
std::vector<bool> visited(n, false);
dist[src] = 0.0f;
MinHeap heap;
heap.Push(src, 0.0f);
// Pop the next closest unvisited vertex. Old entries with outdated distances
// are skipped via the 'visited' array (lazy deletion).
while (!heap.isEmpty()) {
HeapNode* node = heap.Pop();
const int u = node->vertex;
// float d = node->distance; not needed
delete node;
if (visited[u])
continue;
visited[u] = true;
if (u == dst)
break;
for (const TEdge* e : graph.GetEdges(u)) {
int v = e->toIndex;
float w = e->weight;
if (visited[v])
continue;
if (dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
prev[v] = u;
heap.Push(v, dist[v]);
}
}
}
outPath.clear();
if (dist[dst] == INF)
return INF;
for (int v = dst; v != -1; v = prev[v])
outPath.push_back(v);
std::reverse(outPath.begin(), outPath.end());
return dist[dst];
}
//////////////////////////////// Class logic ////////////////////////////////
// Graph
// Clean up all dynamically allocated vertices and edges.
// Graph owns all TVertex* and TEdge*.
Graph::~Graph()
{
for (TVertex* v : vertices) {
for (TEdge* e : v->edges) {
delete e;
}
delete v;
}
}
int Graph::AddVertex(const std::string& name)
{
auto* v = new TVertex;
v->name = name;
vertices.push_back(v);
return static_cast<int>(vertices.size()) - 1;
}
void Graph::AddUndirectedEdge(int fromIndex, int toIndex, float weight)
{
TEdge* e1 = new TEdge;
e1->toIndex = toIndex;
e1->weight = weight;
TEdge* e2 = new TEdge;
e2->toIndex = fromIndex;
e2->weight = weight;
vertices[fromIndex]->edges.push_back(e1);
vertices[toIndex]->edges.push_back(e2);
}
int Graph::GetVertexCount() const
{
return static_cast<int>(vertices.size());
}
const TVertex *Graph::GetVertex(int index) const
{
return vertices[index];
}
const std::vector<TEdge*>& Graph::GetEdges(const int index) const
{
return vertices[index]->edges;
}
// Heap
// Min-heap storing (vertex, distance) pairs.
// Used by Dijkstra as a priority queue.
MinHeap::~MinHeap()
{
for (HeapNode* n : data)
delete n;
}
bool MinHeap::isEmpty() const
{
return data.empty();
}
void MinHeap::Push(int vertex, float dist)
{
auto* n = new HeapNode{vertex, dist};
data.push_back(n);
HeapUp(static_cast<int>(data.size()) - 1);
}
HeapNode* MinHeap::Pop()
{
if (data.empty())
return nullptr;
HeapNode* root = data[0];
data[0] = data.back();
data.pop_back();
if (!data.empty())
HeapDown(0);
return root;
}
void MinHeap::HeapUp(int idx)
{
while (idx > 0) {
int parent = (idx - 1) / 2;
if (data[parent]->distance <= data[idx]->distance)
break;
std::swap(data[idx], data[parent]);
idx = parent;
}
}
void MinHeap::HeapDown(int idx)
{
int n = static_cast<int>(data.size());
while (true) {
int left = 2 * idx + 1;
int right = 2 * idx + 2;
int smallest = idx;
if (left < n && data[left]->distance < data[smallest]->distance)
smallest = left;
if (right < n && data[right]->distance < data[smallest]->distance)
smallest = right;
if (smallest == idx)
break;
std::swap(data[idx], data[smallest]);
idx = smallest;
}
}
// Entry point for Assignment 04 Option 1.
// Loads the network graph from file, prints node list,
// prompts the user for source and destination,
// and runs Dijkstra to find the lowest-latency path.
int RunApp() { int RunApp() {
readGraphFromFile(filename, onNodeRead, onEdgeRead);
// Debug: Print all nodes and vertices
/*
pack("Graph");
for (int i = 0; i < g.GetVertexCount(); i++) {
const TVertex* v = g.GetVertex(i);
std::cout << i << ": " << v->name << std::endl;
for (const TEdge* e : g.GetEdges(i)) {
std::cout << " -> " << e->toIndex << " (weight = " << e->weight << ")" << std::endl;
}
}
*/
/* Debug heap test
pack("Heap");
MinHeap test;
test.Push(1, 5.0f);
test.Push(2, 3.0f);
test.Push(3, 10.0f);
while (!test.isEmpty())
{
const HeapNode* n = test.Pop();
std::cout << "(" << n->vertex << ", " << n->distance << ")" << "\n";
delete n;
}
printline();
*/
std::cout << "\nGraph:" << std::endl;
for (int i = 0; i < g.GetVertexCount(); ++i)
std::cout << i << ": " << g.GetVertex(i)->name << std::endl;
int src, dst;
std::cout << "\nEnter source index: ";
std::cin >> src;
std::cout << "\nEnter destination index: ";
std::cin >> dst;
if (src < 0 || src >= g.GetVertexCount() ||
dst < 0 || dst >= g.GetVertexCount()) {
std::cout << "Invalid indices.\n";
return 0;
}
std::vector<int> path;
float total = Dijkstra(g, src, dst, path);
if (total >= INF) {
std::cout << "\nNo path between those nodes.\n";
} else {
std::cout << "\nLowest latency path: ";
for (size_t i = 0; i < path.size(); ++i) {
std::cout << g.GetVertex(path[i])->name;
if (i + 1 < path.size()) std::cout << " -> ";
}
std::cout << " \n(Total: " << total << " ms)\n";
}
printline();
return 0; return 0;
} }

View File

@@ -2,6 +2,81 @@
#ifndef OPTION1_H #ifndef OPTION1_H
#define OPTION1_H #define OPTION1_H
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
// Structs and classes
struct TEdge {
int toIndex;
float weight;
};
struct TVertex {
std::string name;
std::vector<TEdge*> edges;
};
struct HeapNode {
int vertex;
float distance;
};
class MinHeap {
private:
std::vector<HeapNode*> data;
void HeapUp(int idx);
void HeapDown(int idx);
public:
~MinHeap();
[[nodiscard]] bool isEmpty() const;
void Push(int vertex, float dist);
HeapNode* Pop();
};
class Graph {
private:
std::vector<TVertex*> vertices; // Owns all TVertex*
public:
~Graph();
int AddVertex(const std::string& name);
void AddUndirectedEdge(int fromIndex, int toIndex, float weight);
[[nodiscard]] int GetVertexCount() const;
[[nodiscard]] const TVertex* GetVertex(int index) const;
[[nodiscard]] const std::vector<TEdge*>& GetEdges(int index) const;
};
// Callbacks & funcs
bool onNodeRead(int aIndex, int aTotalCount, const std::string& aNode);
bool onEdgeRead(int aIndex, int aTotalCount, const std::string& aFromNode, const std::string& aToNode, float aWeight);
float Dijkstra(const Graph& graph, int src, int dst, std::vector<int>& outPath);
// Terminal tidying
inline void printline()
{
std::cout << "----------------------------------------" << std::endl;
}
inline void pack(const std::string& line)
{
std::cout << "\n\n\n" << std::endl;
printline();
std::cout << line << std::endl;
printline();
}
int RunApp(); int RunApp();

View File

@@ -27,7 +27,7 @@ static bool EdgeReadCallback(const int aIndex, const int aTotalCount, const std:
return true; return true;
} }
/*
int RunApp() int RunApp()
{ {
@@ -44,4 +44,4 @@ int RunApp()
std::cout << "\nFinished reading graph." << std::endl; std::cout << "\nFinished reading graph." << std::endl;
return 0; return 0;
} }*/

View File

@@ -2,8 +2,8 @@
#ifndef OPTION2_H #ifndef OPTION2_H
#define OPTION2_H #define OPTION2_H
/*
int RunApp(); int RunApp();
*/
#endif // OPTION2_H #endif // OPTION2_H

View File

@@ -3,6 +3,7 @@
#define SHARED_LIB_H #define SHARED_LIB_H
#include <string> #include <string>
#include <functional> #include <functional>
#include "../Assignment-03/TAVL.h"
/// <summary> /// <summary>
/// Delegate type for processing a name read from a file. /// Delegate type for processing a name read from a file.
@@ -97,4 +98,4 @@ typedef bool (*FSongRead)(
void ReadSongsFromFile(const std::string& aFilename, FSongRead aOnSongRead); void ReadSongsFromFile(const std::string& aFilename, FSongRead aOnSongRead);
#endif // SHARED_LIB_H #endif // SHARED_LIB_H

View File

@@ -3,7 +3,19 @@
#include "SharedLib.h" #include "SharedLib.h"
TDoublyLinkedList::~TDoublyLinkedList()
{
const Node* cur = head;
while (cur) {
const Node* next = cur->GetNext();
delete cur;
cur = next;
}
head = tail = nullptr;
size = 0;
}
// Append a new line at the end of the list.
void TDoublyLinkedList::Append(const std::string& line) void TDoublyLinkedList::Append(const std::string& line)
{ {
auto* newNode = new Node(line); auto* newNode = new Node(line);
@@ -17,6 +29,7 @@ void TDoublyLinkedList::Append(const std::string& line)
size++; size++;
} }
// Insert a new line at the beginning.
void TDoublyLinkedList::Prepend(const std::string& line) void TDoublyLinkedList::Prepend(const std::string& line)
{ {
auto* newNode = new Node(line); auto* newNode = new Node(line);
@@ -43,6 +56,7 @@ TDoublyLinkedList::Node* TDoublyLinkedList::NavigateToNode(const int index) cons
return node; return node;
} }
// Removes the node at the given index and updates head/tail if needed.
void TDoublyLinkedList::Remove(const int index) void TDoublyLinkedList::Remove(const int index)
{ {
auto* node = NavigateToNode(index); auto* node = NavigateToNode(index);

View File

@@ -2,13 +2,16 @@
#define TDOUBLYLINKEDLIST_H #define TDOUBLYLINKEDLIST_H
#include <string> #include <string>
#include <utility> #include <utility>
#include "SharedLib.h"
// Doubly linked list used to store document lines.
// Supports insertion, removal, and indexed access.
// Chosen because it allows efficient updates in the middle of the document.
class TDoublyLinkedList { class TDoublyLinkedList {
private: private:
// Internal node storing a single line of text
// and links to previous and next nodes.
struct Node { struct Node {
std::string line; std::string line;
Node* next; Node* next;
@@ -45,12 +48,21 @@ private:
public: public:
TDoublyLinkedList() : head(nullptr), tail(nullptr), size(0) {} TDoublyLinkedList() : head(nullptr), tail(nullptr), size(0) {}
~TDoublyLinkedList() = default; ~TDoublyLinkedList();
void Append(const std::string &line); void Append(const std::string &line);
void Prepend(const std::string& line); void Prepend(const std::string& line);
// Returns pointer to node at given index.
// Linear traversal; used internally by Remove and InsertAtIndex.
[[nodiscard]] Node* NavigateToNode(int index) const; [[nodiscard]] Node* NavigateToNode(int index) const;
// Removes a node at the given index.
// Updates links and frees the removed node.
void Remove(int index); void Remove(int index);
// Returns the text stored at the given index.
// Uses NavigateToNode internally.
[[nodiscard]] std::string GetAtIndex(int index) const; [[nodiscard]] std::string GetAtIndex(int index) const;
void InsertAtIndex(int index, const std::string &line); void InsertAtIndex(int index, const std::string &line);
[[nodiscard]] int GetSize() const; [[nodiscard]] int GetSize() const;

View File

@@ -149,8 +149,8 @@ TLinkedList::Node *TLinkedList::MergeList(Node *a, Node *b)
return result; return result;
} }
/// Time complexity O(n log n) at all times // Time complexity O(n log n) at all times
/// Does NOT sort in place, so more memory is needed to complete // Does NOT sort in place, so more memory is needed to complete
TLinkedList::Node *TLinkedList::MergeSort(Node *head) TLinkedList::Node *TLinkedList::MergeSort(Node *head)
{ {
if (head == nullptr || head->next == nullptr) if (head == nullptr || head->next == nullptr)
@@ -166,6 +166,8 @@ TLinkedList::Node *TLinkedList::MergeSort(Node *head)
return MergeList(front, back); return MergeList(front, back);
} }
// Stable merge sort on the linked list.
// Time complexity: O(n log n), requires extra pointers but no extra arrays.
void TLinkedList::Sort() void TLinkedList::Sort()
{ {
this->head = MergeSort(head); this->head = MergeSort(head);

View File

@@ -3,12 +3,15 @@
#include "TPerson.h" #include "TPerson.h"
// Singly linked list of TPerson, used for the guest and employee manifests.
// Owns all its Node objects and frees them in the destructor.
// Supports append, prepend, insert, remove, indexed access, and merge-sort.
class TLinkedList { class TLinkedList {
private: private:
struct Node { struct Node {
TPerson person; TPerson person; // stored by value
Node* next; Node* next;
explicit Node(const TPerson& p) : person(p), next(nullptr) {} explicit Node(const TPerson& p) : person(p), next(nullptr) {}

View File

@@ -9,7 +9,9 @@ enum ENumStatus {
EMPLOYEE EMPLOYEE
}; };
// Represents one person on the cruise ship.
// - 'status' tells us if they're a GUEST or EMPLOYEE
// - 'cabinSize' is random in [1, 4] and used for cabin grouping
struct TPerson { struct TPerson {
std::string firstName; std::string firstName;
std::string lastName; std::string lastName;
@@ -20,6 +22,8 @@ struct TPerson {
TPerson(std::string , std::string , ENumStatus); TPerson(std::string , std::string , ENumStatus);
~TPerson() = default; ~TPerson() = default;
// Comparison for alphabetical sorting:
// primary key: lastName, secondary key: firstName.
bool operator<(const TPerson& other) const bool operator<(const TPerson& other) const
{ {
if (lastName < other.lastName) return true; if (lastName < other.lastName) return true;

View File

@@ -10,8 +10,13 @@ enum EnumActionType {
DELETE DELETE
}; };
// Simple fixed-size stack used for undo/redo.
// Stores actions describing line insert/delete operations.
class TStack { class TStack {
private: private:
// Describes a single text-edit action.
// 'action' indicates INSERT or DELETE,
// 'text' stores the affected line, and 'index' is the line position.
struct TAction { struct TAction {
EnumActionType action; EnumActionType action;
std::string text; std::string text;
@@ -24,9 +29,8 @@ private:
public: public:
TStack() = default; TStack() = default;
~TStack() = default; ~TStack() = default;
void Push(const TAction& action); // Adds a new action to the top of the stack.
void Push(const TAction& action); TAction Pop(); // Removes and returns the most recent action.
TAction Pop();
[[nodiscard]] TAction Peek() const; [[nodiscard]] TAction Peek() const;
[[nodiscard]] bool IsEmpty() const; [[nodiscard]] bool IsEmpty() const;
void Clear(); void Clear();

View File

@@ -5,7 +5,9 @@
#include "TDoublyLinkedList.h" #include "TDoublyLinkedList.h"
// Circular array-based queue implementation.
// Used in Cat 1 to store print jobs (each job is a full document snapshot).
// Demonstrates FIFO behavior through enqueue/dequeue operations.
class TTreeQueue { class TTreeQueue {
private: private:
std::string queue[MAX_SIZE]; std::string queue[MAX_SIZE];
@@ -17,8 +19,8 @@ public:
TTreeQueue() = default; TTreeQueue() = default;
~TTreeQueue() = default; ~TTreeQueue() = default;
void Enqueue(const std::string& text); void Enqueue(const std::string& text); // Adds a new job at the tail of the queue.
std::string Dequeue(); std::string Dequeue(); // Removes and returns the next job in FIFO order.
[[nodiscard]] int GetTail() const; [[nodiscard]] int GetTail() const;
[[nodiscard]] std::string Peek() const; [[nodiscard]] std::string Peek() const;
[[nodiscard]] bool IsEmpty() const; [[nodiscard]] bool IsEmpty() const;

View File

@@ -5,11 +5,11 @@
#include <ctime> #include <ctime>
#include <iostream> #include <iostream>
#include <limits> #include <limits>
#include <numbers>
// Displays the main menu and reads user choice.
int Utils::Choice() int Utils::Choice()
{ {
std::cout << "========\n1. Add line\n2. Remove line\n3. Print current document\n4. Print queue\n5. Undo\n6. Redo\n0. Exit" std::cout << "========\n1. Add line\n2. Remove line\n3. View current1 document\n4. Print queue\n5. Process print job\n6. Undo\n7. Redo\n0. Exit"
"\n\nChoice: "; "\n\nChoice: ";
int choice; int choice;
std::cin >> choice; std::cin >> choice;
@@ -17,6 +17,9 @@ int Utils::Choice()
return choice; return choice;
} }
// Inserts a new line into the document.
// Records the action into the undo stack.
// 'index' determines insert location; defaults to end of document.
int Utils::Insert(TDoublyLinkedList &document, TStack &undoStack, TStack &redoStack, int index) int Utils::Insert(TDoublyLinkedList &document, TStack &undoStack, TStack &redoStack, int index)
{ {
for (int i = 0; i < document.GetSize(); i++) { for (int i = 0; i < document.GetSize(); i++) {
@@ -58,6 +61,8 @@ void Utils::PrintList(const TDoublyLinkedList &document)
std::cout << "\n\n"; std::cout << "\n\n";
} }
// Removes a line chosen by the user.
// Action is pushed to undo stack for reversibility.
int Utils::RemoveLine(TDoublyLinkedList &document, TStack &undoStack, TStack &redoStack, int index) int Utils::RemoveLine(TDoublyLinkedList &document, TStack &undoStack, TStack &redoStack, int index)
{ {
std::cout << "Enter the number of the line you want to remove" <<std::endl; std::cout << "Enter the number of the line you want to remove" <<std::endl;
@@ -90,6 +95,9 @@ int Utils::RandomInt(const int min, const int max)
return min + rand() % (max - min + 1); // <---- Limited randomness, but again return min + rand() % (max - min + 1); // <---- Limited randomness, but again
} // sufficient for this use case } // sufficient for this use case
// Comparison used for cabin grouping (QuickSort):
// 1) cabinSize ascending
// 2) lastName alphabetical
bool Utils::CompareLastnames(const TPerson *a, const TPerson *b) bool Utils::CompareLastnames(const TPerson *a, const TPerson *b)
{ {
if (a->cabinSize < b->cabinSize) if (a->cabinSize < b->cabinSize)
@@ -117,10 +125,10 @@ int Utils::Partition(TPerson **arr, const int startIndex, const int endIndex)
return i + 1; return i + 1;
} }
/// Time complexity **on average** is O(n log n) but worst case it O(n^2) // QuickSort on an array of TPerson* using CompareLastnames:
/// depending on where in the range the pivot lands -- If pivot is at either extreme // - Average time: O(n log n)
/// the algorithm has to search through the entire list for every value it sorts -- n^2 // - Worst case: O(n^2) if pivot choices are bad
/// However it does sort in-place, meaning no extra memory is needed // - Sorts in-place (no extra arrays)
void Utils::QuickSort(TPerson** arr, const int low, const int high) void Utils::QuickSort(TPerson** arr, const int low, const int high)
{ {
if (low < high) { if (low < high) {
@@ -130,8 +138,8 @@ void Utils::QuickSort(TPerson** arr, const int low, const int high)
} }
} }
/// Time complexity of the binary search is O(log n) // Binary search on an alphabetically sorted array of TPerson* (by lastName, then firstName).
/// However the included fallback search is O(n) // Primary search key: surname. If no surname match is found, falls back to linear scan on firstName.
int Utils::BinarySearch(TPerson** arr, int p1, int p2, const std::string &target) int Utils::BinarySearch(TPerson** arr, int p1, int p2, const std::string &target)
{ {
const int origStart = p1; const int origStart = p1;
@@ -153,9 +161,7 @@ int Utils::BinarySearch(TPerson** arr, int p1, int p2, const std::string &target
p2 = newP - 1; p2 = newP - 1;
} }
/// Extra to search for firstname in the event that no matches were found // Fallback linear scan for first names if no last name match
/// Disregard this section if you're purely looking at the
/// binary search understanding and implementation
for (int i = origStart; i <= origEnd; i++) { for (int i = origStart; i <= origEnd; i++) {
if (arr[i]->firstName == target) if (arr[i]->firstName == target)
return i; return i;

View File

@@ -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

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 4.0)
project(SimpleSearch)
set(CMAKE_CXX_STANDARD 20)
add_executable(SimpleSearch main.cpp
EBankAccountType.h
TBankAccount.cpp
TBankAccount.h
TLinkedList.h
SearchSummary.h
FCompareAccount.h
)

View File

@@ -0,0 +1,25 @@
#ifndef SIMPLESEARCH_EBANKACCOUNTTYPE_H
#define SIMPLESEARCH_EBANKACCOUNTTYPE_H
enum class EBankAccountType {
Checking,
Savings,
Credit,
Pension,
Loan
};
inline const char* ToString(EBankAccountType t)
{
switch (t) {
case EBankAccountType::Checking: return "Checking";
case EBankAccountType::Savings: return "Savings";
case EBankAccountType::Credit: return "Credit";
case EBankAccountType::Pension: return "Pension";
case EBankAccountType::Loan: return "Loan";
default: return "Unknown";
}
}
#endif //SIMPLESEARCH_EBANKACCOUNTTYPE_H

View File

@@ -0,0 +1,8 @@
#ifndef SIMPLESEARCH_FCOMPAREACCOUNT_H
#define SIMPLESEARCH_FCOMPAREACCOUNT_H
#include "TBankAccount.h"
using FCompareAccount = bool (*)(TBankAccount* account, void* searchKey);
#endif //SIMPLESEARCH_FCOMPAREACCOUNT_H

5401
SimpleSearch/Random_Name.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
#ifndef SIMPLESEARCH_SEARCHSUMMARY_H
#define SIMPLESEARCH_SEARCHSUMMARY_H
struct SearchSummary {
long long comparisons = 0;
double timeSpentMs = 0;
};
#endif //SIMPLESEARCH_SEARCHSUMMARY_H

View File

@@ -0,0 +1,69 @@
#include "TBankAccount.h"
#include <random>
#include <thread>
static std::mt19937& GetRng()
{
static thread_local std::mt19937 rng
{
std::random_device{}()
};
return rng;
}
double TBankAccount::RandomInRange(double min, double max)
{
std::uniform_real_distribution<double> dist(min, max);
return dist(GetRng());
}
double TBankAccount::RandomBalanceFor(EBankAccountType t)
{
switch (t)
{
case EBankAccountType::Checking:
case EBankAccountType::Savings:
case EBankAccountType::Pension: return RandomInRange(0.0, 1000.0);
case EBankAccountType::Loan: return RandomInRange(-50000.0, -25000.0);
case EBankAccountType::Credit: return RandomInRange(-1000.0, 0.0);
default: return 0.0;
}
}
TBankAccount::TBankAccount(const std::string &accNo, EBankAccountType type, const std::string &firstName
, const std::string &lastName, time_t createdAt) : accountNumber(accNo), accountType(type), ownerFirstName(firstName)
, ownerLastName(lastName), creationTimestamp(createdAt), balance(RandomBalanceFor(type))
{
}
const std::string &TBankAccount::GetAccountNumber() const
{
return accountNumber;
}
EBankAccountType TBankAccount::GetAccountType() const
{
return accountType;
}
const std::string &TBankAccount::GetOwnerFirstName() const
{
return ownerFirstName;
}
const std::string &TBankAccount::GetOwnerLastName() const
{
return ownerLastName;
}
time_t TBankAccount::GetCreationTimestamp() const
{
return creationTimestamp;
}
double TBankAccount::GetBalance() const
{
return balance;
}

View File

@@ -0,0 +1,37 @@
#ifndef SIMPLESEARCH_TBANKACCOUNT_H
#define SIMPLESEARCH_TBANKACCOUNT_H
#include <string>
#include <ctime>
#include "EBankAccountType.h"
class TBankAccount {
private:
std::string accountNumber;
EBankAccountType accountType;
std::string ownerFirstName;
std::string ownerLastName;
time_t creationTimestamp;
double balance;
double RandomInRange(double min, double max);
double RandomBalanceFor(EBankAccountType t);
public:
TBankAccount(const std::string& accNo, EBankAccountType type, const std::string& firstName, const std::string& lastName, time_t createdAt);
~TBankAccount() = default;
[[nodiscard]] const std::string& GetAccountNumber() const;
[[nodiscard]] EBankAccountType GetAccountType() const;
[[nodiscard]] const std::string& GetOwnerFirstName() const;
[[nodiscard]] const std::string& GetOwnerLastName() const;
[[nodiscard]] time_t GetCreationTimestamp() const;
[[nodiscard]] double GetBalance() const;
};
#endif //SIMPLESEARCH_TBANKACCOUNT_H

157
SimpleSearch/TLinkedList.h Normal file
View File

@@ -0,0 +1,157 @@
#ifndef SIMPLESEARCH_TLINKEDLIST_H
#define SIMPLESEARCH_TLINKEDLIST_H
#include "TBankAccount.h"
#include "FCompareAccount.h"
#include "SearchSummary.h"
// Using singly linked list since we gain very little in terms of functionality when going for doubly or circular
// and singly is a lot leaner when it comes to space complexity
template <typename T>
struct Node {
T value;
Node* next = nullptr;
explicit Node(T v) : value(v), next(nullptr) {}
};
template <typename T>
class TLinkedList {
private:
Node<T>* head = nullptr;
Node<T>* tail = nullptr;
bool ownsData = false;
std::size_t listSize = 0;
public:
explicit TLinkedList(bool owns) : ownsData(owns) {}
~TLinkedList()
{
Node<T>* current = head;
while (current) {
Node<T>* next = current->next;
if (ownsData)
delete current->value;
delete current;
current = next;
}
}
[[nodiscard]] size_t Size() const;
[[nodiscard]] bool Empty() const;
void PushBack(T v);
template <typename Pred>
T FindIf(Pred p) const
{
for (auto* n = head; n; n = n->next)
if (p(n->value))
return n->value;
return nullptr;
}
template <typename Pred>
bool RemoveIf(Pred p)
{
Node<T>* prev = nullptr;
Node<T>* current = head;
while (current) {
if (p(current->value)) {
if (prev)
prev->next = current->next;
else
head = current->next;
if (ownsData)
delete current->value;
delete current;
--listSize;
return true;
}
prev = current;
current = current->next;
}
return false;
}
TBankAccount* Find(FCompareAccount onCompare, void* searchKey, SearchSummary* summary) const;
TLinkedList<TBankAccount*>* Every(FCompareAccount onCompare, void* searchKey, SearchSummary* summary) const;
};
#endif //SIMPLESEARCH_TLINKEDLIST_H
#include <chrono>
template<typename T>
TBankAccount *TLinkedList<T>::Find(FCompareAccount onCompare, void *searchKey, SearchSummary *summary) const
{
using clock = std::chrono::steady_clock;
auto start = clock::now();
if (!onCompare)
return nullptr;
for (auto* n = head; n; n = n->next) {
++summary->comparisons;
if (onCompare(n->value, searchKey)) {
auto elapsed = clock::now() - start;
summary->timeSpentMs = std::chrono::duration<double, std::milli>(elapsed).count();
return n->value;
}
}
auto elapsed = clock::now() - start;
summary->timeSpentMs = std::chrono::duration<double, std::milli>(elapsed).count();
return nullptr;
}
template<typename T>
TLinkedList<TBankAccount *> *TLinkedList<T>::Every(FCompareAccount onCompare, void *searchKey, SearchSummary *summary) const
{
using clock = std::chrono::steady_clock;
auto start = clock::now();
auto* result = new TLinkedList<TBankAccount*>(false);
if (!onCompare) {
auto elapsed = clock::now() - start;
summary->timeSpentMs = std::chrono::duration<double, std::milli>(elapsed).count();
return result;
}
for (auto* n = head; n; n = n->next) {
++summary->comparisons;
if (onCompare(n->value, searchKey)) {
result->PushBack(n->value);
}
}
auto elapsed = clock::now() - start;
summary->timeSpentMs = std::chrono::duration<double, std::milli>(elapsed).count();
return result;
}
template<typename T>
size_t TLinkedList<T>::Size() const
{
return listSize;
}
template<typename T>
bool TLinkedList<T>::Empty() const
{
return listSize == 0;
}
template<typename T>
void TLinkedList<T>::PushBack(T v)
{
auto* n = new Node<T>(v);
if (!tail)
head = tail = n;
else {
tail->next = n;
tail = n;
}
listSize++;
}

256
SimpleSearch/main.cpp Normal file
View File

@@ -0,0 +1,256 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <chrono>
#include <iomanip>
#include <ctime>
#include "TLinkedList.h"
#include "TBankAccount.h"
#include "EBankAccountType.h"
#include "SearchSummary.h"
// -------------------- Helpers: random generators --------------------
static int RandInt(int lo, int hi) { // inclusive
return lo + (std::rand() % (hi - lo + 1));
}
static std::string RandomAccountNumber()
{
// super-simple: NO + 11 random digits
std::string s = "NO";
for (int i = 0; i < 11; ++i) s += char('0' + RandInt(0, 9));
return s;
}
// Any moment in 2024
static time_t RandomTimestamp2024()
{
std::tm tm{}; // zero-init
tm.tm_year = 124; // 2024 - 1900
tm.tm_mon = RandInt(0, 11); // 0..11
tm.tm_mday = RandInt(1, 28); // safe day-of-month (avoid month length edge cases)
tm.tm_hour = RandInt(0, 23);
tm.tm_min = RandInt(0, 59);
tm.tm_sec = RandInt(0, 59);
tm.tm_isdst = -1; // let C library figure it out
return std::mktime(&tm);
}
static EBankAccountType RandomAccountType()
{
return static_cast<EBankAccountType>(RandInt(0, 4)); // 5 enum values
}
// -------------------- Standalone search functions (Part 3) --------------------
TBankAccount* FindAccountByNumber(
TBankAccount** accountArray, int arraySize,
const std::string& accountNumber, SearchSummary& summary)
{
using clock = std::chrono::steady_clock;
auto t0 = clock::now();
for (int i = 0; i < arraySize; ++i) {
++summary.comparisons;
if (accountArray[i]->GetAccountNumber() == accountNumber) {
auto dt = clock::now() - t0;
summary.timeSpentMs = std::chrono::duration<double, std::milli>(dt).count();
return accountArray[i];
}
}
auto dt = clock::now() - t0;
summary.timeSpentMs = std::chrono::duration<double, std::milli>(dt).count();
return nullptr;
}
void PrintEveryAccountInDateRange(
TBankAccount** accountArray, int arraySize,
time_t fromDate, time_t toDate, SearchSummary& summary)
{
using clock = std::chrono::steady_clock;
auto t0 = clock::now();
for (int i = 0; i < arraySize; ++i) {
++summary.comparisons;
time_t created = accountArray[i]->GetCreationTimestamp();
if (created >= fromDate && created <= toDate) {
std::tm* t = std::localtime(&created);
std::cout << " " << accountArray[i]->GetAccountNumber()
<< " | " << accountArray[i]->GetOwnerFirstName()
<< ' ' << accountArray[i]->GetOwnerLastName()
<< " | created " << std::put_time(t, "%Y-%m-%d %H:%M:%S")
<< " | type " << ToString(accountArray[i]->GetAccountType())
<< " | balance " << accountArray[i]->GetBalance()
<< std::endl;
}
}
auto dt = clock::now() - t0;
summary.timeSpentMs = std::chrono::duration<double, std::milli>(dt).count();
}
// -------------------- Name reader (names given) --------------------
typedef bool (*FNameRead)(const std::string& firstName, const std::string& lastName);
// Globals only to satisfy the plain-C callback style used here
static TLinkedList<TBankAccount*>* gList = nullptr;
static std::vector<TBankAccount*>* gVec = nullptr;
static bool OnNameRead(const std::string& firstName, const std::string& lastName)
{
// Create between 5 and 10 accounts per name
int count = RandInt(5, 10);
for (int i = 0; i < count; ++i) {
const auto accNo = RandomAccountNumber();
const auto accType = RandomAccountType();
const auto created = RandomTimestamp2024();
// requires the 5-arg constructor overload
auto* acc = new TBankAccount(accNo, accType, firstName, lastName, created);
gList->PushBack(acc);
gVec->push_back(acc);
}
return true; // return false if you ever want to stop early
}
static void readNamesFromFile(const std::string& filename, FNameRead cb)
{
if (filename.empty()) return;
std::ifstream file(filename);
if (!file.is_open()) {
std::cerr << "Error opening file: " << filename << '\n';
return;
}
std::string line, first, last;
while (std::getline(file, line)) {
std::istringstream iss(line);
if (iss >> first >> last) {
if (cb && !cb(first, last)) break;
}
}
file.close();
}
// -------------------- Integrated callbacks for TLinkedList::Every --------------------
static bool MatchMonthJune2024(TBankAccount* acc, void* /*key*/)
{
time_t ts = acc->GetCreationTimestamp();
std::tm* t = std::localtime(&ts);
return (t->tm_year == 124 && t->tm_mon == 5); // June (0-based month)
}
int main()
{
std::srand(static_cast<unsigned>(std::time(nullptr)));
// 1) Build primary list + a vector mirror (will become the dynamic array)
TLinkedList<TBankAccount*> list(/*ownsData=*/true);
std::vector<TBankAccount*> mirror;
mirror.reserve(55000); // 5400 names × up to 10 accounts ≈ 54k (avoid re-alloc)
gList = &list;
gVec = &mirror;
// Read file and populate (file in same directory as executable)
readNamesFromFile("Random_Name.txt", OnNameRead);
// Ensure we met the >= 5000 requirement
if (mirror.size() < 5000) {
std::cerr << "Warning: only " << mirror.size()
<< " accounts created; expected >= 5000.\n";
}
// Create the dynamic array copy (Part 3 requirement)
const int N = static_cast<int>(mirror.size());
auto** accountArray = new TBankAccount*[N];
for (int i = 0; i < N; ++i) accountArray[i] = mirror[i];
std::cout << "Populated " << list.Size() << " accounts.\n\n";
// 2) Demonstrations & Analysis (Part 4.12a)
// a) Find First: search for one near the end and one that does not exist
{
std::cout << "[Find() near the end]\n";
SearchSummary s{};
// Pick a target near the end (if we have enough accounts)
const std::string target = (N >= 3) ? accountArray[N - 3]->GetAccountNumber()
: accountArray[N - 1]->GetAccountNumber();
TBankAccount* found = list.Find(
/*onCompare:*/ [](TBankAccount* a, void* key){
return a->GetAccountNumber() == *static_cast<std::string*>(key);
},
/*key:*/ const_cast<std::string*>(&target),
/*summary:*/ &/*summary:*/ s);
std::cout << " Target: " << target << " | Comparisons: " << s.comparisons
<< " | Time: " << s.timeSpentMs << " ms\n";
std::cout << "[Find() non-existent]\n";
SearchSummary s2{};
std::string missing = "NO00000000000"; // extremely unlikely to exist
TBankAccount* notFound = list.Find(
[](TBankAccount* a, void* key){
return a->GetAccountNumber() == *static_cast<std::string*>(key);
},
&missing, &s2);
std::cout << " Target: " << missing << " | Found? " << (notFound ? "Yes" : "No")
<< " | Comparisons: " << s2.comparisons
<< " | Time: " << s2.timeSpentMs << " ms\n\n";
}
// b) Find All (Integrated): Every() for accounts created in June 2024
{
std::cout << "[Every() - accounts created in June 2024]\n";
SearchSummary s{};
TLinkedList<TBankAccount*>* june = list.Every(MatchMonthJune2024, nullptr, &s);
std::cout << " Matches: " << june->Size()
<< " | Comparisons: " << s.comparisons
<< " | Time: " << s.timeSpentMs << " ms\n";
// You could iterate and print a few:
// (Avoid printing thousands to keep output sane.)
delete june; // ownsData=false inside Every()
std::cout << '\n';
}
// c) Find All (Standalone): first quarter of 2024
{
std::cout << "[Standalone search -- accounts created in Q1 2024]\n";
// Q1 range: 2024-01-01 00:00:00 to 2024-03-31 23:59:59
std::tm from{}; from.tm_year = 124; from.tm_mon = 0; from.tm_mday = 1;
std::tm to {}; to .tm_year = 124; to .tm_mon = 2; to .tm_mday = 31; to.tm_hour = 23; to.tm_min = 59; to.tm_sec = 59;
time_t tFrom = std::mktime(&from);
time_t tTo = std::mktime(&to);
SearchSummary s{};
PrintEveryAccountInDateRange(accountArray, N, tFrom, tTo, s);
std::cout << " Comparisons: " << s.comparisons
<< " | Time: " << s.timeSpentMs << " ms\n\n";
}
// Cleanup dynamic array (the list owns the account objects)
delete[] accountArray;
std::cout << "Done.\n";
return 0;
}
// --------------Analysis---------------
// The Find() function iterates sequentially through the linked list to compare the data field of each node
// until a match is found, or it gets a nullptr as return. This means that if the matching node is towards the very end
// of the list, then the complexity would be near-as-makes-no-difference O(n). Therefore the other edge case is that the
// matching node is found at the very start of the list, making the time complexity essentially O(1).
// Since we have no way to arbitrarily reorganise the list according to the search query, we have to account for the
// worst case time complexity, which in the case of linked lists is O(n)
// The Every() function displays polymorphic flexibility through callbacks - meaning one function can
// handle many search conditions. PrintEveryAccountInDateRange() is more specialised, which also makes it more readable
// in this case. This also means that it's search functionality is not as versatile as Every(), with the specialisation
// of the PrintEveryAcc....() function being tied to a single search criteria.

8
TheAlgorithmicOrganizer/.idea/.gitignore generated vendored Normal file
View File

@@ -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

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

343
TheAlgorithmicOrganizer/.idea/editor.xml generated Normal file
View File

@@ -0,0 +1,343 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="BackendCodeEditorSettings">
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CDeclarationWithImplicitIntType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConstevalIfIsAlwaysConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractClassWithoutSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractVirtualFunctionCallInCtor/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAccessSpecifierWithNoDeclarations/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAwaiterTypeIsNotClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBooleanIncrementExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatBadCode/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatLegacyCode/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatMixedArgs/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooFewArgs/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooManyArgs/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCVQualifierCanNotBeAppliedToReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassIsIncomplete/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeedsConstructorBecauseOfUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCompileTimeConstantCanBeReplacedWithBooleanConstant/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConceptNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConditionalExpressionCanBeSimplified/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstValueFunctionReturnType/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCoroutineCallResolveError/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAArrayIndexOutOfBounds/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantConditions/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantFunctionResult/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantParameter/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFADeletedPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAEndlessLoop/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInfiniteRecursion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInvalidatedMemory/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesScope/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALoopConditionNotUpdated/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAMemoryLeak/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANotInitializedField/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANullDereference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFATimeOver/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableCode/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableFunctionCall/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreadVariable/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnusedValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesLocal/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesUncapturedLocal/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationSpecifierWithoutDeclarators/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorDisambiguatedAsFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorUsedBeforeInitialization/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultCaseNotHandledInSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultInitializationWithNoUserConstructor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultIsUsedAsIdentifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultedSpecialMemberFunctionIsImplicitlyDeleted/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeletingVoidPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTemplateWithoutTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTypeWithoutTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedEntity/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedOverridenMethod/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedRegisterStorageClassSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDereferenceOperatorLimitExceeded/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDiscardedPostfixOperatorResult/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenSyntaxError/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUndocumentedParameter/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUnresolvedReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEmptyDeclaration/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersOrder/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersPlacement/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceDoStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceForStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceFunctionDeclarationStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceIfStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceNestedNamespacesStyle/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingDestructorStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingFunctionStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceTypeAliasCodeStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceWhileStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityAssignedButNoRead/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityUsedOnlyInUnevaluatedContext/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnumeratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEqualOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEvaluationFailure/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExplicitSpecializationInNonNamespaceScope/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExpressionWithoutSideEffects/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalFunctionInFinalClass/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalNonOverridingVirtualFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForLoopCanBeReplacedWithWhile/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForwardEnumDeclarationWithoutUnderlyingType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionDoesntReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionResultShouldBeUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionalStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHeaderHasBeenAlreadyIncluded/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHiddenFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHidingFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIdenticalOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIfCanBeReplacedByConstexprIf/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppImplicitDefaultConstructorNotAvailable/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompatiblePointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompleteSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInconsistentNaming/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIntegralToPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInvalidLineContinuation/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppJoinDeclarationAndAssignment/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLambdaCaptureNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberInitializersOrder/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMismatchedClassTags/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingIncludeGuard/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingKeywordThrow/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppModulePartitionWithSeveralPartitionUnits/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtAddressOfClassRValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtBindingRValueToLvalueReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtCopyElisionInCopyInitDeclarator/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtDoubleUserConversionInCopyInit/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtNotInitializedStaticConstLocalVar/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtReinterpretCastFromNullptr/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterLiteral/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterWideLiteral/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMustBePublicVirtualToImplementInterface/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMutableSpecifierOnReferenceMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNoDiscardExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNodiscardFunctionWithoutReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExceptionSafeResourceAcquisition/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConversionOperator/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConvertingConstructor/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineFunctionDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineVariableDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNotAllPathsReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppObjectMemberMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppOutParameterMustBeWritten/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConstPtrOrRef/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNamesMismatch/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPassValueParameterByConstReference/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerConversionDropsQualifiers/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerToIntegralConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPolymorphicClassWithNonVirtualPublicDestructor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyErroneousEmptyStatements/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUnintendedObjectSlicing/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderIsNotIncluded/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderNotFound/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfBadFormat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfExtraArg/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfMissedArg/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfRiskyFormat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrivateSpecialMemberFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRangeBasedForIncompatibleReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedefinitionOfDefaultArgumentInOverrideFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBooleanExpressionArgument/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantCastExpression/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantComplexityInComparison/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConditionalExpression/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConstSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantControlFlowJump/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantDereferencingAndTakingAddress/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElaboratedTypeSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeyword/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeywordInsideCompoundStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyDeclaration/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantExportKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantFwdClassOrEnumSpecifier/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantInlineSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantLambdaParameterList/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantMemberInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantNamespaceDefinition/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantParentheses/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifierADL/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnMemberAllocationFunction/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnThreadLocalLocalVariable/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateArguments/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantVoidArgumentList/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantZeroInitializerInAggregateInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReinterpretCastFromVoidPtr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRemoveRedundantBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceMemsetWithZeroInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceTieWithStructuredBinding/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReturnNoValueInNonVoidFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSmartPointerVsMakeFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSomeObjectMembersMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSpecialFunctionWithoutNoexceptSpecification/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticAssertFailure/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticDataMemberInUnnamedStruct/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticSpecifierOnAnonymousNamespaceMember/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStringLiteralToCharPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTabsAreDisallowed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateArgumentsCanBeDeduced/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterShadowing/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppThrowExpressionCanBeReplacedWithRethrow/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScope/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScopeInitStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTypeAliasNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedDependentBaseClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedNonStaticDataMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnionMemberOfReferenceType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaEndRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnamedNamespaceInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnecessaryWhitespace/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnsignedZeroComparison/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnusedIncludeDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAlgorithmWithCount/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAssociativeContains/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAuto/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAutoForNumeric/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseElementsView/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseEraseAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseFamiliarTemplateSyntaxForGenericLambdas/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseRangeAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStdSize/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStructuredBinding/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseTypeTraitAlias/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUserDefinedLiteralSuffixDoesNotStartWithUnderscore/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUsingResultOfAssignmentAsCondition/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVariableCanBeMadeConstexpr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionCallInsideCtor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionInFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVolatileParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWarningDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongIncludesOrder/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongSlashesInIncludeDirective/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroConstantCanBeReplacedWithNullptr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroValuedExpressionUsedAsNullPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
</component>
</project>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MaterialThemeProjectNewConfig">
<option name="metadata">
<MTProjectMetadataState>
<option name="migrated" value="true" />
<option name="pristineConfig" value="false" />
<option name="userId" value="54f3be3a:19a5567208e:-7ffe" />
</MTProjectMetadataState>
</option>
</component>
</project>

7
TheAlgorithmicOrganizer/.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakePythonSetting">
<option name="pythonIntegrationState" value="YES" />
</component>
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/TheAlgoeithmicOrganizer.iml" filepath="$PROJECT_DIR$/.idea/TheAlgoeithmicOrganizer.iml" />
</modules>
</component>
</project>

6
TheAlgorithmicOrganizer/.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

View File

@@ -0,0 +1,108 @@
#include "BankAccount.h"
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdlib> // For rand()
#include <random> // For better random number generation
#include <ctime>
#include <cstring> // For memset
#include <cmath> // For floor
#include <chrono> // For time manipulation
#include <locale> // For locale settings
#include <codecvt> // For codecvt_utf8
#include <stdexcept> // For std::invalid_argument
#include <string>
TBankAccount::TBankAccount(EBankAccountType accType, std::string firstName, std::string lastName)
: accountType(accType), ownerFirstName(firstName), ownerLastName(lastName)
{
// Random genration of account number: XXXX.XX.XXXXX
accountNumber = toString(rand() % 9000 + 1000) + "." + toString(rand() % 90 + 10) + "." + toString(rand() % 90000 + 10000);
balance = 0.0f;
//Random generation of creation timestamp, date is any date and time in 2024
int month = rand() % 12 + 1;
int day = rand() % 28 + 1; // To avoid complexity of different month lengths
int hour = rand() % 24;
int minute = rand() % 60;
// Calculate creation timestamp in seconds from 2024-01-01 00:00:00
std:tm tm = {};
tm.tm_year = 2024 - 1900; // Year since 1900
tm.tm_mon = rand() % 12; // Month [0-11]
tm.tm_mday = rand() % 28 + 1; // Day of the month [1-28] to avoid month length issues
tm.tm_hour = rand() % 24; // Hour [0-23]
tm.tm_min = rand() % 60; // Minute [0-59]
tm.tm_sec = 0; // Second [0-59]
creationTimestamp = _mkgmtime(&tm); // Use _mkgmtime for UTC
if (accType == Checking || accType == Saving || accType == Pension)
balance = static_cast<double>(rand() % 1001); // 0 to 1000
else if (accType == Loan)
balance = static_cast<double>(-(rand() % 25001 + 25000)); // -50000 to -25000
else if (accType == Credit)
balance = static_cast<double>(-(rand() % 1001)); // -1000 to 0
}
TBankAccount::~TBankAccount()
{
// Destructor logic if needed
}
std::string TBankAccount::getAccountNumber() const {
return accountNumber;
}
EBankAccountType TBankAccount::getAccountType() const {
return accountType;
}
time_t TBankAccount::getCreationTimestamp() const {
return creationTimestamp;
}
double TBankAccount::getBalance() const {
return balance;
}
void TBankAccount::deposit(double aAmount) {
if (aAmount > 0) balance += aAmount;
}
void TBankAccount::withdraw(double aAmount) {
if (aAmount > 0 && aAmount <= balance) balance -= aAmount;
}
std::string TBankAccount::getAccountTypeString() const
{
switch (accountType)
{
case Checking: return "Checking";
case Saving: return "Saving";
case Credit: return "Credit";
case Pension: return "Pension";
case Loan: return "Loan";
default: return "Unknown";
}
}
//
std::string TBankAccount::getCreationTimeString() const
{
char buffer[26];
ctime_s(buffer, sizeof(buffer), &creationTimestamp);
std::string timeString(buffer);
if (!timeString.empty() && timeString.back() == '\n') {
timeString.pop_back(); // Remove the trailing newline character
}
return timeString;
}
void TBankAccount::printAccountInfo() const
{
std::cout << "Account Number: " << accountNumber << ", Type: " << getAccountTypeString()
<< ", Owner: " << ownerFirstName << " " << ownerLastName
<< ", Balance: " << balance
<< ", Created: " << getCreationTimeString()
<< std::endl;
}

View File

@@ -0,0 +1,52 @@
#pragma once
#ifndef BANKACCOUNT_H
#define BANKACCOUNT_H
#include <string> // For std::string
#include <ctime> // For time_t
#include <cstdlib> // For rand()
#include <iomanip> // For std::setfill and std::setw
#include <sstream> // For std::ostringstream
#include <iostream> // For std::cout
// Helper function to convert value to string
template <typename T>
std::string toString(T value)
{
std::ostringstream oss;
oss << value;
return oss.str();
}
enum EBankAccountType { Checking, Saving, Credit, Pension, Loan };
class TBankAccount {
private:
std::string accountNumber;
EBankAccountType accountType;
time_t creationTimestamp;
double balance;
public:
std::string ownerFirstName;
std::string ownerLastName;
//TBankAccount() {} // Don't use default constructor
TBankAccount(EBankAccountType, std::string, std::string);
~TBankAccount();
std::string getAccountNumber() const;
std::string getCreationTimeString() const;
time_t getCreationTimestamp() const;
double getBalance() const;
void deposit(double);
void withdraw(double);
EBankAccountType getAccountType() const;
std::string getAccountTypeString() const;
void printAccountInfo() const;
};
#endif // BANKACCOUNT_H

View File

@@ -0,0 +1,130 @@
#include "BankAccountList.h"
TLinkedList::TLinkedList(bool aOwnsData) : head(nullptr), ownsData(aOwnsData), size(0) {
head = new TLinkedListNode(nullptr); // Dummy head node
}
TLinkedList::~TLinkedList()
{
while (head->next != nullptr)
{
TLinkedListNode* temp = head->next;
head->next = temp->next;
if (ownsData) delete temp->data; // Delete the TBankAccount object
delete temp; // Delete the node
}
delete head;
}
int TLinkedList::getSize() const { return size; }
void TLinkedList::Add(TBankAccount* aData)
{
TLinkedListNode* newNode = new TLinkedListNode(aData);
newNode->next = head->next;
head->next = newNode;
size++;
}
TBankAccount* TLinkedList::Find(FCompareAccount aCompareFunc, void* aSearchKey)
{
TLinkedListNode* current = head->next;
while (current != nullptr)
{
if (aCompareFunc(current->data, aSearchKey))
{
return current->data; // Found
}
current = current->next;
}
return nullptr; // Not found
}
TLinkedList* TLinkedList::Every(FCompareAccount aCompareFunc, void* aSearchKey)
{
TLinkedList* resultList = new TLinkedList(false); // New list does not own data
TLinkedListNode* current = head->next;
while (current != nullptr)
{
if (aCompareFunc(current->data, aSearchKey))
{
resultList->Add(current->data); // Add to result list
}
current = current->next;
}
return resultList; // Return the new list
}
// Loop through all accounts, if aEveryFunc returns false for any, return that account
TBankAccount* TLinkedList::Every(FEveryAccount aEveryFunc) {
TLinkedListNode* current = head->next;
int index = 0;
while (current != nullptr)
{
if (!aEveryFunc(current->data, index++))
{
return current->data; // Return the first account that fails the test
}
current = current->next;
}
return nullptr; // All accounts passed the test
}
TBankAccount** TLinkedList::ToArray()
{
if (size == 0) return nullptr;
TBankAccount** array = new TBankAccount * [size];
TLinkedListNode* current = head->next;
int index = 0;
while (current != nullptr && index < size) // Ensure index < size
{
array[index++] = current->data;
current = current->next;
}
return array;
}
void TLinkedList::forEach(FForEachAccount aFunc)
{
TLinkedListNode* current = head->next;
int index = 0;
while (current != nullptr)
{
aFunc(current->data, index++);
current = current->next;
}
}
TLinkedListNode* TLinkedList::getHead() const { return head; }
void TLinkedList::Append(TBankAccount* account)
{
TLinkedListNode* newNode = new TLinkedListNode(account);
TLinkedListNode* current = head;
while (current->next != nullptr)
{
current = current->next;
}
current->next = newNode;
size++;
}
void TLinkedList::Remove(TBankAccount* account)
{
TLinkedListNode* current = head;
while (current->next != nullptr)
{
if (current->next->data == account)
{
TLinkedListNode* temp = current->next;
current->next = temp->next;
if (ownsData) delete temp->data; // Delete the TBankAccount object
delete temp; // Delete the node
size--;
return; // Exit after removing
}
current = current->next;
}
}

View File

@@ -0,0 +1,51 @@
#pragma once
#ifndef BANKACCOUNTLIST_H
#define BANKACCOUNTLIST_H
#include "BankAccount.h"
#include <string>
#include <functional>
typedef bool (*FCompareAccount)(TBankAccount* account, void* searchKey);
typedef void (*FForEachAccount)(TBankAccount* account, int index);
typedef bool (*FEveryAccount)(TBankAccount*, int);
// Node class for linked list
class TLinkedListNode
{
public:
TBankAccount* data;
TLinkedListNode* next;
TLinkedListNode(TBankAccount* aData) : data(aData), next(nullptr) {}
~TLinkedListNode()
{
// Destructor logic if needed
}
};
// Use dummy head node for simplicity
class TLinkedList
{
private:
TLinkedListNode* head;
bool ownsData;
int size;
public:
TLinkedList(bool);
~TLinkedList();
int getSize() const;
TLinkedListNode* getHead() const;
void Add(TBankAccount*);
TBankAccount* Find(FCompareAccount, void*);
TLinkedList* Every(FCompareAccount, void*);
TBankAccount* Every(FEveryAccount aEveryFunc);
TBankAccount** ToArray();
void forEach(FForEachAccount);
void Append(TBankAccount* account);
void Remove(TBankAccount* account);
};
#endif// BANKACCOUNTLIST_H

View File

@@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 4.0)
project(TheAlgorithmicOrganizer)
set(CMAKE_CXX_STANDARD 20)
add_executable(TheAlgorithmicOrganizer main.cpp
main.h
BankAccount.h
BankAccount.cpp
BankAccountList.cpp
BankAccountList.h
FileReaderUtils.cpp
FileReaderUtils.h
ReadNames.cpp
SharedLib.h
Utils.cpp
Sort.cpp
Sort.h
)

View File

@@ -0,0 +1,30 @@
#include "FileReaderUtils.h"
int GetRecordCount(const std::string& aHeaderLine)
{
size_t recordPos = aHeaderLine.find("records:=");
if (recordPos == std::string::npos)
{
return 0; // No record count found
}
size_t countStart = recordPos + 9; // Length of "records:="
// Find the end bracket ']' or a potential semicolon ';'
size_t countEnd = aHeaderLine.find_first_of("];", countStart);
if (countEnd == std::string::npos)
{
return 0; // Malformed header
}
std::string countStr = aHeaderLine.substr(countStart, countEnd - countStart);
try
{
// stoi = string to integer
return std::stoi(countStr);
}
catch (const std::exception&)
{
return 0; // Malformed number
}
}

View File

@@ -0,0 +1,13 @@
// FileReaderUtils.h
#pragma once
#if !defined(FILEREADERUTILS_H)
#define FILEREADERUTILS_H
#include <string>
/**
* @brief [Internal] Safely parses the "records:=N" part of a header line.
* @param aHeaderLine The line, e.g., "[NODES;records:=11]"
* @return The number of records, or 0 if not found.
*/
int GetRecordCount(const std::string& aHeaderLine);
#endif // FILEREADERUTILS_H

View File

@@ -0,0 +1,55 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include "SharedLib.h"
#include "FileReaderUtils.h"
void readNamesFromFile(const std::string& aFilename, FNameRead aOnNameRead)
{
if (aFilename.empty()) return;
std::ifstream file(aFilename);
if (!file.is_open())
{
std::cerr << "Error: Could not open file " << aFilename << std::endl;
return;
}
std::string line;
int totalCount = 0;
int currentIndex = 0;
bool keepReading = true;
// --- 1. Read the header line ---
if (std::getline(file, line))
{
// Use our shared helper to get the count
totalCount = GetRecordCount(line);
}
// --- 2. Loop through the rest of the file ---
while (keepReading && std::getline(file, line))
{
if (line.empty()) continue;
std::istringstream nameStream(line);
std::string firstName, lastName;
// Parse "FirstName LastName"
if (nameStream >> firstName >> lastName)
{
if (aOnNameRead)
{
// Call the callback with all parameters
if (!aOnNameRead(currentIndex, totalCount, firstName, lastName))
{
keepReading = false;
}
currentIndex++;
}
}
}
file.close();
}

View File

@@ -0,0 +1,106 @@
#pragma once
#ifndef SHARED_LIB_H
#define SHARED_LIB_H
#include <array>
#include <string>
#include "BankAccount.h"
#include "BankAccountList.h"
// Taken from exam project. Added functions, callbacks, structs and classes are at the bottom
/// <summary>
/// Delegate type for processing a name read from a file.
/// </summary>
/// <param name="aIndex">The index of the name (0-based).</param>
/// <param name="aTotalCount">The total number of names.</param>
/// <param name="aFirstName">The first name read from the file.</param>
/// <param name="aLastName">The last name read from the file.</param>
/// <returns>Returns true to continue reading, false to stop.</returns>
typedef bool (*FNameRead)(
const int aIndex,
const int aTotalCount,
const std::string& aFirstName,
const std::string& aLastName
);
/// <summary>
/// Use this function to read names from a specified file and process them using a callback function.
/// </summary>
/// <function>readNamesFromFile</function>
/// <description>Reads names from a specified file and invokes a callback for each name read.</description>
/// <param name="aFilename">The path to the file containing names.</param>
/// <param name="aOnNameRead">A callback function that is called for each name read. It takes two parameters: firstName and lastName. If the callback returns false, the reading process stops.</param>
/// <param name="firstName">The first name read from the file.</param>
/// <param name="lastName">The last name read from the file.</param>
/// <returns>None.</returns>
void readNamesFromFile(const std::string& aFilename, FNameRead aOnNameRead);
/// <summary>
/// Delegate type for processing a node read from the file.
/// </summary>
/// <description>Function pointer type for a callback that processes nodes read from a file.</description>
/// <param name="aIndex">The index of the node (0-based).</param>
/// <param name="aTotalCount">The total number of nodes.</param>
/// <param name="aNode">The node std::string.</param>
/// <returns>Returns true to continue reading, false to stop.</returns>
typedef bool (*FNodeRead)(const int aIndex, const int aTotalCount, const std::string& aNode);
/// <summary>
/// Delegate type for processing an edge read from the file.
/// </summary>
/// <description>Function pointer type for a callback that processes edges read from a file.</description>
/// <param name="aIndex">The index of the edge (0-based).</param>
/// <param name="aTotalCount">The total number of edges.</param>
/// <param name="aFromNode">The from node std::string.</param>
/// <param name="aToNode">The to node std::string.</param>
/// <param name="aWeight">The weight of the edge.</param>
/// <returns>Returns true to continue reading, false to stop.</returns>
typedef bool (*FEdgeRead)(const int aIndex, const int aTotalCount, const std::string& aFromNode, const std::string& aToNode, float aWeight);
/// </summary>
/// Use this function to read a graph from a specified file and process its nodes and edges using callback functions.
/// </summary>
/// <function>readGraphFromFile</function>
/// <description>
/// Reads a graph from a specified file and invokes callbacks for each node and edge read.
/// All nodes are read first, followed by edges.
/// </description>
/// <param name="aFilename">The path to the file containing the graph data.</param>
/// <param name="aOnNodeRead">A callback function that is called for each node read. It takes one parameter: the node std::string. If the callback returns false, the reading process stops.</param>
/// <param name="aOnEdgeRead">A callback function that is called for each edge read. It takes three parameters: the fromNode std::string, the toNode std::string, and the weight float. If the callback returns false, the reading process stops.</param>
void readGraphFromFile(const std::string& aFilename, FNodeRead aOnNodeRead, FEdgeRead aOnEdgeRead);
/// <summary>
/// Delegate type for processing a song read from the file.
/// </summary>
/// <param name="aIndex">The index of the song (0-based).</param>
/// <param name="aTotalCount">The total number of songs.</param>
/// <param name="aArtist">The artist.</param>
/// <param name="aTitle">The title.</param>
/// <param name="aYear">The release year (as a std::string).</param>
/// <param name="aGenre">The genre.</param>
/// <param name="aSource">The source.</param>
/// <returns>Returns true to continue reading, false to stop.</returns>
typedef bool (*FSongRead)(
const int aIndex,
const int aTotalCount,
const std::string& aArtist,
const std::string& aTitle,
const std::string& aYear,
const std::string& aGenre,
const std::string& aSource
);
/// <summary>
/// Reads song data from a file and processes them using a callback.
/// This function automatically skips the "records:=" header.
/// </summary>
/// <param name="aFilename">The path to the file (e.g., "songs.txt").</param>
/// <param name="aOnSongRead">The callback function called for each song.</param>
void ReadSongsFromFile(const std::string& aFilename, FSongRead aOnSongRead);
void PrintList(TLinkedList* list);
#endif // SHARED_LIB_H

View File

@@ -0,0 +1,82 @@
#include "Sort.h"
int CompareByLastName(const TBankAccount* a, const TBankAccount* b)
{
if (a == b)
return 0;
if (!a)
return -1;
if (!b)
return 1;
if (a->ownerLastName < b->ownerLastName)
return -1;
if (a->ownerLastName > b->ownerLastName)
return 1;
if (a->ownerFirstName < b->ownerFirstName)
return -1;
if (a->ownerFirstName > b->ownerFirstName)
return 1;
return 0;
}
int CompareByBalanceAsc(const TBankAccount* a, const TBankAccount* b)
{
if (a == b)
return 0;
if (!a)
return -1;
if (!b)
return 1;
if (a->getBalance() < b->getBalance())
return -1;
if (a->getBalance() > b->getBalance())
return 1;
return 0;
}
static int CmpWrap(FCompareAccounts cmp, TBankAccount* a, TBankAccount* b, OperationSummary& s)
{
++s.comparisons;
return cmp(a, b);
}
static void SwapPointers(TBankAccount* a, TBankAccount* b, OperationSummary* s)
{
std::swap(a, b);
++s->swaps;
}
Sort::Sort(TBankAccount **sourceArray, int count, TLinkedList *sourceList)
: m_array(sourceArray), m_count(count), m_list(sourceList){}
TBankAccount **Sort::CloneArray() const
{
if (!m_array || m_count == 0)
return nullptr;
auto** copy = new TBankAccount*[m_count];
for (int i = 0; i < m_count; i++)
copy[i] = m_array[i];
return copy;
}
static TLinkedList* g_cloneTarget = nullptr;
static void AppendToClone(TBankAccount* acc, int)
{
if (g_cloneTarget)
g_cloneTarget->Append(acc);
}
TLinkedList *Sort::CloneList() const
{
if (!m_list)
return nullptr;
auto* copy = new TLinkedList(false);
m_list->forEach(AppendToClone);
g_cloneTarget = copy;
return copy;
}

View File

@@ -0,0 +1,53 @@
#pragma once
#include "BankAccount.h"
#include "BankAccountList.h"
typedef int (*FCompareAccounts)(TBankAccount* a, TBankAccount* b);
struct OperationSummary {
long long comparisons = 0;
long long swaps = 0;
double timeSpentInMs = 0.0;
void Reset()
{
comparisons = 0;
swaps = 0;
timeSpentInMs = 0.0;
}
};
class Sort {
public:
Sort(TBankAccount** sourceArray, int count, TLinkedList* sourceList);
TBankAccount** GetArray() const
{
return m_array;
}
int GetCount() const
{
return m_count;
}
TLinkedList* GetList() const
{
return m_list;
}
TBankAccount** CloneArray() const;
TLinkedList* CloneList() const;
TBankAccount** SelectionSortArray(FCompareAccounts cmp, OperationSummary& out);
TLinkedList* SelectionSortList(FCompareAccounts cmp, OperationSummary& out);
TBankAccount** BubbleSortArray(FCompareAccounts cmp, OperationSummary& out);
TBankAccount** QuickSortArray(FCompareAccounts cmp, OperationSummary& out);
TLinkedList* MergeSortList(FCompareAccounts cmp, OperationSummary& out);
private:
TBankAccount** m_array = nullptr;
int m_count = 0;
TLinkedList* m_list = nullptr;
};

View File

@@ -0,0 +1,18 @@
#include <bits/stl_tree.h>
#include "SharedLib.h"
int g_printIndex = 0;
static void PrintAccCallback(TBankAccount* acc, int /*i*/)
{
std::cout << g_printIndex++ << ": " << acc->ownerFirstName << " " << acc->ownerLastName
<< " | Balance: " << acc->getBalance() << std::endl;
}
void PrintList(TLinkedList* list)
{
if (!list)
return;
g_printIndex = 0;
list->forEach(PrintAccCallback);
}

View File

@@ -0,0 +1,28 @@
#include "main.h"
#include "SharedLib.h"
#include "Sort.h"
static TLinkedList g_list(false);
static std::vector<TBankAccount*> g_array;
static bool onNameRead(const int idx, const int total, const std::string& first, const std::string& last)
{
auto* acc = new TBankAccount(Checking, first, last);
g_list.Append(acc);
g_array.push_back(acc);
return true;
}
int main()
{
readNamesFromFile("random_names.txt", onNameRead);
Sort sorter(g_array.data(), (int)g_array.size(), &g_list);
PrintList(&g_list);
return 0;
}

View File

@@ -0,0 +1,6 @@
#include <iostream>

File diff suppressed because it is too large Load Diff