fix template classes

apparently you can't have template stuff in .cpp files after all, lesson learned.
This commit is contained in:
Iurii Tatishchev 2024-06-17 22:07:55 -07:00
parent 1ef6e3eef4
commit c6243e2314
Signed by: CaZzzer
GPG Key ID: E0EBF441EA424369
16 changed files with 279 additions and 270 deletions

View File

@ -1,63 +0,0 @@
#include "BinarySearchTree.h"
template<typename T>
void BinarySearchTree<T>::insert(const T& newEntry)
{
BinaryTreeNode<T>* newNodePtr = new BinaryTreeNode<T>(newEntry);
this->rootPtr = _insert(this->rootPtr, newNodePtr);
this->count++;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::_insert(BinaryTreeNode<T>* nodePtr, BinaryTreeNode<T>* newNodePtr) {
BinaryTreeNode<T>* pWalk = nodePtr, * parent = nullptr;
if (!nodePtr)
{
nodePtr = newNodePtr;
return nodePtr;
} else {
while (pWalk)
{
parent = pWalk;
if (pWalk->getItem() > newNodePtr->getItem())
pWalk = pWalk->getLeftPtr();
else
pWalk = pWalk->getRightPtr();
}
if (parent->getItem() > newNodePtr->getItem())
parent->setLeftPtr(newNodePtr);
else
parent->setRightPtr(newNodePtr);
}
return nodePtr;
}
template<typename T>
bool BinarySearchTree<T>::search(const T& target, T& returnedItem) const
{
BinarySearchTree<T>* temp = nullptr;
temp = _search(this->rootPtr, target);
if (temp) {
returnedItem = temp->getItem();
return true;
}
return false;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::_search(BinaryTreeNode<T>* nodePtr, const T& target) const
{
BinaryTreeNode<T>* found = nullptr;
if (nodePtr) {
if (target.getCode() == nodePtr->getItem().getCode()) found = nodePtr;
else if (target.getCode() < nodePtr->getItem().getCode()) found = _search(nodePtr->getLeftPtr(), target);
else found = _search(nodePtr->getRightPtr(), target);
}
return found;
}

View File

@ -20,4 +20,66 @@ public:
bool search(const T& target, T& returnedItem) const; bool search(const T& target, T& returnedItem) const;
}; };
template<typename T>
void BinarySearchTree<T>::insert(const T& newEntry)
{
BinaryTreeNode<T>* newNodePtr = new BinaryTreeNode<T>(newEntry);
this->root = _insert(this->root, newNodePtr);
this->size++;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::_insert(BinaryTreeNode<T>* nodePtr, BinaryTreeNode<T>* newNodePtr) {
BinaryTreeNode<T>* pWalk = nodePtr, * parent = nullptr;
if (!nodePtr)
{
nodePtr = newNodePtr;
return nodePtr;
} else {
while (pWalk)
{
parent = pWalk;
if (pWalk->getItem() > newNodePtr->getItem())
pWalk = pWalk->getLeftPtr();
else
pWalk = pWalk->getRightPtr();
}
if (parent->getItem() > newNodePtr->getItem())
parent->setLeftPtr(newNodePtr);
else
parent->setRightPtr(newNodePtr);
}
return nodePtr;
}
template<typename T>
bool BinarySearchTree<T>::search(const T& target, T& returnedItem) const
{
BinaryTreeNode<T>* temp = nullptr;
temp = _search(this->root, target);
if (temp) {
returnedItem = temp->getItem();
return true;
}
return false;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::_search(BinaryTreeNode<T>* nodePtr, const T& target) const
{
BinaryTreeNode<T>* found = nullptr;
if (nodePtr) {
if (target == nodePtr->getItem()) found = nodePtr;
else if (target < nodePtr->getItem()) found = _search(nodePtr->getLeftPtr(), target);
else found = _search(nodePtr->getRightPtr(), target);
}
return found;
}
#endif //INC_08_TEAM_PROJECT_BINARYSEARCHTREE_H #endif //INC_08_TEAM_PROJECT_BINARYSEARCHTREE_H

View File

@ -1,56 +0,0 @@
#include "BinaryTree.h"
template<class T>
void BinaryTree<T>::destroyTree(BinaryTreeNode<T>* nodePtr)
{
if (nodePtr) // != NULL
{
destroyTree(nodePtr->getLeftPtr());
destroyTree(nodePtr->getRightPtr());
delete nodePtr;
}
}
template<typename T>
void BinaryTree<T>::_preorder(void visit(const T&), BinaryTreeNode<T>* nodePtr) const
{
if (nodePtr) {
T item = nodePtr->getItem();
visit(item);
_preorder(visit, nodePtr->getLeftPtr());
_preorder(visit, nodePtr->getRightPtr());
}
}
template<typename T>
void BinaryTree<T>::_inorder(void visit(const T&), BinaryTreeNode<T>* nodePtr) const
{
if (nodePtr) // != NULL
{
T item = nodePtr->getItem();
_inorder(visit, nodePtr->getLeftPtr());
visit(item);
_inorder(visit, nodePtr->getRightPtr());
}
}
template<typename T>
void BinaryTree<T>::_postorder(void visit(const T&), BinaryTreeNode<T>* nodePtr) const
{
if (nodePtr) {
T item = nodePtr->getItem();
_postorder(visit, nodePtr->getLeftPtr());
_postorder(visit, nodePtr->getRightPtr());
visit(item);
}
}
template<typename T>
void BinaryTree<T>::_printindented(void visit(const T&, int), BinaryTreeNode<T>* nodePtr) const {
if (nodePtr) {
T item = nodePtr->getItem();
_printInnerNodes(visit, nodePtr->getLeftPtr());
if (nodePtr->getLeftPtr() || nodePtr->getRightPtr()) visit(item);
_printInnerNodes(visit, nodePtr->getRightPtr());
}
}

View File

@ -13,8 +13,6 @@ public:
BinaryTree() : root(nullptr), size(0) {}; BinaryTree() : root(nullptr), size(0) {};
BinaryTree(const BinaryTree<T>& tree) { }
~BinaryTree() { destroyTree(root); }; ~BinaryTree() { destroyTree(root); };
[[nodiscard]] bool isEmpty() const { return size == 0; }; [[nodiscard]] bool isEmpty() const { return size == 0; };
@ -51,4 +49,59 @@ private:
}; };
template<class T>
void BinaryTree<T>::destroyTree(BinaryTreeNode<T>* nodePtr)
{
if (nodePtr) // != NULL
{
destroyTree(nodePtr->getLeftPtr());
destroyTree(nodePtr->getRightPtr());
delete nodePtr;
}
}
template<typename T>
void BinaryTree<T>::_preorder(void visit(const T&), BinaryTreeNode<T>* nodePtr) const
{
if (nodePtr) {
T item = nodePtr->getItem();
visit(item);
_preorder(visit, nodePtr->getLeftPtr());
_preorder(visit, nodePtr->getRightPtr());
}
}
template<typename T>
void BinaryTree<T>::_inorder(void visit(const T&), BinaryTreeNode<T>* nodePtr) const
{
if (nodePtr) // != NULL
{
T item = nodePtr->getItem();
_inorder(visit, nodePtr->getLeftPtr());
visit(item);
_inorder(visit, nodePtr->getRightPtr());
}
}
template<typename T>
void BinaryTree<T>::_postorder(void visit(const T&), BinaryTreeNode<T>* nodePtr) const
{
if (nodePtr) {
T item = nodePtr->getItem();
_postorder(visit, nodePtr->getLeftPtr());
_postorder(visit, nodePtr->getRightPtr());
visit(item);
}
}
template<typename T>
void BinaryTree<T>::_printindented(void visit(const T&, int), BinaryTreeNode<T>* nodePtr) const {
if (nodePtr) {
T item = nodePtr->getItem();
_printInnerNodes(visit, nodePtr->getLeftPtr());
if (nodePtr->getLeftPtr() || nodePtr->getRightPtr()) visit(item);
_printInnerNodes(visit, nodePtr->getRightPtr());
}
}
#endif //INC_08_TEAM_PROJECT_BINARYTREE_H #endif //INC_08_TEAM_PROJECT_BINARYTREE_H

