diff --git a/Lab2/.gitignore b/Lab2/.gitignore index 7bce85c..aca22fe 100644 --- a/Lab2/.gitignore +++ b/Lab2/.gitignore @@ -1,2 +1,3 @@ -/dist -benchmarks +benchmark +results.csv +charts/ diff --git a/Lab2/benchmark.cpp b/Lab2/benchmark.cpp index cbff6d2..c25bccd 100644 --- a/Lab2/benchmark.cpp +++ b/Lab2/benchmark.cpp @@ -1,16 +1,61 @@ #include "bst/bst.h" #include "list/list.h" +#include #include #include #include #include -void measureBST(std::set *sequence){ - int buildTime = 0, searchTime = 0, deleteTime = 0; +void measureList(std::set *sequence, FILE *file){ + float buildTime = 0, searchTime = 0, deleteTime = 0; for (int i = 0; i < 10; i++) { - std::cout << "- Running test " << i + 1 << "/10\r"; + std::cout << "- Running list " << i + 1 << "/10\r"; + fflush(stdout); + + // Measure build time + auto start = std::chrono::high_resolution_clock::now(); + List *head = nullptr; + for (int value : *sequence) { + head = insert(head, value); + } + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + buildTime += elapsed_seconds.count() * 1000; // Convert to milliseconds + + // Now we run the search + start = std::chrono::high_resolution_clock::now(); + for (int value : *sequence) { + search(head, value); + } + end = std::chrono::high_resolution_clock::now(); + elapsed_seconds = end - start; + searchTime += elapsed_seconds.count() * 1000; // Convert to milliseconds + + // Measure deletion time for list + start = std::chrono::high_resolution_clock::now(); + while(head != nullptr){ + head = remove(head); + } + end = std::chrono::high_resolution_clock::now(); + elapsed_seconds = end - start; + deleteTime += elapsed_seconds.count() * 1000; // Convert to milliseconds + } + + buildTime /= 10; + searchTime /= 10; + deleteTime /= 10; + + std::cout << "- List built in " << buildTime << "ms | searched in " << searchTime << "ms | deleted in " << deleteTime << "ms" << std::endl; + fprintf(file, "List,%f,%f,%f\n", buildTime, searchTime, deleteTime); +} + +void measureBST(std::set *sequence, FILE *file){ + float buildTime = 0, searchTime = 0, deleteTime = 0; + + for (int i = 0; i < 10; i++) { + std::cout << "- Running bst " << i + 1 << "/10\r"; fflush(stdout); // Measure build time @@ -19,11 +64,13 @@ void measureBST(std::set *sequence){ for (int value : *sequence) { root = insert(root, value); } + root = balance(root); auto end = std::chrono::high_resolution_clock::now(); std::chrono::duration elapsed_seconds = end - start; buildTime += elapsed_seconds.count() * 1000; // Convert to milliseconds // Now we run the search + start = std::chrono::high_resolution_clock::now(); for (int value : *sequence) { search(root, value); } @@ -33,7 +80,7 @@ void measureBST(std::set *sequence){ // Measure deletion time for tree start = std::chrono::high_resolution_clock::now(); - freeTree(root); + deleteTree(root); end = std::chrono::high_resolution_clock::now(); elapsed_seconds = end - start; deleteTime += elapsed_seconds.count() * 1000; // Convert to milliseconds @@ -43,9 +90,8 @@ void measureBST(std::set *sequence){ searchTime /= 10; deleteTime /= 10; - std::cout << "- Tree built in " << buildTime << "ms" << std::endl; - std::cout << "- Tree searched in " << searchTime << "ms" << std::endl; - std::cout << "- Tree deleted in " << deleteTime << "ms" << std::endl; + std::cout << "- Tree built in " << buildTime << "ms | searched in " << searchTime << "ms | deleted in " << deleteTime << "ms" << std::endl; + fprintf(file, "BST,%f,%f,%f\n", buildTime, searchTime, deleteTime); } int main() { @@ -54,19 +100,25 @@ int main() { std::mt19937 gen(rd()); std::uniform_int_distribution<> dis(1, 1000000); - for (int n = 1; n < 16; n++) { + // Open a file for writing results + FILE *file = fopen("results.csv", "w"); + fprintf(file, "Elements,Structure,BuildTime,SearchTime,DeleteTime\n"); + + for (int n = 1; n < 26; n++) { std::set sequence; while (sequence.size() < n * 1000) { sequence.insert(dis(gen)); } - // Display this like a cascade std::cout << "Running tests for " << n * 1000 << " elements..." << std::endl; - measureBST(&sequence); + measureList(&sequence, file); + measureBST(&sequence, file); } + fclose(file); + return 0; } diff --git a/Lab2/bst/bst.cpp b/Lab2/bst/bst.cpp index e78567f..4431b44 100644 --- a/Lab2/bst/bst.cpp +++ b/Lab2/bst/bst.cpp @@ -24,10 +24,37 @@ Tree *search(Tree *root, int value) { return nullptr; } -void freeTree(Tree *root) { +void traverseInOrder(Tree *root, std::vector *vec) { if (root != nullptr) { - freeTree(root->left); - freeTree(root->right); + traverseInOrder(root->left, vec); + vec->push_back(root->info); + traverseInOrder(root->right, vec); + } +} + +Tree *rebuild(std::vector *vec, int start, int end) { + if (start > end) + return nullptr; + + int mid = (start + end) / 2; + Tree *node = new Tree(); + node->info = vec->at(mid); + node->left = rebuild(vec, start, mid - 1); + node->right = rebuild(vec, mid + 1, end); + + return node; +} + +Tree *balance(Tree *root) { + std::vector vec; + traverseInOrder(root, &vec); + return rebuild(&vec, 0, vec.size() - 1); +} + +void deleteTree(Tree *root) { + if (root != nullptr) { + deleteTree(root->left); + deleteTree(root->right); delete root; } } diff --git a/Lab2/bst/bst.h b/Lab2/bst/bst.h index 8a29641..4c5e56a 100644 --- a/Lab2/bst/bst.h +++ b/Lab2/bst/bst.h @@ -1,3 +1,5 @@ +#include + struct Tree { int info; Tree *left; @@ -6,4 +8,7 @@ struct Tree { Tree *insert(Tree *root, int value); Tree *search(Tree *root, int value); -void freeTree(Tree *root); +void traverseInOrder(Tree *root,std::vector &vec); +Tree *rebuild(std::vector *vec, int start, int end); +Tree *balance(Tree *root); +void deleteTree(Tree *root); diff --git a/Lab2/list/list.cpp b/Lab2/list/list.cpp index 225b9b2..bc237ac 100644 --- a/Lab2/list/list.cpp +++ b/Lab2/list/list.cpp @@ -1,25 +1,26 @@ #include "list.h" +#include -List *insert(List *head, int data) { +List *insert(List *head, int value) { if (head == nullptr) { List *node = new List(); - node->data = data; + node->data = value; node->next = nullptr; return node; } - if (head->data > data) { + if (head->data > value) { List *newHead = new List(); - newHead->data = data; + newHead->data = value; newHead->next = head; head = newHead; } else { List *tmp = head; - while (tmp->next != nullptr && tmp->data < data) { - tmp = head->next; + while (tmp->next != nullptr && tmp->data < value) { + tmp = tmp->next; } List *tail = new List(); - tail->data = data; + tail->data = value; // Set the pointer to the next, we don't know if its at the end or not tail->next = tmp->next; tmp->next = tail; @@ -27,3 +28,28 @@ List *insert(List *head, int data) { return head; } + +List *search(List *list, int value) { + List *ptr = list; + while (ptr != nullptr && ptr->data != value) { + ptr = ptr->next; + } + + if (ptr->data == value) { + return ptr; + } + + return nullptr; +} + + + +// Remove the first element +List *remove(List *head) { + if (head == nullptr) { + return nullptr; + } + List *newHead = head->next; + delete head; + return newHead; +} diff --git a/Lab2/list/list.h b/Lab2/list/list.h index 4db1a3a..86c732d 100644 --- a/Lab2/list/list.h +++ b/Lab2/list/list.h @@ -4,3 +4,5 @@ struct List { }; List *insert(List *head, int data); +List *search(List *list, int value); +List* remove(List *head); diff --git a/Lab2/plot.py b/Lab2/plot.py index e69de29..493df3c 100644 --- a/Lab2/plot.py +++ b/Lab2/plot.py @@ -0,0 +1,47 @@ +import matplotlib.pyplot as plt + +def plot(header:str, first:list[int], second:list[int], log=False): + plt.figure(figsize=(10, 6)) + plt.plot(range(1000,25001,1000), first, label="Lista") + plt.plot(range(1000,25001,1000), second, label="Drzewo BST") + plt.xlabel("Rozmiar tablicy") + plt.ylabel("Czas (ms)") + if log: + plt.yscale('log', base=2) + plt.title(header) + plt.legend() + plt.savefig(f"./charts/{header}.png") + +if __name__ == "__main__": + with open('results.csv', 'r') as file: + data = file.read() + lines = data.split('\n') + headers = lines[0].split(',') + values = [line.split(',') for line in lines[1:]] + + bstTimes = { + "build":[], + "search":[], + "delete":[] + } + + listTimes = { + "build":[], + "search":[], + "delete":[] + } + + for row in values: + if row[0] == 'BST': + bstTimes['build'].append(float(row[1])) + bstTimes['search'].append(float(row[2])) + bstTimes['delete'].append(float(row[3])) + elif row[0] == 'List': + listTimes['build'].append(float(row[1])) + listTimes['search'].append(float(row[2])) + listTimes['delete'].append(float(row[3])) + + + plot("Tworzenie", listTimes['build'], bstTimes['build']) + plot("Wyszukiwanie", listTimes['search'], bstTimes['search'], log=True) + plot("Usuwanie", listTimes['delete'], bstTimes['delete'])