Compare commits
11 Commits
d6d627adad
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0a4fa60b8 | ||
|
|
6e9e3ecd4d | ||
|
|
a014e4ca73 | ||
|
|
e77d7ff21e | ||
|
|
d1fa8eda6b | ||
|
|
1e00ba3521 | ||
|
|
b8aa672431 | ||
|
|
58772c0488 | ||
|
|
ae8a53e16b | ||
|
|
730987913e | ||
|
|
4c6e3d0905 |
@@ -21,8 +21,6 @@ endif()
|
||||
# The order matters here: we add LibExample first so that its library is
|
||||
# defined before the executables that need to link to it.
|
||||
|
||||
add_subdirectory(LibExample)
|
||||
add_subdirectory(Submissions)
|
||||
add_subdirectory(Portfolio)
|
||||
|
||||
# --- End of File ---
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 ---
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
// 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 <iostream>
|
||||
@@ -16,6 +17,9 @@ bool running = true;
|
||||
int lastIndex = 0;
|
||||
std::string deletedLine;
|
||||
|
||||
// Undo the last text modification.
|
||||
// Reverses INSERT/DELETE actions by applying the inverse operation.
|
||||
// Moves reversed action into redoStack.
|
||||
void Undo()
|
||||
{
|
||||
if (!undoStack.IsEmpty()) {
|
||||
@@ -29,6 +33,10 @@ void Undo()
|
||||
redoStack.Push(action);
|
||||
}
|
||||
}
|
||||
|
||||
// Redo the last undone modification.
|
||||
// Re-applies an action previously undone.
|
||||
// Pushes the executed action back into undoStack.
|
||||
void Redo()
|
||||
{
|
||||
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()
|
||||
{
|
||||
// Implement the Console Text Editor application logic here
|
||||
@@ -62,31 +72,56 @@ int RunApp()
|
||||
}
|
||||
case 3: {
|
||||
std::cout << "----------Current document----------" << std::endl;
|
||||
for (int i = 0; i < document.GetSize(); i++)
|
||||
std::cout << i + 1 << ". " << document.GetAtIndex(i) << std::endl;
|
||||
std::cout << "------------------------------------\n\n";
|
||||
for (int i = 0; i < document.GetSize(); i++) {
|
||||
std::cout << document.GetAtIndex(i) << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Build a single print job containing the entire document.
|
||||
// Snapshot is stored as a single string and enqueued.
|
||||
case 4: {
|
||||
for (int i = 0; i < document.GetSize(); ++i)
|
||||
printQueue.Enqueue(document.GetAtIndex(i));
|
||||
|
||||
std::cout << "----------Printing queue-----------" << std::endl;
|
||||
|
||||
while (!printQueue.IsEmpty())
|
||||
std::cout << printQueue.Dequeue() << std::endl;
|
||||
std::cout << "------------------------------------\n\n";
|
||||
std::cout << "----------Add print job----------" << std::endl;
|
||||
|
||||
if (document.GetSize() == 0) {
|
||||
std::cout << "Document is empty - nothing added to print queue." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
Undo();
|
||||
break;
|
||||
}
|
||||
|
||||
case 6: {
|
||||
case 7: {
|
||||
std::cout << "----------REDO----------" <<std::endl;
|
||||
Redo();
|
||||
break;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,43 +1,38 @@
|
||||
// Option 1 (Standard): Console Text Editor.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "option1.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "SharedLib.h"
|
||||
#include "TLinkedList.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()
|
||||
{
|
||||
/* Path to the names data file
|
||||
This is MY absolute path -- change to your local path for this to read properly
|
||||
something like "C:\Users\Username\FolderYouSavedTheSubmissionIn\Exam\IKT203Exam\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";
|
||||
// Path to the names data file.
|
||||
// IMPORTANT: working directory must be set so that "DATA/random_names.txt" resolves correctly.
|
||||
const std::string filename = "DATA/random_names.txt";
|
||||
|
||||
pack("Reading names and grouping them.");
|
||||
// Call the utility function with the name callback
|
||||
readNamesFromFile(filename, onNameRead);
|
||||
|
||||
pack("Finished reading names.");
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////// Merge sorting ///////////////////////////
|
||||
// Sort both employee and guest linked lists alphabetically
|
||||
// using the linked-list merge sort implementation in TLinkedList.
|
||||
e.Sort();
|
||||
g.Sort();
|
||||
pack("Sorting.");
|
||||
// Attempt at "beautifying" the terminal output somewhat
|
||||
pack("Employees merge sorted alphabetically.");
|
||||
TPerson* employeeAlphaSort[e.GetSize()];
|
||||
const int employeeSize = e.GetSize();
|
||||
auto** employeeAlphaSort = new TPerson*[employeeSize];
|
||||
printline();
|
||||
for (int i = 0; i < e.GetSize(); i++) {
|
||||
std::cout << "[" << i << "] " << e.GetAtIndex(i).lastName << ", " << e.GetAtIndex(i).firstName
|
||||
@@ -45,8 +40,9 @@ int RunApp()
|
||||
employeeAlphaSort[i] = new TPerson(e.GetAtIndex(i));
|
||||
}
|
||||
printline();
|
||||
pack("Guests merger sorted alphabetically.");
|
||||
TPerson* guestAlphaSort[g.GetSize()];
|
||||
pack("Guests merge sorted alphabetically.");
|
||||
const int guestSize = g.GetSize();
|
||||
auto** guestAlphaSort = new TPerson*[guestSize];
|
||||
printline();
|
||||
for (int i = 0; i < g.GetSize(); i++) {
|
||||
std::cout << "[" << i << "] " << g.GetAtIndex(i).lastName << ", " << g.GetAtIndex(i).firstName
|
||||
@@ -55,15 +51,15 @@ int RunApp()
|
||||
}
|
||||
printline();
|
||||
|
||||
|
||||
|
||||
/////////////////////////// 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
|
||||
auto** guestList = new TPerson*[guestCount];
|
||||
for (int i = 0; i < guestCount; i++) {
|
||||
guestList[i] = new TPerson(g.GetAtIndex(i));
|
||||
}
|
||||
// Quicksorting the guestlist array
|
||||
Utils::QuickSort(guestList, 0, guestCount - 1);
|
||||
|
||||
pack("Guests quick sorted by 1) cabinsize, 2) lastname.");
|
||||
@@ -74,19 +70,16 @@ int RunApp()
|
||||
}
|
||||
printline();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////// 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;
|
||||
std::string target;
|
||||
std::cout << "What list do you want to search through: \n [1] Employee\n [2] Guest" << std::endl;
|
||||
std::cin >> choice;
|
||||
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);
|
||||
|
||||
switch (choice) {
|
||||
@@ -100,21 +93,31 @@ switch (choice) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////// 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;
|
||||
|
||||
while (e.GetSize() > 0)
|
||||
e.Remove(0);
|
||||
while (g.GetSize() > 0)
|
||||
g.Remove(0);
|
||||
|
||||
pack("Cleaned up memory");
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -7,8 +9,13 @@
|
||||
#include "TLinkedList.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 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)
|
||||
{
|
||||
// Determine status based on index: first 1500 are employees, rest are guests.
|
||||
const ENumStatus status = (aIndex < 1500) ? EMPLOYEE : GUEST;
|
||||
|
||||
const TPerson p(aFirstName, aLastName, status);
|
||||
@@ -64,7 +75,10 @@ static bool onNameRead(const int aIndex, const int aTotalCount, const std::strin
|
||||
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)
|
||||
{
|
||||
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 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)) {
|
||||
--left;
|
||||
}
|
||||
|
||||
// Move right while neighbouring entries share the same first or last name
|
||||
while (right < arraySize && (targetArray[right]->firstName == target || targetArray[right]->lastName == target)) {
|
||||
++right;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ add_executable(Assignment-03
|
||||
TBST.cpp
|
||||
TBST.h
|
||||
TEmployee.h
|
||||
TTreeQueue.cpp
|
||||
TAVL.cpp
|
||||
TAVL.h
|
||||
)
|
||||
|
||||
# Conditionally add the correct source file
|
||||
|
||||
243
Exam/IKT203Exam/Portfolio/Assignment-03/TAVL.cpp
Normal file
243
Exam/IKT203Exam/Portfolio/Assignment-03/TAVL.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
51
Exam/IKT203Exam/Portfolio/Assignment-03/TAVL.h
Normal file
51
Exam/IKT203Exam/Portfolio/Assignment-03/TAVL.h
Normal 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
|
||||
@@ -1,48 +1,58 @@
|
||||
#include "TBST.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "TTreeQueue.h"
|
||||
|
||||
|
||||
void TBST::destroy(Node *node)
|
||||
void TBST::destroy(BSTNode *node)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
destroy(node->left);
|
||||
destroy(node->right);
|
||||
// TBST owns the TEmployee* stored in each node, so delete it here.
|
||||
delete node->data;
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
auto* n = new Node{key, data, nullptr, nullptr};
|
||||
auto* n = new BSTNode{key, data, nullptr, nullptr};
|
||||
return n;
|
||||
}
|
||||
if (key < node->key)
|
||||
node->left = insert(node->left, key, data);
|
||||
else if (key > node->key)
|
||||
node->right = insert(node->right, key, data);
|
||||
else
|
||||
std::cout << "Error with node insertion" << std::endl;
|
||||
|
||||
else {
|
||||
// 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;
|
||||
}
|
||||
|
||||
///<summary> Search for node </summary
|
||||
///<param name="key"> Node key value (int) </param>
|
||||
/// <returns> TEmployee </returns>
|
||||
TEmployee *TBST::Search(int key) const
|
||||
{
|
||||
const Node* result = search(root, key);
|
||||
const BSTNode* result = search(root, key);
|
||||
return result ? result->data : nullptr;
|
||||
}
|
||||
|
||||
Node* TBST::search(Node* node, const int key)
|
||||
BSTNode* TBST::search(BSTNode* node, const int key)
|
||||
{
|
||||
if (node == nullptr)
|
||||
return nullptr;
|
||||
@@ -54,12 +64,15 @@ Node* TBST::search(Node* node, const int 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)
|
||||
{
|
||||
root = remove(root, key);
|
||||
}
|
||||
|
||||
Node *TBST::remove(Node *node, const int key)
|
||||
BSTNode *TBST::remove(BSTNode *node, const int key)
|
||||
{
|
||||
if (node == nullptr)
|
||||
return nullptr;
|
||||
@@ -76,21 +89,24 @@ Node *TBST::remove(Node *node, const int key)
|
||||
}
|
||||
// Right child only
|
||||
if (node->left == nullptr) {
|
||||
Node* child = node->right;
|
||||
BSTNode* child = node->right;
|
||||
delete node->data;
|
||||
delete node;
|
||||
return child;
|
||||
}
|
||||
// Left child only
|
||||
if (node->right == nullptr) {
|
||||
Node* child = node->left;
|
||||
BSTNode* child = node->left;
|
||||
delete node->data;
|
||||
delete node;
|
||||
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 {
|
||||
Node* minRight = findMin(node->right);
|
||||
BSTNode* minRight = findMin(node->right);
|
||||
node->key = minRight->key;
|
||||
node->data = minRight->data;
|
||||
node->right = remove(minRight->right, minRight->key);
|
||||
@@ -99,16 +115,16 @@ Node *TBST::remove(Node *node, const int key)
|
||||
return node;
|
||||
}
|
||||
|
||||
Node* TBST::findMin(Node* node)
|
||||
BSTNode* TBST::findMin(BSTNode* node)
|
||||
{
|
||||
while (node && node->left)
|
||||
node = node->left;
|
||||
return node;
|
||||
}
|
||||
|
||||
/// Traversals
|
||||
/// Private helpers
|
||||
void TBST::preorder(const Node* node)
|
||||
// Traversals
|
||||
// Private helpers
|
||||
void TBST::preorder(const BSTNode* node)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
@@ -117,7 +133,7 @@ void TBST::preorder(const Node* node)
|
||||
preorder(node->right);
|
||||
}
|
||||
|
||||
void TBST::inorder(const Node* node)
|
||||
void TBST::inorder(const BSTNode* node)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
@@ -126,7 +142,7 @@ void TBST::inorder(const Node* node)
|
||||
inorder(node->right);
|
||||
}
|
||||
|
||||
void TBST::postorder(const Node *node)
|
||||
void TBST::postorder(const BSTNode *node)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
@@ -135,48 +151,52 @@ void TBST::postorder(const Node *node)
|
||||
std::cout << "[" << node->key << "] ";
|
||||
}
|
||||
|
||||
void TBST::levelorder(const Node* node)
|
||||
void TBST::levelorder(const BSTNode* node)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
TTreeQueue q;
|
||||
q.Enqueue(const_cast<Node*>(node));
|
||||
TTreeQueue<BSTNode> q;
|
||||
q.Enqueue(const_cast<BSTNode*>(node));
|
||||
|
||||
while (!q.IsEmpty()) {
|
||||
const Node* cur = q.Dequeue();
|
||||
const BSTNode* cur = q.Dequeue();
|
||||
std::cout << "[" << cur->key << "] ";
|
||||
if (cur->left)
|
||||
q.Enqueue(cur->left);
|
||||
if (cur->right)
|
||||
q.Enqueue(cur->right);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///<summary> Inorder sorting </summary
|
||||
/// <returns> None </returns>
|
||||
void TBST::Inorder() const
|
||||
{
|
||||
inorder(root);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
///<summary> Preorder sorting </summary
|
||||
/// <returns> None </returns>
|
||||
void TBST::Preorder() const
|
||||
{
|
||||
preorder(root);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
///<summary> Postorder sorting </summary
|
||||
/// <returns> None </returns>
|
||||
void TBST::Postorder() const
|
||||
{
|
||||
postorder(root);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
///<summary> LevelOrder sorting </summary
|
||||
/// <returns> None </returns>
|
||||
void TBST::LevelOrder() const
|
||||
{
|
||||
levelorder(root);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,36 +2,32 @@
|
||||
#define IKT203_COURSE_ASSIGNMENTS_TBST_H
|
||||
#include "TEmployee.h"
|
||||
|
||||
|
||||
struct Node {
|
||||
int key;
|
||||
TEmployee* data;
|
||||
Node* left;
|
||||
Node* right;
|
||||
// Node in the Binary Search Tree.
|
||||
// Owns a single TEmployee* which is deleted by TBST::destroy/remove.
|
||||
struct BSTNode {
|
||||
int key; // employee ID
|
||||
TEmployee* data; // employee record
|
||||
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 {
|
||||
private:
|
||||
Node* root;
|
||||
BSTNode* root;
|
||||
|
||||
static Node* insert(Node* node, int key, TEmployee* data);
|
||||
|
||||
static Node* search(Node* node, int key);
|
||||
|
||||
static Node* remove(Node* node, int key);
|
||||
|
||||
static void inorder(const Node* node);
|
||||
|
||||
static void preorder(const Node* node);
|
||||
|
||||
static void postorder(const Node* node);
|
||||
|
||||
static void levelorder(const Node* node);
|
||||
|
||||
static void destroy(Node* node);
|
||||
|
||||
static Node* findMin(Node* node);
|
||||
static BSTNode* insert(BSTNode* node, int key, TEmployee* data);
|
||||
static BSTNode* search(BSTNode* node, int key);
|
||||
static BSTNode* remove(BSTNode* node, int key);
|
||||
static void inorder(const BSTNode* node);
|
||||
static void preorder(const BSTNode* node);
|
||||
static void postorder(const BSTNode* node);
|
||||
static void levelorder(const BSTNode* node);
|
||||
static void destroy(BSTNode* node);
|
||||
static BSTNode* findMin(BSTNode* node);
|
||||
|
||||
public:
|
||||
TBST() = default;
|
||||
@@ -40,13 +36,9 @@ class TBST {
|
||||
void Insert(int key, TEmployee* data);
|
||||
[[nodiscard]] TEmployee* Search(int key) const;
|
||||
void Delete(int key);
|
||||
|
||||
void Inorder() const;
|
||||
void Preorder() const;
|
||||
void Postorder() const;
|
||||
|
||||
void LevelOrder() const;
|
||||
};
|
||||
|
||||
|
||||
#endif //IKT203_COURSE_ASSIGNMENTS_TBST_H
|
||||
@@ -3,7 +3,8 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
|
||||
// Simple employee record used in Category 3.
|
||||
// 'id' is set later by IdGenerator and used as the BST key.
|
||||
struct TEmployee {
|
||||
std::string firstName;
|
||||
std::string lastName;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -2,13 +2,15 @@
|
||||
#define TQUEUE_H
|
||||
#define MAX_SIZE 200
|
||||
|
||||
#include <stdexcept>
|
||||
#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 {
|
||||
|
||||
Node* queue[MAX_SIZE];
|
||||
T* queue[MAX_SIZE];
|
||||
int head = 0;
|
||||
int tail = 0;
|
||||
int count = 0;
|
||||
@@ -17,10 +19,38 @@ struct TTreeQueue {
|
||||
TTreeQueue() = default;
|
||||
~TTreeQueue() = default;
|
||||
|
||||
void Enqueue(Node* n);
|
||||
Node* Dequeue();
|
||||
[[nodiscard]] bool IsEmpty() const;
|
||||
[[nodiscard]] bool IsFull() const;
|
||||
void Enqueue(T* n)
|
||||
{
|
||||
if (n == nullptr)
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
#include "option1.h"
|
||||
|
||||
#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() {
|
||||
//Reading names from file for BST population
|
||||
bst = new TBST();
|
||||
/* Path to the names data file
|
||||
This is MY absolute path -- change to your local path for this to read properly
|
||||
something like "C:\Users\Username\FolderYouSavedTheSubmissionIn\Exam\IKT203Exam\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";
|
||||
|
||||
// Read 200 employees from the names file and populate the BST.
|
||||
// IMPORTANT: Working directory must be the Portfolio/Assignment-03 folder
|
||||
// so that "DATA/random_names.txt" resolves correctly.
|
||||
const std::string filename = "DATA/random_names.txt";
|
||||
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)");
|
||||
bst->Inorder();
|
||||
|
||||
@@ -23,6 +34,8 @@ int RunApp() {
|
||||
pack("Postorder traversal");
|
||||
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");
|
||||
std::cout << "\nInput the ID you want to search for\n" << std::endl;
|
||||
int choice;
|
||||
@@ -33,6 +46,9 @@ int RunApp() {
|
||||
else
|
||||
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");
|
||||
std::cout << "\nInput the ID you want to remove\n" << std::endl;
|
||||
std::cin >> choice;
|
||||
@@ -44,8 +60,36 @@ int RunApp() {
|
||||
else
|
||||
std::cout << "ID not found\n" << std::endl;
|
||||
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");
|
||||
delete bst;
|
||||
delete avl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,23 +3,24 @@
|
||||
#ifndef OPTION1_H
|
||||
#define OPTION1_H
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <TTreeQueue.h>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "TAVL.h"
|
||||
#include "TBST.h"
|
||||
#include "TEmployee.h"
|
||||
#include "Utils.h"
|
||||
#include "../../Submissions/Submission-04/BankAccount.h"
|
||||
|
||||
/// To keep track of used ID values to ensure
|
||||
/// all unique IDs
|
||||
// Global state for Category 3, Option 1:
|
||||
// - 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;
|
||||
static TBST* bst;
|
||||
static TAVL* avl;
|
||||
|
||||
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)
|
||||
{
|
||||
int id = Utils::RandomInt(1, 1000);
|
||||
@@ -30,6 +31,11 @@ inline void IdGenerator(TEmployee* employee)
|
||||
usedIds.insert(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)
|
||||
{
|
||||
const auto e = new TEmployee(aFirstName, aLastName);
|
||||
@@ -48,6 +54,7 @@ inline void printline()
|
||||
std::cout << "----------------------------------------" << std::endl;
|
||||
}
|
||||
|
||||
// Helper to visually separate different demos (traversals, search, etc.) in the console output.
|
||||
inline void pack(const std::string& line)
|
||||
{
|
||||
std::cout << "\n\n\n" << std::endl;
|
||||
@@ -56,4 +63,6 @@ inline void pack(const std::string& line)
|
||||
printline();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // OPTION1_H
|
||||
|
||||
@@ -3,10 +3,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
||||
# "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
|
||||
main.cpp
|
||||
option1.cpp
|
||||
)
|
||||
|
||||
if(BUILD_ASSIGNMENT_04_OPTION_1)
|
||||
|
||||
@@ -28,16 +28,18 @@ To force an update (e.g., in Visual Studio):
|
||||
|
||||
#include <iostream>
|
||||
#include <string_view>
|
||||
#include "option1.h"
|
||||
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.";
|
||||
|
||||
/*
|
||||
#if ASSIGNMENT_04_OPTION == 1
|
||||
#include "option1.h"
|
||||
#elif ASSIGNMENT_04_OPTION == 2
|
||||
static constexpr std::string_view AssignmentOption = "Option 2 (Advanced): Inter-city Logistics Router.";
|
||||
#include "option2.h"
|
||||
#endif
|
||||
|
||||
*/
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
@@ -1,6 +1,274 @@
|
||||
#include "option1.h"
|
||||
#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() {
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -2,6 +2,81 @@
|
||||
|
||||
#ifndef 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();
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ static bool EdgeReadCallback(const int aIndex, const int aTotalCount, const std:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
int RunApp()
|
||||
{
|
||||
|
||||
@@ -44,4 +44,4 @@ int RunApp()
|
||||
std::cout << "\nFinished reading graph." << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}*/
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
#ifndef OPTION2_H
|
||||
#define OPTION2_H
|
||||
|
||||
/*
|
||||
int RunApp();
|
||||
|
||||
*/
|
||||
|
||||
#endif // OPTION2_H
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#define SHARED_LIB_H
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include "../Assignment-03/TAVL.h"
|
||||
|
||||
/// <summary>
|
||||
/// Delegate type for processing a name read from a file.
|
||||
|
||||
@@ -3,7 +3,19 @@
|
||||
#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)
|
||||
{
|
||||
auto* newNode = new Node(line);
|
||||
@@ -17,6 +29,7 @@ void TDoublyLinkedList::Append(const std::string& line)
|
||||
size++;
|
||||
}
|
||||
|
||||
// Insert a new line at the beginning.
|
||||
void TDoublyLinkedList::Prepend(const std::string& line)
|
||||
{
|
||||
auto* newNode = new Node(line);
|
||||
@@ -43,6 +56,7 @@ TDoublyLinkedList::Node* TDoublyLinkedList::NavigateToNode(const int index) cons
|
||||
return node;
|
||||
}
|
||||
|
||||
// Removes the node at the given index and updates head/tail if needed.
|
||||
void TDoublyLinkedList::Remove(const int index)
|
||||
{
|
||||
auto* node = NavigateToNode(index);
|
||||
|
||||
@@ -2,13 +2,16 @@
|
||||
#define TDOUBLYLINKEDLIST_H
|
||||
#include <string>
|
||||
#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 {
|
||||
|
||||
private:
|
||||
// Internal node storing a single line of text
|
||||
// and links to previous and next nodes.
|
||||
struct Node {
|
||||
std::string line;
|
||||
Node* next;
|
||||
@@ -45,12 +48,21 @@ private:
|
||||
|
||||
public:
|
||||
TDoublyLinkedList() : head(nullptr), tail(nullptr), size(0) {}
|
||||
~TDoublyLinkedList() = default;
|
||||
~TDoublyLinkedList();
|
||||
|
||||
void Append(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;
|
||||
|
||||
// Removes a node at the given index.
|
||||
// Updates links and frees the removed node.
|
||||
void Remove(int index);
|
||||
|
||||
// Returns the text stored at the given index.
|
||||
// Uses NavigateToNode internally.
|
||||
[[nodiscard]] std::string GetAtIndex(int index) const;
|
||||
void InsertAtIndex(int index, const std::string &line);
|
||||
[[nodiscard]] int GetSize() const;
|
||||
|
||||
@@ -149,8 +149,8 @@ TLinkedList::Node *TLinkedList::MergeList(Node *a, Node *b)
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Time complexity O(n log n) at all times
|
||||
/// Does NOT sort in place, so more memory is needed to complete
|
||||
// Time complexity O(n log n) at all times
|
||||
// Does NOT sort in place, so more memory is needed to complete
|
||||
TLinkedList::Node *TLinkedList::MergeSort(Node *head)
|
||||
{
|
||||
if (head == nullptr || head->next == nullptr)
|
||||
@@ -166,6 +166,8 @@ TLinkedList::Node *TLinkedList::MergeSort(Node *head)
|
||||
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()
|
||||
{
|
||||
this->head = MergeSort(head);
|
||||
|
||||
@@ -3,12 +3,15 @@
|
||||
|
||||
#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 {
|
||||
|
||||
|
||||
private:
|
||||
struct Node {
|
||||
TPerson person;
|
||||
TPerson person; // stored by value
|
||||
Node* next;
|
||||
explicit Node(const TPerson& p) : person(p), next(nullptr) {}
|
||||
|
||||
|
||||
@@ -9,7 +9,9 @@ enum ENumStatus {
|
||||
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 {
|
||||
std::string firstName;
|
||||
std::string lastName;
|
||||
@@ -20,6 +22,8 @@ struct TPerson {
|
||||
TPerson(std::string , std::string , ENumStatus);
|
||||
~TPerson() = default;
|
||||
|
||||
// Comparison for alphabetical sorting:
|
||||
// primary key: lastName, secondary key: firstName.
|
||||
bool operator<(const TPerson& other) const
|
||||
{
|
||||
if (lastName < other.lastName) return true;
|
||||
|
||||
@@ -10,8 +10,13 @@ enum EnumActionType {
|
||||
DELETE
|
||||
};
|
||||
|
||||
// Simple fixed-size stack used for undo/redo.
|
||||
// Stores actions describing line insert/delete operations.
|
||||
class TStack {
|
||||
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 {
|
||||
EnumActionType action;
|
||||
std::string text;
|
||||
@@ -24,9 +29,8 @@ private:
|
||||
public:
|
||||
TStack() = default;
|
||||
~TStack() = default;
|
||||
|
||||
void Push(const TAction& action);
|
||||
TAction Pop();
|
||||
void Push(const TAction& action); // Adds a new action to the top of the stack.
|
||||
TAction Pop(); // Removes and returns the most recent action.
|
||||
[[nodiscard]] TAction Peek() const;
|
||||
[[nodiscard]] bool IsEmpty() const;
|
||||
void Clear();
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
#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 {
|
||||
private:
|
||||
std::string queue[MAX_SIZE];
|
||||
@@ -17,8 +19,8 @@ public:
|
||||
TTreeQueue() = default;
|
||||
~TTreeQueue() = default;
|
||||
|
||||
void Enqueue(const std::string& text);
|
||||
std::string Dequeue();
|
||||
void Enqueue(const std::string& text); // Adds a new job at the tail of the queue.
|
||||
std::string Dequeue(); // Removes and returns the next job in FIFO order.
|
||||
[[nodiscard]] int GetTail() const;
|
||||
[[nodiscard]] std::string Peek() const;
|
||||
[[nodiscard]] bool IsEmpty() const;
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <numbers>
|
||||
|
||||
// Displays the main menu and reads user 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: ";
|
||||
int choice;
|
||||
std::cin >> choice;
|
||||
@@ -17,6 +17,9 @@ int Utils::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)
|
||||
{
|
||||
for (int i = 0; i < document.GetSize(); i++) {
|
||||
@@ -58,6 +61,8 @@ void Utils::PrintList(const TDoublyLinkedList &document)
|
||||
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)
|
||||
{
|
||||
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
|
||||
} // 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)
|
||||
{
|
||||
if (a->cabinSize < b->cabinSize)
|
||||
@@ -117,10 +125,10 @@ int Utils::Partition(TPerson **arr, const int startIndex, const int endIndex)
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
/// Time complexity **on average** is O(n log n) but worst case it O(n^2)
|
||||
/// depending on where in the range the pivot lands -- If pivot is at either extreme
|
||||
/// the algorithm has to search through the entire list for every value it sorts -- n^2
|
||||
/// However it does sort in-place, meaning no extra memory is needed
|
||||
// QuickSort on an array of TPerson* using CompareLastnames:
|
||||
// - Average time: O(n log n)
|
||||
// - Worst case: O(n^2) if pivot choices are bad
|
||||
// - Sorts in-place (no extra arrays)
|
||||
void Utils::QuickSort(TPerson** arr, const int low, const int 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)
|
||||
/// However the included fallback search is O(n)
|
||||
// Binary search on an alphabetically sorted array of TPerson* (by lastName, then firstName).
|
||||
// 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)
|
||||
{
|
||||
const int origStart = p1;
|
||||
@@ -153,9 +161,7 @@ int Utils::BinarySearch(TPerson** arr, int p1, int p2, const std::string &target
|
||||
p2 = newP - 1;
|
||||
}
|
||||
|
||||
/// Extra to search for firstname in the event that no matches were found
|
||||
/// Disregard this section if you're purely looking at the
|
||||
/// binary search understanding and implementation
|
||||
// Fallback linear scan for first names if no last name match
|
||||
for (int i = origStart; i <= origEnd; i++) {
|
||||
if (arr[i]->firstName == target)
|
||||
return i;
|
||||
|
||||
@@ -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
|
||||
13
SimpleSearch/CMakeLists.txt
Normal file
13
SimpleSearch/CMakeLists.txt
Normal 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
|
||||
)
|
||||
25
SimpleSearch/EBankAccountType.h
Normal file
25
SimpleSearch/EBankAccountType.h
Normal 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
|
||||
|
||||
8
SimpleSearch/FCompareAccount.h
Normal file
8
SimpleSearch/FCompareAccount.h
Normal 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
5401
SimpleSearch/Random_Name.txt
Normal file
File diff suppressed because it is too large
Load Diff
9
SimpleSearch/SearchSummary.h
Normal file
9
SimpleSearch/SearchSummary.h
Normal 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
|
||||
69
SimpleSearch/TBankAccount.cpp
Normal file
69
SimpleSearch/TBankAccount.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
37
SimpleSearch/TBankAccount.h
Normal file
37
SimpleSearch/TBankAccount.h
Normal 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
157
SimpleSearch/TLinkedList.h
Normal 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
256
SimpleSearch/main.cpp
Normal 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
8
TheAlgorithmicOrganizer/.idea/.gitignore
generated
vendored
Normal 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
|
||||
2
TheAlgorithmicOrganizer/.idea/TheAlgoeithmicOrganizer.iml
generated
Normal file
2
TheAlgorithmicOrganizer/.idea/TheAlgoeithmicOrganizer.iml
generated
Normal 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
343
TheAlgorithmicOrganizer/.idea/editor.xml
generated
Normal 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>
|
||||
12
TheAlgorithmicOrganizer/.idea/material_theme_project_new.xml
generated
Normal file
12
TheAlgorithmicOrganizer/.idea/material_theme_project_new.xml
generated
Normal 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
7
TheAlgorithmicOrganizer/.idea/misc.xml
generated
Normal 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>
|
||||
8
TheAlgorithmicOrganizer/.idea/modules.xml
generated
Normal file
8
TheAlgorithmicOrganizer/.idea/modules.xml
generated
Normal 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
6
TheAlgorithmicOrganizer/.idea/vcs.xml
generated
Normal 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>
|
||||
108
TheAlgorithmicOrganizer/BankAccount.cpp
Normal file
108
TheAlgorithmicOrganizer/BankAccount.cpp
Normal 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;
|
||||
}
|
||||
52
TheAlgorithmicOrganizer/BankAccount.h
Normal file
52
TheAlgorithmicOrganizer/BankAccount.h
Normal 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
|
||||
130
TheAlgorithmicOrganizer/BankAccountList.cpp
Normal file
130
TheAlgorithmicOrganizer/BankAccountList.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
51
TheAlgorithmicOrganizer/BankAccountList.h
Normal file
51
TheAlgorithmicOrganizer/BankAccountList.h
Normal 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
|
||||
19
TheAlgorithmicOrganizer/CMakeLists.txt
Normal file
19
TheAlgorithmicOrganizer/CMakeLists.txt
Normal 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
|
||||
)
|
||||
30
TheAlgorithmicOrganizer/FileReaderUtils.cpp
Normal file
30
TheAlgorithmicOrganizer/FileReaderUtils.cpp
Normal 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
|
||||
}
|
||||
}
|
||||
13
TheAlgorithmicOrganizer/FileReaderUtils.h
Normal file
13
TheAlgorithmicOrganizer/FileReaderUtils.h
Normal 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
|
||||
55
TheAlgorithmicOrganizer/ReadNames.cpp
Normal file
55
TheAlgorithmicOrganizer/ReadNames.cpp
Normal 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();
|
||||
}
|
||||
106
TheAlgorithmicOrganizer/SharedLib.h
Normal file
106
TheAlgorithmicOrganizer/SharedLib.h
Normal 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
|
||||
82
TheAlgorithmicOrganizer/Sort.cpp
Normal file
82
TheAlgorithmicOrganizer/Sort.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
53
TheAlgorithmicOrganizer/Sort.h
Normal file
53
TheAlgorithmicOrganizer/Sort.h
Normal 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;
|
||||
|
||||
};
|
||||
18
TheAlgorithmicOrganizer/Utils.cpp
Normal file
18
TheAlgorithmicOrganizer/Utils.cpp
Normal 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);
|
||||
}
|
||||
28
TheAlgorithmicOrganizer/main.cpp
Normal file
28
TheAlgorithmicOrganizer/main.cpp
Normal 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;
|
||||
}
|
||||
6
TheAlgorithmicOrganizer/main.h
Normal file
6
TheAlgorithmicOrganizer/main.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
5401
TheAlgorithmicOrganizer/random_names.txt
Normal file
5401
TheAlgorithmicOrganizer/random_names.txt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user