View File

@ -7,17 +7,17 @@ add_executable(08_team_project main.cpp
utils.h utils.h
utils.cpp utils.cpp
BinaryTreeNode.h BinaryTreeNode.h
BinaryTree.cpp
BinaryTree.h BinaryTree.h
BinarySearchTree.cpp
BinarySearchTree.h BinarySearchTree.h
HashNode.h HashNode.h
HashTable.h HashTable.h
CPU.h CPU.h
Stack.cpp CPU.cpp
Stack.h Stack.h
StackNode.cpp
StackNode.h StackNode.h
fio.h fio.h
fio.cpp fio.cpp
DisplayManager.h
UndoManager.h
SearchManager.h
) )

17
CPU.cpp Normal file
View File

@ -0,0 +1,17 @@
#include <iostream>
#include "CPU.h"
using std::string, std::ostream, std::endl;
ostream &operator<<(ostream &os, const CPU &cpu) {
os << "CPU ID: " << cpu.cpuId << std::endl;
return os;
}
int key_to_index(const CPU &key, int size) {
std::string k = key.getCpuId();
int sum = 0;
for (int i = 0; k[i]; i++)
sum += k[i];
return sum % size;
}

15
CPU.h
View File

@ -59,20 +59,13 @@ public:
friend void iDisplay(const CPU &cpu, int level); friend void iDisplay(const CPU &cpu, int level);
friend std::ostream &operator<<(std::ostream &os, const CPU &cpu) { friend std::ostream &operator<<(std::ostream &os, const CPU &cpu);
os << "CPU ID: " << cpu.cpuId << std::endl;
return os;
}
friend int key_to_index(const CPU &key, int size) { friend int key_to_index(const CPU &key, int size) ;
std::string k = key.getCpuId();
int sum = 0;
for (int i = 0; k[i]; i++)
sum += k[i];
return sum % size;
};
}; };
std::ostream &operator<<(std::ostream &os, const CPU &cpu);
/*~*~*~* /*~*~*~*
Hash function: takes the key and returns the index in the hash table Hash function: takes the key and returns the index in the hash table
*~**/ *~**/

