From 848f89a6a40bfd13f48b5aa866743b90baa35b69 Mon Sep 17 00:00:00 2001 From: vylion Date: Sun, 21 Jun 2020 23:36:02 +0200 Subject: [PATCH] BST implementation --- Makefile | 2 +- bst.cpp | 182 ++++++++++++++++++++++++++++++++++++++++++++ bst.h | 37 +++++++++ helpers.h | 1 + main.code-workspace | 62 ++++++++++++++- main.cpp | 59 +++++++++++--- 6 files changed, 330 insertions(+), 13 deletions(-) create mode 100644 bst.cpp create mode 100644 bst.h diff --git a/Makefile b/Makefile index 34365c8..26d2403 100644 --- a/Makefile +++ b/Makefile @@ -358,7 +358,7 @@ OBJ_DIR = obj # Define all object files from source files SRC = $(call rwildcard, *.c, *.h) #OBJS = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) -OBJS ?= main.cpp helpers.cpp +OBJS ?= main.cpp helpers.cpp bst.cpp # For Android platform we call a custom Makefile.Android ifeq ($(PLATFORM),PLATFORM_ANDROID) diff --git a/bst.cpp b/bst.cpp new file mode 100644 index 0000000..67fa750 --- /dev/null +++ b/bst.cpp @@ -0,0 +1,182 @@ +#include "bst.h" + +template +typename BST::node *BST::insert(BST::node *n, const int &key, const T *content, bool &success) +{ + if (n == NULL) + { + n = new BST::node; + n->key = key; + n->content = content; + n->l = NULL; + n->r = NULL; + n->p = NULL; + } + else if (key == n->key) + { + success = false; + return n; + } + else if (key > n->key) + { + n->r = insert(n->r, key, content); + n->r->p = n; + } + else + { + n->l = insert(n->l, key, content); + n->l->p = n; + } + + return n; +} + +template +bool BST::insert(const int &key, const T *content) +{ + bool success = true; + root = insert(root, key, content, success); + return success; +} + +template +typename BST::node *BST::search(const BST::node *n, const int &key) +{ + if (n == NULL) + return NULL; + else if (n->key == key) + { + return n; + } + else if (key > n->key) + { + return search(n->r, key); + } + else + { + return search(n->l, key); + } +} + +template +T *BST::search(const int &key) +{ + node *n = search(root, key); + + if (n == NULL) + return NULL; + + return n->content; +} + +template +typename BST::node *BST::min(BST::node *n) +{ + if (n == NULL) + { + return NULL; + } + else if (n->l == NULL) + { + return n; + } + else + return min(n->l); +} + +template +typename BST::node *BST::max(BST::node *n) +{ + if (n == NULL) + { + return NULL; + } + else if (n->r == NULL) + { + return n; + } + else + return min(n->r); +} + +template +T *BST::min() +{ + node *n = min(root); + if (n == NULL) + { + return NULL; + } + return n->content; +} + +template +T *BST::max() +{ + node *n = max(root); + if (n == NULL) + { + return NULL; + } + return n->content; +} + +template +typename BST::node *BST::succ(BST::node *n) +{ + if (n->r != NULL) + { + return min(n->r); + } + else + { + node *parent = n->p; + node *current = n; + + while (parent != NULL and current == parent->r) + { + current = parent; + parent = current->p; + } + + return parent; + } +} + +template +T *BST::succ(const int &key) +{ + node *n = search(root, key); + + return n == NULL ? NULL : succ(n); +} + +template +typename BST::node *BST::pred(BST::node *n) +{ + if (n->l != NULL) + { + return max(n->l); + } + else + { + node *parent = n->p; + node *current = n; + + while (parent != NULL and current == parent->l) + { + current = parent; + parent = current->p; + } + + return parent; + } +} + +template +T *BST::pred(const int &key) +{ + node *n = search(root, key); + + return n == NULL ? NULL : pred(n); +} diff --git a/bst.h b/bst.h new file mode 100644 index 0000000..ed3cb18 --- /dev/null +++ b/bst.h @@ -0,0 +1,37 @@ +#ifndef BST_H +#define BST_H + +#include +#include "helpers.h" + +template +class BST +{ +private: + struct node + { + int key; + T *content; + node *l; + node *r; + node *p; + }; + node *root = NULL; + node *insert(node *n, const int &key, const T *content, bool &success); + node *search(const node *n, const int &key); + node *min(node *n); + node *max(node *n); + node *succ(node *n); + node *pred(node *n); + +public: + bool insert(const int &key, const T *content); + T *search(const int &key); + T *min(); + T *max(); + T *succ(const int &key); + T *pred(const int &key); + bool remove(const int &key); +}; + +#endif // !BST_H \ No newline at end of file diff --git a/helpers.h b/helpers.h index 695706b..ea9befc 100644 --- a/helpers.h +++ b/helpers.h @@ -1,5 +1,6 @@ #ifndef HELPERS_H +#define HELPERS_H #include #include diff --git a/main.code-workspace b/main.code-workspace index 267248e..21bc7e9 100644 --- a/main.code-workspace +++ b/main.code-workspace @@ -10,7 +10,67 @@ "math.h": "c", "blocks.h": "c", "stdio.h": "c", - "*.m": "c" + "*.m": "c", + "array": "cpp", + "atomic": "cpp", + "hash_map": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "ranges": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp", + "valarray": "cpp" } } } \ No newline at end of file diff --git a/main.cpp b/main.cpp index 29f9705..e41546d 100644 --- a/main.cpp +++ b/main.cpp @@ -10,10 +10,12 @@ #include #include #include +#include #include #include "raylib.h" #include "helpers.h" +#include "bst.h" using time_point = std::chrono::steady_clock::time_point; @@ -25,6 +27,15 @@ struct ColorSegment std::set crossed_by; }; +struct SegmentPoint +{ + Point pos; + uint sid; // Segment ID + bool is_left; + bool is_intersect = false; + uint iid = 0; +}; + void DrawColorSegment(const ColorSegment &cl) { DrawLine(cl.l.first.x, cl.l.first.y, cl.l.second.x, cl.l.second.y, cl.c); @@ -67,14 +78,24 @@ void crossingNaive(std::vector &lines) } } -bool sort_by_x(const ColorSegment &s, const ColorSegment &t) +void crossingSweep(std::vector &lines, const std::vector &points) { - return s.l.first.x < t.l.first.x; -} + struct ComparePoints + { + bool operator()(const SegmentPoint &p, const SegmentPoint &q) + { + return p.pos.x > q.pos.x; + } + }; -void crossingSweep(std::vector &lines) -{ - std::sort(lines.begin(), lines.end(), sort_by_x); + std::priority_queue, ComparePoints> events(points.begin(), points.end(), ComparePoints()); + std::cout << "Queue is size: " << events.size() << std::endl; + BST tree; + + while (!events.empty()) + { + events.pop(); + } } enum States @@ -110,20 +131,35 @@ int main() const int screenHeight = 900; bool close = false; - const int nols = 80; // Number of lines - // Initialize random engine std::random_device rd; std::mt19937_64 gen(rd()); // Delete "_64" in a 32 bit system std::uniform_int_distribution<> distrx(0, screenWidth); std::uniform_int_distribution<> distry(0, screenHeight); + std::uniform_int_distribution<> distrnols(50, 200); std::vector lines, naive_lines, sweep_lines; + std::vector points, sweep_points; + + const int nols = distrnols(gen); // Number of lines // Generate random lines for (uint i = 0; i < nols; ++i) { - LineSegment l = LineSegment{Point{distrx(gen), distry(gen)}, Point{distrx(gen), distry(gen)}}; + Point p, q; + p = Point{distrx(gen), distry(gen)}; + q = Point{distrx(gen), distry(gen)}; + + SegmentPoint sp, sq; + + bool sp_is_left = (p.x < q.x); + sp = SegmentPoint{p, i, sp_is_left}; + sq = SegmentPoint{q, i, !sp_is_left}; + + points.push_back(sp); + points.push_back(sq); + + LineSegment l = LineSegment{p, q}; //std::cout << "(" << l.first.x << "," << l.first.y << ") (" << l.second.x << "," << l.second.y << std::endl; ColorSegment cl = ColorSegment{l, BLACK}; @@ -144,10 +180,11 @@ int main() // Test sweep algorithm time_point begin_sweep = std::chrono::steady_clock::now(); - crossingSweep(sweep_lines); + crossingSweep(sweep_lines, sweep_points); time_point end_sweep = std::chrono::steady_clock::now(); + std::cout << "Experiment " << std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) << " - " << nols << " lines" << std::endl; std::cout << "Naive elapsed time: " << std::chrono::duration_cast(end_naive - begin_naive).count() << " ns" << std::endl; std::cout << "Sweep elapsed time: " << std::chrono::duration_cast(end_sweep - begin_sweep).count() << " ns" << std::endl; @@ -193,7 +230,7 @@ int main() break; } - DrawFPS(10, 10); + //DrawFPS(10, 10); EndDrawing(); //----------------------------------------------------------------------------------