BST implementation

This commit is contained in:
vylion 2020-06-21 23:36:02 +02:00
parent 8418010c1e
commit 848f89a6a4
6 changed files with 330 additions and 13 deletions

View file

@ -358,7 +358,7 @@ OBJ_DIR = obj
# Define all object files from source files # Define all object files from source files
SRC = $(call rwildcard, *.c, *.h) SRC = $(call rwildcard, *.c, *.h)
#OBJS = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) #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 # For Android platform we call a custom Makefile.Android
ifeq ($(PLATFORM),PLATFORM_ANDROID) ifeq ($(PLATFORM),PLATFORM_ANDROID)

182
bst.cpp Normal file
View file

@ -0,0 +1,182 @@
#include "bst.h"
template <typename T>
typename BST<T>::node *BST<T>::insert(BST<T>::node *n, const int &key, const T *content, bool &success)
{
if (n == NULL)
{
n = new BST<T>::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 <typename T>
bool BST<T>::insert(const int &key, const T *content)
{
bool success = true;
root = insert(root, key, content, success);
return success;
}
template <typename T>
typename BST<T>::node *BST<T>::search(const BST<T>::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 <typename T>
T *BST<T>::search(const int &key)
{
node *n = search(root, key);
if (n == NULL)
return NULL;
return n->content;
}
template <typename T>
typename BST<T>::node *BST<T>::min(BST<T>::node *n)
{
if (n == NULL)
{
return NULL;
}
else if (n->l == NULL)
{
return n;
}
else
return min(n->l);
}
template <typename T>
typename BST<T>::node *BST<T>::max(BST<T>::node *n)
{
if (n == NULL)
{
return NULL;
}
else if (n->r == NULL)
{
return n;
}
else
return min(n->r);
}
template <typename T>
T *BST<T>::min()
{
node *n = min(root);
if (n == NULL)
{
return NULL;
}
return n->content;
}
template <typename T>
T *BST<T>::max()
{
node *n = max(root);
if (n == NULL)
{
return NULL;
}
return n->content;
}
template <typename T>
typename BST<T>::node *BST<T>::succ(BST<T>::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 <typename T>
T *BST<T>::succ(const int &key)
{
node *n = search(root, key);
return n == NULL ? NULL : succ(n);
}
template <typename T>
typename BST<T>::node *BST<T>::pred(BST<T>::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 <typename T>
T *BST<T>::pred(const int &key)
{
node *n = search(root, key);
return n == NULL ? NULL : pred(n);
}

37
bst.h Normal file
View file

@ -0,0 +1,37 @@
#ifndef BST_H
#define BST_H
#include <iostream>
#include "helpers.h"
template <typename T>
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

View file

@ -1,5 +1,6 @@
#ifndef HELPERS_H #ifndef HELPERS_H
#define HELPERS_H
#include <utility> #include <utility>
#include <string> #include <string>

View file

@ -10,7 +10,67 @@
"math.h": "c", "math.h": "c",
"blocks.h": "c", "blocks.h": "c",
"stdio.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"
} }
} }
} }

View file

@ -10,10 +10,12 @@
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <set> #include <set>
#include <queue>
#include <chrono> #include <chrono>
#include "raylib.h" #include "raylib.h"
#include "helpers.h" #include "helpers.h"
#include "bst.h"
using time_point = std::chrono::steady_clock::time_point; using time_point = std::chrono::steady_clock::time_point;
@ -25,6 +27,15 @@ struct ColorSegment
std::set<uint> crossed_by; std::set<uint> 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) void DrawColorSegment(const ColorSegment &cl)
{ {
DrawLine(cl.l.first.x, cl.l.first.y, cl.l.second.x, cl.l.second.y, cl.c); 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<ColorSegment> &lines)
} }
} }
bool sort_by_x(const ColorSegment &s, const ColorSegment &t) void crossingSweep(std::vector<ColorSegment> &lines, const std::vector<SegmentPoint> &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<ColorSegment> &lines) std::priority_queue<SegmentPoint, std::vector<SegmentPoint>, ComparePoints> events(points.begin(), points.end(), ComparePoints());
{ std::cout << "Queue is size: " << events.size() << std::endl;
std::sort(lines.begin(), lines.end(), sort_by_x); BST<SegmentPoint> tree;
while (!events.empty())
{
events.pop();
}
} }
enum States enum States
@ -110,20 +131,35 @@ int main()
const int screenHeight = 900; const int screenHeight = 900;
bool close = false; bool close = false;
const int nols = 80; // Number of lines
// Initialize random engine // Initialize random engine
std::random_device rd; std::random_device rd;
std::mt19937_64 gen(rd()); // Delete "_64" in a 32 bit system std::mt19937_64 gen(rd()); // Delete "_64" in a 32 bit system
std::uniform_int_distribution<> distrx(0, screenWidth); std::uniform_int_distribution<> distrx(0, screenWidth);
std::uniform_int_distribution<> distry(0, screenHeight); std::uniform_int_distribution<> distry(0, screenHeight);
std::uniform_int_distribution<> distrnols(50, 200);
std::vector<ColorSegment> lines, naive_lines, sweep_lines; std::vector<ColorSegment> lines, naive_lines, sweep_lines;
std::vector<SegmentPoint> points, sweep_points;
const int nols = distrnols(gen); // Number of lines
// Generate random lines // Generate random lines
for (uint i = 0; i < nols; ++i) 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; //std::cout << "(" << l.first.x << "," << l.first.y << ") (" << l.second.x << "," << l.second.y << std::endl;
ColorSegment cl = ColorSegment{l, BLACK}; ColorSegment cl = ColorSegment{l, BLACK};
@ -144,10 +180,11 @@ int main()
// Test sweep algorithm // Test sweep algorithm
time_point begin_sweep = std::chrono::steady_clock::now(); 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(); 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<std::chrono::nanoseconds>(end_naive - begin_naive).count() << " ns" << std::endl; std::cout << "Naive elapsed time: " << std::chrono::duration_cast<std::chrono::nanoseconds>(end_naive - begin_naive).count() << " ns" << std::endl;
std::cout << "Sweep elapsed time: " << std::chrono::duration_cast<std::chrono::nanoseconds>(end_sweep - begin_sweep).count() << " ns" << std::endl; std::cout << "Sweep elapsed time: " << std::chrono::duration_cast<std::chrono::nanoseconds>(end_sweep - begin_sweep).count() << " ns" << std::endl;
@ -193,7 +230,7 @@ int main()
break; break;
} }
DrawFPS(10, 10); //DrawFPS(10, 10);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------