View File

@ -1,29 +0,0 @@
#include "DisplayManager.h"
#include <iostream>
DisplayManager::DisplayManager(HashTable* ht, BinarySearchTree* bst) {
this->hashTable = ht;
this->bst = bst;
}
DisplayManager::~DisplayManager() {
// No dynamic memory allocation, so no cleanup needed
}
void DisplayManager::displayAll() const {
std::cout << "All CPUs in the database:" << std::endl;
// Iterate over the HashTable and display each CPU
for (int i = 0; i < hashTable->getSize(); i++) {
if (hashTable->getItem(i) != nullptr) {
std::cout << *(hashTable->getItem(i)) << std::endl;
}
}
}
void DisplayManager::displayTree() const {
std::cout << "CPU Binary Search Tree:" << std::endl;
// Call the BST's inorder traversal method to display the tree
bst->inorderTraversal();
}

View File

@ -8,15 +8,49 @@
template<typename T> template<typename T>
class DisplayManager { class DisplayManager {
private: private:
HashTable* hashTable; HashTable<T> hashTable;
BinarySearchTree* bst; BinarySearchTree<std::string> bst;
public: public:
DisplayManager(HashTable* ht, BinarySearchTree* bst); DisplayManager(HashTable<T>& ht, BinarySearchTree<std::string>& bst);
~DisplayManager(); ~DisplayManager();
void displayAll() const; void displayAll() const;
void displayTree() const; void displayTree() const;
}; };
#endif template<typename T>
DisplayManager<T>::DisplayManager(HashTable<T> &ht, BinarySearchTree<std::string> &bst) {
this->hashTable = ht;
this->bst = bst;
}
template<typename T>
DisplayManager<T>::~DisplayManager() {
// No dynamic memory allocation, so no cleanup needed
}
template<typename T>
void DisplayManager<T>::displayAll() const {
std::cout << "All CPUs in the database:" << std::endl;
// Iterate over the HashTable and display each CPU
for (int i = 0; i < hashTable.getSize(); i++) {
if (hashTable.getItem(i) != nullptr) {
std::cout << *(hashTable.getItem(i)) << std::endl;
}
}
}
template<typename T>
void DisplayManager<T>::displayTree() const {
std::cout << "CPU Binary Search Tree:" << std::endl;
// Call the BST's inorder traversal method to display the tree
// TODO: Use a proper display function
bst.inOrder([](const std::string& key) {
std::cout << key << std::endl;
});
}
#endif

