BST implementation
This commit is contained in:
parent
8418010c1e
commit
848f89a6a4
6 changed files with 330 additions and 13 deletions
2
Makefile
2
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)
|
||||
|
|
182
bst.cpp
Normal file
182
bst.cpp
Normal 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
37
bst.h
Normal 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
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#ifndef HELPERS_H
|
||||
#define HELPERS_H
|
||||
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
59
main.cpp
59
main.cpp
|
@ -10,10 +10,12 @@
|
|||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <queue>
|
||||
#include <chrono>
|
||||
|
||||
#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<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)
|
||||
{
|
||||
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::sort(lines.begin(), lines.end(), sort_by_x);
|
||||
std::priority_queue<SegmentPoint, std::vector<SegmentPoint>, ComparePoints> events(points.begin(), points.end(), ComparePoints());
|
||||
std::cout << "Queue is size: " << events.size() << std::endl;
|
||||
BST<SegmentPoint> 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<ColorSegment> lines, naive_lines, sweep_lines;
|
||||
std::vector<SegmentPoint> 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<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;
|
||||
|
||||
|
@ -193,7 +230,7 @@ int main()
|
|||
break;
|
||||
}
|
||||
|
||||
DrawFPS(10, 10);
|
||||
//DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue