diff --git a/Exam/IKT203Exam/.idea/material_theme_project_new.xml b/Exam/IKT203Exam/.idea/material_theme_project_new.xml index 32939b5..554b701 100644 --- a/Exam/IKT203Exam/.idea/material_theme_project_new.xml +++ b/Exam/IKT203Exam/.idea/material_theme_project_new.xml @@ -3,7 +3,9 @@ diff --git a/Exam/IKT203Exam/Portfolio/Assignment-02/option1.cpp b/Exam/IKT203Exam/Portfolio/Assignment-02/option1.cpp index a558b61..ab89140 100644 --- a/Exam/IKT203Exam/Portfolio/Assignment-02/option1.cpp +++ b/Exam/IKT203Exam/Portfolio/Assignment-02/option1.cpp @@ -4,44 +4,14 @@ #include #include #include "option1.h" + +#include + #include "SharedLib.h" #include "TLinkedList.h" #include "TPerson.h" -TLinkedList g, e; - -/** - * @brief Callback function to process one name. -static bool NameReadCallback(const int aIndex, const int aTotalCount, const std::string& aFirstName, const std::string& aLastName) -{ - std::cout << "Reading Name " << (aIndex + 1) << " of " << aTotalCount << ": " - << aFirstName << " " << aLastName << "\n"; - - // We only want to read 10 names (index 0 through 9) - // Return false when aIndex is 9 to stop the loop after this one. - return (aIndex < 9); -} -*/ - -// *Inspired* by the provided NameReadCallback given above -static bool onNameRead(const int aIndex, int aTotalCount, const std::string& aFirstName, const std::string& aLastName) -{ - const ENumStatus status = (aIndex < 1500) ? EMPLOYEE : GUEST; - - const TPerson p(aFirstName, aLastName, status); - - - if (status == EMPLOYEE) - e.Append(p); - else - g.Append(p); - - std::cout << "[" <lastName << ", " << guestList[i]->firstName + << " | cabinSize: " << guestList[i]->cabinSize << std::endl; + } + printline(); + + + + + + + + /////////////////////////// Binary search /////////////////////////// + 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::max(), '\n'); + std::cout << "Enter surname to search: " << std::endl; + std::getline(std::cin, target); + +switch (choice) { + case 1: SearchAndPrint(employeeAlphaSort, employCount, target); break; + + case 2: SearchAndPrint(guestAlphaSort, guestCount, target); break; + + default: { + std::cout << "Choice invalid" << std::endl; + std::cin.ignore(std::numeric_limits::max(), '\n'); + } +} + + + + + + + + /////////////////////////// Cleanup before exit /////////////////////////// + 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; } \ No newline at end of file diff --git a/Exam/IKT203Exam/Portfolio/Assignment-02/option1.h b/Exam/IKT203Exam/Portfolio/Assignment-02/option1.h index f0b36c3..17d88f8 100644 --- a/Exam/IKT203Exam/Portfolio/Assignment-02/option1.h +++ b/Exam/IKT203Exam/Portfolio/Assignment-02/option1.h @@ -4,8 +4,98 @@ #ifndef OPTION1_H #define OPTION1_H +#include "TLinkedList.h" +#include "TPerson.h" + +inline TLinkedList g, e; +inline int guestCount, employCount = 0; + + int RunApp(); +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(); + std::cout << "\n\n\n" << std::endl; +} + +/** + * @brief Callback function to process one name. +static bool NameReadCallback(const int aIndex, const int aTotalCount, const std::string& aFirstName, const std::string& aLastName) +{ + std::cout << "Reading Name " << (aIndex + 1) << " of " << aTotalCount << ": " + << aFirstName << " " << aLastName << "\n"; + + // We only want to read 10 names (index 0 through 9) + // Return false when aIndex is 9 to stop the loop after this one. + return (aIndex < 9); +} +*/ + +// *Inspired* by the provided NameReadCallback given above +static bool onNameRead(const int aIndex, const int aTotalCount, const std::string& aFirstName, const std::string& aLastName) +{ + const ENumStatus status = (aIndex < 1500) ? EMPLOYEE : GUEST; + + const TPerson p(aFirstName, aLastName, status); + + + if (status == EMPLOYEE) { + e.Append(p); + employCount++; + } + else { + g.Append(p); + guestCount++; + } + + std::cout << "[" <= 0 && (targetArray[left]->firstName == target || targetArray[left]->lastName == target)) { + --left; + } + + while (right < arraySize && (targetArray[right]->firstName == target || targetArray[right]->lastName == target)) { + ++right; + } + + for (int i = left + 1; i < right; ++i) { + std::cout << "Match found: \nName: " << targetArray[i]->firstName << " " + << targetArray[i]->lastName << " | status: " << (targetArray[i]->status == 0 ? "Guest" : "Employee") + << " | cabinsize: " << targetArray[i]->cabinSize << "\n" << std::endl; + } +} + + + + + + + #endif // OPTION1_H diff --git a/Exam/IKT203Exam/Portfolio/SharedLib/TLinkedList.cpp b/Exam/IKT203Exam/Portfolio/SharedLib/TLinkedList.cpp index 7c0ca56..050129b 100644 --- a/Exam/IKT203Exam/Portfolio/SharedLib/TLinkedList.cpp +++ b/Exam/IKT203Exam/Portfolio/SharedLib/TLinkedList.cpp @@ -3,12 +3,15 @@ TLinkedList::~TLinkedList() { - const Node* cur = head; + Node* cur = head; while (cur) { - const Node* next = cur->next; + Node* next = cur->next; delete cur; cur = next; } + head = nullptr; + tail = nullptr; + size = 0; } void TLinkedList::Append(const TPerson& person) @@ -92,8 +95,7 @@ TPerson TLinkedList::GetAtIndex(const int index) const { if (index < 0 || index >= size) { std::cout << "Index out of range\n"; - // return dummy - return {"N/A", "N/A", GUEST}; + return {}; } Node* cur = head; @@ -147,6 +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 TLinkedList::Node *TLinkedList::MergeSort(Node *head) { if (head == nullptr || head->next == nullptr) @@ -160,8 +164,6 @@ TLinkedList::Node *TLinkedList::MergeSort(Node *head) front = MergeSort(front); back = MergeSort(back); return MergeList(front, back); - - } void TLinkedList::Sort() @@ -175,13 +177,4 @@ void TLinkedList::Sort() tail = cur; cur = cur->next; } -} - - - - - - - - - +} \ No newline at end of file diff --git a/Exam/IKT203Exam/Portfolio/SharedLib/TPerson.cpp b/Exam/IKT203Exam/Portfolio/SharedLib/TPerson.cpp index 41effea..9a69de8 100644 --- a/Exam/IKT203Exam/Portfolio/SharedLib/TPerson.cpp +++ b/Exam/IKT203Exam/Portfolio/SharedLib/TPerson.cpp @@ -1,14 +1,11 @@ #include "TPerson.h" +#include +#include "Utils.h" - - - - - - - - +TPerson::TPerson() : firstName("N/A"),lastName("N/A"), status(GUEST), cabinSize(Utils::RandomInt(1, 4)) {} + +TPerson::TPerson(std::string f, std::string l, const ENumStatus s) : firstName(std::move(f)), lastName(std::move(l)), status(s), cabinSize(Utils::RandomInt(1, 4)) {} diff --git a/Exam/IKT203Exam/Portfolio/SharedLib/TPerson.h b/Exam/IKT203Exam/Portfolio/SharedLib/TPerson.h index d10d94f..9753fb7 100644 --- a/Exam/IKT203Exam/Portfolio/SharedLib/TPerson.h +++ b/Exam/IKT203Exam/Portfolio/SharedLib/TPerson.h @@ -14,9 +14,10 @@ struct TPerson { std::string firstName; std::string lastName; ENumStatus status; - int cabinSize = Utils::RandomInt(1, 4); + int cabinSize{}; - TPerson(std::string f, std::string l, ENumStatus s) : firstName(std::move(f)), lastName(std::move(l)), status(s){} + TPerson(); + TPerson(std::string , std::string , ENumStatus); ~TPerson() = default; bool operator<(const TPerson& other) const @@ -26,6 +27,7 @@ struct TPerson { // same last name → compare first name return firstName < other.firstName; } + }; diff --git a/Exam/IKT203Exam/Portfolio/SharedLib/Utils.cpp b/Exam/IKT203Exam/Portfolio/SharedLib/Utils.cpp index 9c8d6f8..4b34f75 100644 --- a/Exam/IKT203Exam/Portfolio/SharedLib/Utils.cpp +++ b/Exam/IKT203Exam/Portfolio/SharedLib/Utils.cpp @@ -1,12 +1,11 @@ #include "Utils.h" - +#include "TDoublyLinkedList.h" +#include "TStack.h" +#include "TPerson.h" #include #include #include - -#include "TDoublyLinkedList.h" -#include "TStack.h" - +#include int Utils::Choice() { @@ -15,7 +14,6 @@ int Utils::Choice() int choice; std::cin >> choice; std::cin.ignore(std::numeric_limits::max(), '\n'); - //std::cout << "\n=====================\n"; return choice; } @@ -89,5 +87,78 @@ int Utils::RandomInt(const int min, const int max) if (max <= min) return 0; - return min + rand() % (max - min + 1); // <---- Limited randomness, but again + return min + rand() % (max - min + 1); // <---- Limited randomness, but again } // sufficient for this use case + +bool Utils::CompareLastnames(const TPerson *a, const TPerson *b) +{ + if (a->cabinSize < b->cabinSize) + return true; + if (a->cabinSize > b->cabinSize) + return false; + return a->lastName < b->lastName; +} + + +int Utils::Partition(TPerson **arr, const int startIndex, const int endIndex) +{ + TPerson *pivot = arr[endIndex]; + int i = startIndex - 1; + + for (int j = startIndex; j < endIndex; j++) { + if (CompareLastnames(arr[j], pivot)) { + i++; + std::swap(arr[i], arr[j]); + } + } + + + std::swap(arr[i + 1], arr[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 +void Utils::QuickSort(TPerson** arr, const int low, const int high) +{ + if (low < high) { + int p = Partition(arr, low, high); + QuickSort(arr, low, p - 1); + QuickSort(arr, p + 1, high); + } +} + +/// Time complexity of the binary search is O(log n) +/// However the included fallback search is O(n) +int Utils::BinarySearch(TPerson** arr, int p1, int p2, const std::string &target) +{ + const int origStart = p1; + const int origEnd = p2; + + + while (p1 <= p2) { + const int newP = (p1 + p2) / 2; + std::string currentFirst = arr[newP]->firstName; + std::string currentLast = arr[newP]->lastName; + + if (target == currentFirst || target == currentLast) + return newP; + + if (target > currentLast) + p1 = newP + 1; + + else + 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 + for (int i = origStart; i <= origEnd; i++) { + if (arr[i]->firstName == target) + return i; + } + return -1; +} \ No newline at end of file diff --git a/Exam/IKT203Exam/Portfolio/SharedLib/Utils.h b/Exam/IKT203Exam/Portfolio/SharedLib/Utils.h index fbf115e..febdcae 100644 --- a/Exam/IKT203Exam/Portfolio/SharedLib/Utils.h +++ b/Exam/IKT203Exam/Portfolio/SharedLib/Utils.h @@ -1,8 +1,10 @@ #ifndef UTILS_H #define UTILS_H #include "TDoublyLinkedList.h" +#include "TPerson.h" #include "TStack.h" +struct TPerson; class Utils { public: @@ -11,16 +13,11 @@ class Utils { static void PrintList(const TDoublyLinkedList &document); static int RemoveLine(TDoublyLinkedList &document, TStack &undoStack, TStack &redoStack, int index); static int RandomInt(int, int); - - - - - - - - - - + static int Partition(TPerson** arr, int startIndex, int endIndex); + static void QuickSort(TPerson**, int, int); + static bool CompareLastnames(const TPerson*, const TPerson*); + static int BinarySearch(TPerson**, int, int, const std::string&); + static int CountMatches(TPerson**, int, const std::string&); };