View File

@ -1,27 +0,0 @@
#include "SearchManager.h"
#include <iostream>
#include <string>
SearchManager::SearchManager(HashTable* ht) {
this->hashTable = ht;
}
SearchManager::~SearchManager() {
// No dynamic memory allocation, so no cleanup needed
}
void SearchManager::searchCPU() const {
std::string cpuID;
std::cout << "Enter the CPU ID to search: ";
std::cin >> cpuID;
// Search for the CPU in the HashTable
CPU* foundCPU = hashTable->search(cpuID);
if (foundCPU != nullptr) {
std::cout << "CPU found:" << std::endl;
std::cout << *foundCPU << std::endl;
} else {
std::cout << "CPU not found." << std::endl;
}
}

View File

@ -7,13 +7,34 @@
template<typename T> template<typename T>
class SearchManager { class SearchManager {
private: private:
HashTable* hashTable; HashTable<T> hashTable;
public: public:
SearchManager(HashTable* ht); SearchManager(HashTable<T> &ht);
~SearchManager();
void searchCPU() const; void searchCPU() const;
}; };
#endif template<typename T>
SearchManager<T>::SearchManager(HashTable<T> &ht) {
this->hashTable = ht;
}
template<typename T>
void SearchManager<T>::searchCPU() const {
std::string cpuID;
std::cout << "Enter the CPU ID to search: ";
std::cin >> cpuID;
// Search for the CPU in the HashTable
CPU *foundCPU = hashTable.search(cpuID);
if (foundCPU != nullptr) {
std::cout << "CPU found:" << std::endl;
std::cout << *foundCPU << std::endl;
} else {
std::cout << "CPU not found." << std::endl;
}
}
#endif

View File

@ -1 +0,0 @@
#include "Stack.h"

View File

@ -1 +0,0 @@
#include "StackNode.h"

View File

@ -1,37 +0,0 @@
#include "UndoManager.h"
#include <iostream>
UndoManager::UndoManager(HashTable* ht, BinarySearchTree* bst) {
this->hashTable = ht;
this->bst = bst;
this->undoStack = new Stack<CPU>();
}
UndoManager::~UndoManager() {
delete undoStack;
}
void UndoManager::addToUndoStack(const CPU& cpu) {
undoStack->push(cpu);
}
void UndoManager::undoDelete() {
if (!undoStack->isEmpty()) {
CPU lastDeleted = undoStack->pop();
// Reinsert the CPU into the HashTable and BST
hashTable->insert(lastDeleted);
bst->insert(lastDeleted);
std::cout << "Undo successful. CPU reinserted:" << std::endl;
std::cout << lastDeleted << std::endl;
} else {
std::cout << "No deletions to undo." << std::endl;
}
}
void UndoManager::clearUndoStack() {
while (!undoStack->isEmpty()) {
undoStack->pop();
}
}

