binary tree
parent
7bf24a11a5
commit
05e5fcf7f1
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
include(cmake/color.cmake)
|
include(cmake/color.cmake)
|
||||||
set(BLT_VERSION 2.1.7)
|
set(BLT_VERSION 2.1.8)
|
||||||
|
|
||||||
set(BLT_TARGET BLT)
|
set(BLT_TARGET BLT)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!python3
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import argparse
|
import argparse
|
||||||
|
|
|
@ -10,10 +10,12 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <blt/std/allocator.h>
|
#include <blt/std/allocator.h>
|
||||||
|
#include <blt/std/types.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
// TODO: blt::queue
|
// TODO: blt::queue
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
namespace blt
|
namespace blt
|
||||||
{
|
{
|
||||||
|
@ -142,6 +144,205 @@ namespace blt
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename K, typename V>
|
||||||
|
class range_tree_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct node_t
|
||||||
|
{
|
||||||
|
K k;
|
||||||
|
V v;
|
||||||
|
blt::i64 children = 0;
|
||||||
|
|
||||||
|
node_t(K k, V v): k(std::move(k)), v(std::move(v))
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
void insert(K k, V v)
|
||||||
|
{
|
||||||
|
auto insert_point = nodes.begin();
|
||||||
|
auto insert_parent = insert_point;
|
||||||
|
|
||||||
|
while (insert_point != nodes.end())
|
||||||
|
{
|
||||||
|
// no children
|
||||||
|
if (insert_point->children == 0)
|
||||||
|
{
|
||||||
|
++insert_point->children;
|
||||||
|
++insert_point;
|
||||||
|
break;
|
||||||
|
} else if (insert_point->children == 1)
|
||||||
|
{
|
||||||
|
// 1 child case
|
||||||
|
insert_parent = insert_point;
|
||||||
|
// find if child is min & move to it
|
||||||
|
++insert_point;
|
||||||
|
bool min = insert_point->k < insert_parent->k;
|
||||||
|
if (k < insert_parent->k)
|
||||||
|
{
|
||||||
|
// if the parent's child is a min value, then we can safely move towards it
|
||||||
|
if (min)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// otherwise we can break and this will insert the new node as the new min.
|
||||||
|
++insert_parent->children;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// parents child is min, so we move past it
|
||||||
|
if (min)
|
||||||
|
{
|
||||||
|
insert_point = skip_children(insert_point);
|
||||||
|
// can break as we insert here
|
||||||
|
++insert_parent->children;
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// parents child is max, we can safely move towards it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
insert_parent = insert_point;
|
||||||
|
++insert_point;
|
||||||
|
if (k < insert_parent->k)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
insert_point = skip_children(insert_point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes.insert(insert_point, {std::move(k), std::move(v)});
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(std::ostream& out, bool pretty_print)
|
||||||
|
{
|
||||||
|
std::stack<blt::size_t> left;
|
||||||
|
blt::size_t indent = 0;
|
||||||
|
for (auto& v : nodes)
|
||||||
|
{
|
||||||
|
if (v.children > 0)
|
||||||
|
{
|
||||||
|
create_indent(out, indent, pretty_print) << "(";
|
||||||
|
indent++;
|
||||||
|
left.emplace(v.children);
|
||||||
|
out << v.k << ": " << v.v << end_indent(pretty_print);
|
||||||
|
} else
|
||||||
|
create_indent(out, indent, pretty_print) << v.k << ": " << v.v << end_indent(pretty_print);
|
||||||
|
while (!left.empty())
|
||||||
|
{
|
||||||
|
auto top = left.top();
|
||||||
|
left.pop();
|
||||||
|
if (top == 0)
|
||||||
|
{
|
||||||
|
indent--;
|
||||||
|
create_indent(out, indent, pretty_print) << ")" << end_indent(pretty_print);
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (!pretty_print)
|
||||||
|
out << " ";
|
||||||
|
left.push(top - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!left.empty())
|
||||||
|
{
|
||||||
|
auto top = left.top();
|
||||||
|
left.pop();
|
||||||
|
if (top == 0)
|
||||||
|
{
|
||||||
|
indent--;
|
||||||
|
create_indent(out, indent, pretty_print) << ")" << end_indent(pretty_print);
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
out << "TREE MISMATCH";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<V> search(const K& k)
|
||||||
|
{
|
||||||
|
auto point = nodes.begin();
|
||||||
|
while (point != nodes.end())
|
||||||
|
{
|
||||||
|
if (k == point->k)
|
||||||
|
return point->v;
|
||||||
|
if (point->children == 0)
|
||||||
|
return {};
|
||||||
|
auto parent = point;
|
||||||
|
++point;
|
||||||
|
auto min = point->k < parent->k;
|
||||||
|
if (k >= parent->k)
|
||||||
|
{
|
||||||
|
if (min)
|
||||||
|
point = skip_children(point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<V> search_min(const K& min)
|
||||||
|
{
|
||||||
|
auto point = nodes.begin();
|
||||||
|
while (point != nodes.end())
|
||||||
|
{
|
||||||
|
if (point->children == 0)
|
||||||
|
return {};
|
||||||
|
auto parent = point;
|
||||||
|
++point;
|
||||||
|
auto is_min = point->k < parent->k;
|
||||||
|
if (k >= parent->k)
|
||||||
|
{
|
||||||
|
if (is_min)
|
||||||
|
point = skip_children(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto skip_children(typename std::vector<node_t>::iterator begin)
|
||||||
|
{
|
||||||
|
blt::i64 children_left = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (children_left != 0)
|
||||||
|
children_left--;
|
||||||
|
if (begin->children > 0)
|
||||||
|
children_left += begin->children;
|
||||||
|
++begin;
|
||||||
|
} while (children_left > 0);
|
||||||
|
|
||||||
|
return begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& create_indent(std::ostream& out, blt::size_t amount, bool pretty_print)
|
||||||
|
{
|
||||||
|
if (!pretty_print)
|
||||||
|
return out;
|
||||||
|
for (blt::size_t i = 0; i < amount; i++)
|
||||||
|
out << '\t';
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view end_indent(bool pretty_print)
|
||||||
|
{
|
||||||
|
return pretty_print ? "\n" : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<node_t> nodes;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //BLT_BINARY_TREE_H
|
#endif //BLT_BINARY_TREE_H
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
/*
|
|
||||||
* Created by Brett on 16/01/23.
|
|
||||||
* Licensed under GNU General Public License V3.0
|
|
||||||
* See LICENSE file for license detail
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BLT_WINDOW_H
|
|
||||||
#define BLT_WINDOW_H
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#ifndef BLT_MAP_FUNC
|
|
||||||
#include <unordered_map>
|
|
||||||
#define BLT_MAP_FUNC std::unordered_map
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define KEY_MAP BLT_MAP_FUNC<int, bool>
|
|
||||||
|
|
||||||
namespace blt {
|
|
||||||
|
|
||||||
class window {
|
|
||||||
protected:
|
|
||||||
bool m_windowOpen = true;
|
|
||||||
int m_width = 800, m_height = 600;
|
|
||||||
|
|
||||||
std::vector<std::function<void(window*)>> renderFunctions{};
|
|
||||||
std::vector<std::function<void(window*, int, bool)>> keyListeners{};
|
|
||||||
std::vector<std::function<void(window*, int, bool)>> mouseListeners{};
|
|
||||||
|
|
||||||
KEY_MAP keysDown{};
|
|
||||||
KEY_MAP mouseDown{};
|
|
||||||
public:
|
|
||||||
window() = default;
|
|
||||||
window(int width_, int height_) {
|
|
||||||
m_width = width_;
|
|
||||||
m_height = height_;
|
|
||||||
}
|
|
||||||
virtual void createWindow() = 0;
|
|
||||||
virtual void startMainLoop() = 0;
|
|
||||||
virtual void destroyWindow() = 0;
|
|
||||||
virtual ~window() = 0;
|
|
||||||
|
|
||||||
virtual inline bool setResizeable(bool resizeEnabled) = 0;
|
|
||||||
virtual inline bool setWindowSize(int width_, int height_) = 0;
|
|
||||||
[[nodiscard]] inline int getWidth() const {return m_width;};
|
|
||||||
[[nodiscard]] inline int getHeight() const {return m_height;};
|
|
||||||
|
|
||||||
[[nodiscard]] virtual inline bool isWindowOpen() const {return m_windowOpen;};
|
|
||||||
virtual inline void closeWindow(){
|
|
||||||
m_windowOpen = false;
|
|
||||||
}
|
|
||||||
virtual inline void registerLoopFunction(const std::function<void(window*)>& func) {
|
|
||||||
renderFunctions.push_back(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual inline bool isKeyDown(int key) const { return keysDown.at(key); }
|
|
||||||
virtual inline bool isMouseDown(int button) const {return mouseDown.at(button);};
|
|
||||||
// Function signature is window pointer to this, key press, pressed/released (true/false)
|
|
||||||
virtual inline void registerKeyListener(const std::function<void(window*, int, bool)>& listener) {
|
|
||||||
keyListeners.push_back(listener);
|
|
||||||
}
|
|
||||||
// Function signature is window pointer to this, mouse button press, pressed/released (true/false)
|
|
||||||
virtual inline void registerMouseListener(const std::function<void(window*, int, bool)>& listener) {
|
|
||||||
mouseListeners.push_back(listener);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue