diff --git a/QVectorSearch/mainwindow.cpp b/QVectorSearch/mainwindow.cpp index 9d9652f..c37b2a6 100644 --- a/QVectorSearch/mainwindow.cpp +++ b/QVectorSearch/mainwindow.cpp @@ -5,11 +5,10 @@ #include "linear_finder.h" #include "parallel_finder.h" #include "timer.h" -#include "tree_finder.h" #include "word_list_generator.h" -#include #include +#include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { @@ -27,7 +26,6 @@ MainWindow::~MainWindow() { delete ui; } void MainWindow::setupAlgorithmSelector() { search_algorithms_.appendRow(new QStandardItem("Linear search")); search_algorithms_.appendRow(new QStandardItem("Parallel search")); - search_algorithms_.appendRow(new QStandardItem("Tree search")); } void MainWindow::generateWordList() { @@ -38,6 +36,13 @@ void MainWindow::generateWordList() { std::stringstream status_message; status_message << "generated " << word_list_.size() << " words in " << timer; ui->mainStatusBar->showMessage(QString::fromStdString(status_message.str())); + + QStringList words; + for (const auto &word : word_list_) { + words.append(QString::fromStdString(word)); + } + + result_model_.setStringList(words); } void MainWindow::search(const QString &search_term) { @@ -48,37 +53,32 @@ void MainWindow::search(const QString &search_term) { } Timer timer; - const auto results = finder_->find_prefix(search_term.toStdString()); + const auto finder = createSelectedFinder(); + const auto results = finder->find_prefix(search_term.toStdString()); timer.stop(); std::stringstream status_message; - status_message << "search took " << timer << ", found " - << std::distance(results.begin(), results.end()) << " results"; + status_message << "search took " << timer << ", found " << results.size() + << " results"; ui->mainStatusBar->showMessage(QString::fromStdString(status_message.str())); showResults(results); } -void MainWindow::createSelectedFinder() { +std::unique_ptr MainWindow::createSelectedFinder() const { auto selectedFinder = ui->searchAlgorithmSelector->currentIndex(); switch (selectedFinder) { case 0: default: - finder_ = std::make_unique(word_list_); - break; + return std::make_unique(word_list_); case 1: - finder_ = std::make_unique( + return std::make_unique( word_list_, std::thread::hardware_concurrency()); - break; - case 2: - finder_ = std::make_unique(word_list_); - break; } } -void MainWindow::showResults( - const std::forward_list &results) { +void MainWindow::showResults(const std::vector &results) { QStringList ui_results; for (auto word : results) { ui_results.append(QString::fromStdString(*word)); @@ -92,6 +92,5 @@ void MainWindow::on_searchInput_textChanged(const QString &search_term) { } void MainWindow::on_searchAlgorithmSelector_currentIndexChanged(int) { - createSelectedFinder(); search(ui->searchInput->displayText()); } diff --git a/QVectorSearch/mainwindow.h b/QVectorSearch/mainwindow.h index 0a38215..15ea3f8 100644 --- a/QVectorSearch/mainwindow.h +++ b/QVectorSearch/mainwindow.h @@ -19,7 +19,6 @@ private: std::vector word_list_; QStringListModel result_model_; QStandardItemModel search_algorithms_; - std::unique_ptr finder_; public: MainWindow(QWidget *parent = nullptr); @@ -29,8 +28,8 @@ private: void setupAlgorithmSelector(); void generateWordList(); void search(const QString &search_term); - void createSelectedFinder(); - void showResults(const std::forward_list &results); + std::unique_ptr createSelectedFinder() const; + void showResults(const std::vector &results); private slots: void on_searchInput_textChanged(const QString &search_term); diff --git a/lib_vector_search/CMakeLists.txt b/lib_vector_search/CMakeLists.txt index 6c00ac7..edb6b42 100644 --- a/lib_vector_search/CMakeLists.txt +++ b/lib_vector_search/CMakeLists.txt @@ -5,18 +5,8 @@ project( VERSION 0.1.0 LANGUAGES CXX) -add_library( - vector_search STATIC - src/word_list_generator.cpp - include/word_list_generator.h - src/timer.cpp - include/timer.h - src/linear_finder.cpp - include/linear_finder.h - src/parallel_finder.cpp - include/parallel_finder.h - src/tree_finder.cpp - include/tree_finder.h) +add_library(vector_search STATIC src/word_list_generator.cpp src/timer.cpp + src/linear_finder.cpp src/parallel_finder.cpp) target_include_directories(vector_search PUBLIC ${PROJECT_SOURCE_DIR}/include) diff --git a/lib_vector_search/include/finder.h b/lib_vector_search/include/finder.h index 1266392..9543adf 100644 --- a/lib_vector_search/include/finder.h +++ b/lib_vector_search/include/finder.h @@ -1,14 +1,12 @@ #pragma once -#include #include +#include -using std::string, std::string_view, std::forward_list; +using std::string, std::string_view, std::vector; class Finder { public: virtual ~Finder() = default; - - virtual forward_list - find_prefix(string_view search_term) const = 0; + virtual vector find_prefix(string_view search_term) const = 0; }; diff --git a/lib_vector_search/include/linear_finder.h b/lib_vector_search/include/linear_finder.h index 646c248..e9f3419 100644 --- a/lib_vector_search/include/linear_finder.h +++ b/lib_vector_search/include/linear_finder.h @@ -2,16 +2,11 @@ #include "finder.h" -#include - -using std::vector; - class LinearFinder : public Finder { private: const vector &word_list_; public: LinearFinder(const vector &word_list); - forward_list - find_prefix(string_view search_term) const override; + vector find_prefix(string_view search_term) const override; }; diff --git a/lib_vector_search/include/parallel_finder.h b/lib_vector_search/include/parallel_finder.h index 7226e0c..556a167 100644 --- a/lib_vector_search/include/parallel_finder.h +++ b/lib_vector_search/include/parallel_finder.h @@ -2,16 +2,12 @@ #include "finder.h" -#include - class ParallelFinder : public Finder { private: const size_t thread_count_; - const std::vector &word_list_; + const vector &word_list_; public: - ParallelFinder(const std::vector &word_list, size_t thread_count); - - std::forward_list - find_prefix(std::string_view search_term) const override; + ParallelFinder(const vector &word_list, size_t thread_count); + vector find_prefix(string_view search_term) const override; }; diff --git a/lib_vector_search/include/tree_finder.h b/lib_vector_search/include/tree_finder.h deleted file mode 100644 index 6117573..0000000 --- a/lib_vector_search/include/tree_finder.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include "finder.h" - -#include -#include - -class SearchTreeNode { -private: - std::forward_list words_; - std::map children_; - -public: - void insert(std::string_view partial_word, const string *original_word); - const SearchTreeNode *find(std::string_view search_term) const; - - std::forward_list words() const; -}; - -class SearchTree : public SearchTreeNode { -public: - SearchTree(const std::vector &word_list); -}; - -class TreeFinder : public Finder { -private: - SearchTree search_tree_; - -public: - TreeFinder(const std::vector &word_list); - - virtual std::forward_list - find_prefix(std::string_view search_term) const override; -}; diff --git a/lib_vector_search/src/linear_finder.cpp b/lib_vector_search/src/linear_finder.cpp index 0c4705e..f6c76c1 100644 --- a/lib_vector_search/src/linear_finder.cpp +++ b/lib_vector_search/src/linear_finder.cpp @@ -3,13 +3,13 @@ LinearFinder::LinearFinder(const vector &word_list) : word_list_(word_list) {} -forward_list +vector LinearFinder::find_prefix(string_view search_term) const { - forward_list matching_words; + vector matching_words; for (const auto ¤t_word : word_list_) { if (current_word.starts_with(search_term)) { - matching_words.push_front(¤t_word); + matching_words.push_back(¤t_word); } } diff --git a/lib_vector_search/src/parallel_finder.cpp b/lib_vector_search/src/parallel_finder.cpp index 1ea4676..d83b97a 100644 --- a/lib_vector_search/src/parallel_finder.cpp +++ b/lib_vector_search/src/parallel_finder.cpp @@ -3,15 +3,15 @@ #include #include -using std::mutex, std::thread, std::lock_guard, std::vector, std::forward_list; +using std::mutex, std::thread, std::lock_guard; ParallelFinder::ParallelFinder(const vector &word_list, size_t thread_count) : word_list_(word_list), thread_count_(thread_count) {} -forward_list +vector ParallelFinder::find_prefix(string_view search_term) const { - forward_list result; + vector result; mutex result_mutex; vector threads; @@ -25,19 +25,15 @@ ParallelFinder::find_prefix(string_view search_term) const { threads.emplace_back( [](const vector &word_list, const string_view &search_term, - forward_list &result, size_t start_index, - size_t end_index, mutex &result_mutex) { - forward_list thread_results; + vector &result, size_t start_index, size_t end_index, + mutex &result_mutex) { for (size_t index = start_index; index < end_index; ++index) { const auto ¤t_word = word_list[index]; if (current_word.starts_with(search_term)) { - thread_results.push_front(¤t_word); + const lock_guard lock(result_mutex); + result.push_back(¤t_word); } } - if (!thread_results.empty()) { - const lock_guard lock(result_mutex); - result.merge(thread_results); - } }, cref(word_list_), cref(search_term), ref(result), first_word_index, last_word_index, ref(result_mutex)); diff --git a/lib_vector_search/src/tree_finder.cpp b/lib_vector_search/src/tree_finder.cpp deleted file mode 100644 index 9b94682..0000000 --- a/lib_vector_search/src/tree_finder.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "tree_finder.h" - -void SearchTreeNode::insert(std::string_view partial_word, - const string *original_word) { - if (partial_word.empty()) { - words_.push_front(original_word); - } else { - children_[partial_word.front()].insert( - std::string_view(partial_word).substr(1, partial_word.length()), - original_word); - } -} - -const SearchTreeNode *SearchTreeNode::find(std::string_view search_term) const { - if (search_term.empty()) { - return this; - } - - auto child = children_.find(search_term.front()); - if (child != children_.cend()) { - return child->second.find(search_term.substr(1, search_term.length())); - } - - return nullptr; -} - -std::forward_list SearchTreeNode::words() const { - std::forward_list results(words_); - for (const auto &child : children_) { - results.merge(child.second.words()); - } - - return results; -}; - -SearchTree::SearchTree(const std::vector &word_list) { - for (const auto &word : word_list) { - insert(std::string_view(word), &word); - } -} - -TreeFinder::TreeFinder(const std::vector &word_list) - : search_tree_(word_list) {} - -std::forward_list -TreeFinder::find_prefix(std::string_view search_term) const { - const auto *result_node = search_tree_.find(search_term); - if (result_node == nullptr) { - return {}; - } - - return result_node->words(); -} diff --git a/vector_search_cli/main.cpp b/vector_search_cli/main.cpp index 0d31e5b..ace12f7 100644 --- a/vector_search_cli/main.cpp +++ b/vector_search_cli/main.cpp @@ -1,7 +1,6 @@ #include "linear_finder.h" #include "parallel_finder.h" #include "timer.h" -#include "tree_finder.h" #include "word_list_generator.h" #include @@ -27,15 +26,16 @@ vector generate_word_list() { void test_linear_finder(const vector &word_list) { cout << "\nrunning linear finder" << endl; + Timer constructor_timer; LinearFinder linear_finder(word_list); + constructor_timer.stop(); Timer find_timer; auto result = linear_finder.find_prefix("ABCD"); find_timer.stop(); cout << "linear finder took " << find_timer << endl; - cout << "result list is " << std::distance(result.cbegin(), result.cend()) - << " element(s) long" << endl; + cout << "result list is " << result.size() << " element(s) long" << endl; } void test_parallel_finder(const vector &word_list) { @@ -45,33 +45,16 @@ void test_parallel_finder(const vector &word_list) { cout << "using " << thread_count << " threads" << endl; + Timer constructor_timer; ParallelFinder parallel_finder(word_list, thread_count); + constructor_timer.stop(); Timer find_timer; auto result = parallel_finder.find_prefix("ABCD"); find_timer.stop(); cout << "parallel finder took " << find_timer << endl; - cout << "result list is " << std::distance(result.cbegin(), result.cend()) - << " element(s) long" << endl; -} - -void test_tree_finder(const vector &word_list) { - cout << "\nrunning tree finder" << endl; - - Timer constructor_timer; - TreeFinder tree_finder(word_list); - constructor_timer.stop(); - - cout << "tree finder constructor took " << constructor_timer << endl; - - Timer find_timer; - auto result = tree_finder.find_prefix("ABCD"); - find_timer.stop(); - - cout << "tree finder took " << find_timer << endl; - cout << "result list is " << std::distance(result.cbegin(), result.cend()) - << " element(s) long" << endl; + cout << "result list is " << result.size() << " element(s) long" << endl; } int main(int argc, char *argv[]) { @@ -81,7 +64,6 @@ int main(int argc, char *argv[]) { test_linear_finder(word_list); test_parallel_finder(word_list); - test_tree_finder(word_list); return EXIT_SUCCESS; }