View File

@ -9,17 +9,60 @@
template<typename T> template<typename T>
class UndoManager { class UndoManager {
private: private:
HashTable* hashTable; HashTable<T> hashTable;
BinarySearchTree* bst; BinarySearchTree<std::string> bst;
Stack<CPU>* undoStack; Stack<T> *undoStack;
public: public:
UndoManager(HashTable* ht, BinarySearchTree* bst); UndoManager(HashTable<T> &ht, BinarySearchTree<std::string> &bst);
~UndoManager(); ~UndoManager();
void addToUndoStack(const CPU& cpu); void addToUndoStack(const T &cpu);
void undoDelete(); void undoDelete();
void clearUndoStack(); void clearUndoStack();
}; };
#endif template<typename T>
UndoManager<T>::UndoManager(HashTable<T> &ht, BinarySearchTree<std::string> &bst) {
this->hashTable = ht;
this->bst = bst;
this->undoStack = new Stack<CPU>();
}
template<typename T>
UndoManager<T>::~UndoManager() {
delete undoStack;
}
template<typename T>
void UndoManager<T>::addToUndoStack(const T &cpu) {
undoStack->push(cpu);
}
template<typename T>
void UndoManager<T>::undoDelete() {
if (!undoStack->isEmpty()) {
T lastDeleted = undoStack->pop();
// Reinsert the CPU into the HashTable and BST
hashTable.insert(lastDeleted, key_to_index);
bst.insert(lastDeleted.getCpuId());
std::cout << "Undo successful. CPU reinserted:" << std::endl;
std::cout << lastDeleted << std::endl;
} else {
std::cout << "No deletions to undo." << std::endl;
}
}
template<typename T>
void UndoManager<T>::clearUndoStack() {
while (!undoStack->isEmpty()) {
undoStack->pop();
}
}
#endif

View File

