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;
};
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

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(const BinaryTree<T>& tree) { }
~BinaryTree() { destroyTree(root); };
[[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

View File

@ -7,17 +7,17 @@ add_executable(08_team_project main.cpp
utils.h
utils.cpp
BinaryTreeNode.h
BinaryTree.cpp
BinaryTree.h
BinarySearchTree.cpp
BinarySearchTree.h
HashNode.h
HashTable.h
CPU.h
Stack.cpp
CPU.cpp
Stack.h
StackNode.cpp
StackNode.h
fio.h
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 std::ostream &operator<<(std::ostream &os, const CPU &cpu) {
os << "CPU ID: " << cpu.cpuId << std::endl;
return os;
}
friend std::ostream &operator<<(std::ostream &os, const CPU &cpu);
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;
};
friend int key_to_index(const CPU &key, int size) ;
};
std::ostream &operator<<(std::ostream &os, const CPU &cpu);
/*~*~*~*
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>
class DisplayManager {
private:
HashTable* hashTable;
BinarySearchTree* bst;
HashTable<T> hashTable;
BinarySearchTree<std::string> bst;
public:
DisplayManager(HashTable* ht, BinarySearchTree* bst);
DisplayManager(HashTable<T>& ht, BinarySearchTree<std::string>& bst);
~DisplayManager();
void displayAll() 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>
class SearchManager {
private:
HashTable* hashTable;
HashTable<T> hashTable;
public:
SearchManager(HashTable* ht);
~SearchManager();
SearchManager(HashTable<T> &ht);
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>
class UndoManager {
private:
HashTable* hashTable;
BinarySearchTree* bst;
Stack<CPU>* undoStack;
HashTable<T> hashTable;
BinarySearchTree<std::string> bst;
Stack<T> *undoStack;
public:
UndoManager(HashTable* ht, BinarySearchTree* bst);
UndoManager(HashTable<T> &ht, BinarySearchTree<std::string> &bst);
~UndoManager();
void addToUndoStack(const CPU& cpu);
void addToUndoStack(const T &cpu);
void undoDelete();
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 "Stack.h"
#include "fio.h"
#include "UndoManager.h"
#include "DisplayManager.h"
#include "SearchManager.h"
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() {
// Print help table for commands
@ -44,7 +49,11 @@ int main() {
HashTable<CPU> cpuTable;
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 = ' ';
while (command != 'Q') {
@ -53,7 +62,7 @@ int main() {
command = toupper(command, std::locale());
// Temporary try catch block to handle unimplemented commands
try {
processInput(command, cpuTable, cpuTree, undoStack);
processInput(command, cpuTable, cpuTree, undoManager, displayManager, searchManager);
}
catch (std::logic_error &e) {
cout << e.what() << '\n';
@ -68,13 +77,15 @@ int main() {
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) {
case 'H':
printHelp();
@ -83,13 +94,14 @@ void processInput(char command, HashTable<CPU> &cpuTable, BinarySearchTree<strin
handleInsert(cpuTable, cpuTree);
break;
case 'F': // File input: add data from a file
handleFileInput(cpuTable, cpuTree, undoStack);
handleFileInput(cpuTable, cpuTree);
undoManager.clearUndoStack();
break;
case 'D': // Delete one record
deleteCPU(cpuTable, cpuTree, undoStack);
deleteCPU(cpuTable, cpuTree, undoManager);
break;
case 'U': // Undo delete
undoDelete(cpuTable, cpuTree, undoStack);
undoManager.undoDelete();
break;
case 'L': // 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);
}
void handleFileInput(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack) {
void handleFileInput(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree) {
string filename;
cout << "Enter filename: ";
cin >> filename;
int hashSize = findHashSize(filename);
hashTable = HashTable<CPU>(hashSize);
tree = BinarySearchTree<string>();
undoStack = Stack<CPU>();
insertFile(filename, tree, hashTable);
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;
cout << "Enter CPU ID to delete: ";
cin >> cpuId;
@ -147,19 +158,8 @@ void deleteCPU(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<
cpu = CPU(cpuId, 0, 0, "", 0.0);
}
hashTable.remove(cpuFound, cpu, key_to_index);
undoStack.push(cpuFound);
undoManager.addToUndoStack(cpuFound);
tree.remove(cpuId);
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";
}