@ -33,10 +33,15 @@
#include "BinarySearchTree.h" #include "BinarySearchTree.h"
#include "Stack.h" #include "Stack.h"
#include "fio.h" #include "fio.h"
#include "UndoManager.h"
#include "DisplayManager.h"
#include "SearchManager.h"
using std::cin, std::cout, std::string, std::vector; using std::cin, std::cout, std::string, std::vector;
void processInput(char command, HashTable<CPU> &table, BinarySearchTree<string> &tree, Stack<CPU> &stack); void processInput(char command, HashTable<CPU> &table, BinarySearchTree<string> &tree,
UndoManager<CPU> &undoManager, DisplayManager<CPU> &displayManager,
SearchManager<CPU> &searchManager);
int main() { int main() {
// Print help table for commands // Print help table for commands
@ -44,7 +49,11 @@ int main() {
HashTable<CPU> cpuTable; HashTable<CPU> cpuTable;
BinarySearchTree<string> cpuTree; BinarySearchTree<string> cpuTree;
Stack<CPU> undoStack; // Stack<CPU> undoStack;
DisplayManager<CPU> displayManager(cpuTable, cpuTree);
SearchManager<CPU> searchManager(cpuTable);
UndoManager<CPU> undoManager(cpuTable, cpuTree);
char command = ' '; char command = ' ';
while (command != 'Q') { while (command != 'Q') {
@ -53,7 +62,7 @@ int main() {
command = toupper(command, std::locale()); command = toupper(command, std::locale());
// Temporary try catch block to handle unimplemented commands // Temporary try catch block to handle unimplemented commands
try { try {
processInput(command, cpuTable, cpuTree, undoStack); processInput(command, cpuTable, cpuTree, undoManager, displayManager, searchManager);
} }
catch (std::logic_error &e) { catch (std::logic_error &e) {
cout << e.what() << '\n'; cout << e.what() << '\n';
@ -68,13 +77,15 @@ int main() {
void handleInsert(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree); void handleInsert(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree);
void handleFileInput(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack); void handleFileInput(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree);
void deleteCPU(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack); void deleteCPU(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, UndoManager<CPU> &undoManager);
void undoDelete(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack); // void undoDelete(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, UndoManager<CPU> &undoManager);
void processInput(char command, HashTable<CPU> &cpuTable, BinarySearchTree<string> &cpuTree, Stack<CPU> &undoStack) { void processInput(char command, HashTable<CPU> &cpuTable, BinarySearchTree<string> &cpuTree,
UndoManager<CPU> &undoManager, DisplayManager<CPU> &displayManager,
SearchManager<CPU> &searchManager) {
switch (command) { switch (command) {
case 'H': case 'H':
printHelp(); printHelp();
@ -83,13 +94,14 @@ void processInput(char command, HashTable<CPU> &cpuTable, BinarySearchTree<strin
handleInsert(cpuTable, cpuTree); handleInsert(cpuTable, cpuTree);
break; break;
case 'F': // File input: add data from a file case 'F': // File input: add data from a file
handleFileInput(cpuTable, cpuTree, undoStack); handleFileInput(cpuTable, cpuTree);
undoManager.clearUndoStack();
break; break;
case 'D': // Delete one record case 'D': // Delete one record
deleteCPU(cpuTable, cpuTree, undoStack); deleteCPU(cpuTable, cpuTree, undoManager);
break; break;
case 'U': // Undo delete case 'U': // Undo delete
undoDelete(cpuTable, cpuTree, undoStack); undoManager.undoDelete();
break; break;
case 'L': // List all CPUs sorted by primary key case 'L': // List all CPUs sorted by primary key
throw std::logic_error("Not yet implemented: List all CPUs sorted by primary key"); throw std::logic_error("Not yet implemented: List all CPUs sorted by primary key");
@ -122,20 +134,19 @@ void handleInsert(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree) {
insertCPU(tree, hashTable); insertCPU(tree, hashTable);
} }
void handleFileInput(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack) { void handleFileInput(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree) {
string filename; string filename;
cout << "Enter filename: "; cout << "Enter filename: ";
cin >> filename; cin >> filename;
int hashSize = findHashSize(filename); int hashSize = findHashSize(filename);
hashTable = HashTable<CPU>(hashSize); hashTable = HashTable<CPU>(hashSize);
tree = BinarySearchTree<string>(); tree = BinarySearchTree<string>();
undoStack = Stack<CPU>();
insertFile(filename, tree, hashTable); insertFile(filename, tree, hashTable);
cout << "Data from file \"" << filename << "\" added.\n"; cout << "Data from file \"" << filename << "\" added.\n";
} }
void deleteCPU(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack) { void deleteCPU(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, UndoManager<CPU> &undoManager) {
string cpuId; string cpuId;
cout << "Enter CPU ID to delete: "; cout << "Enter CPU ID to delete: ";
cin >> cpuId; cin >> cpuId;
@ -147,19 +158,8 @@ void deleteCPU(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<
cpu = CPU(cpuId, 0, 0, "", 0.0); cpu = CPU(cpuId, 0, 0, "", 0.0);
} }
hashTable.remove(cpuFound, cpu, key_to_index); hashTable.remove(cpuFound, cpu, key_to_index);
undoStack.push(cpuFound); undoManager.addToUndoStack(cpuFound);
tree.remove(cpuId); tree.remove(cpuId);
cout << "CPU ID \"" << cpuId << "\" deleted.\n"; cout << "CPU ID \"" << cpuId << "\" deleted.\n";
} }
void undoDelete(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack) {
if (undoStack.isEmpty()) {
cout << "No deletions to undo.\n";
return;
}
CPU cpu = undoStack.pop();
hashTable.insert(cpu, key_to_index);
tree.insert(cpu.getCpuId());
cout << "Undo deletion of CPU ID \"" << cpu.getCpuId() << "\".\n";
}