mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-07 01:01:45 +00:00
279 lines
5.6 KiB
C++
279 lines
5.6 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#ifndef HPL1_TREE_H
|
|
#define HPL1_TREE_H
|
|
|
|
#include "common/func.h"
|
|
#include "common/util.h"
|
|
#include "hpl1/std/pair.h"
|
|
|
|
namespace Hpl1 {
|
|
|
|
namespace Std {
|
|
|
|
template<class Key, class Val, class KeyComp = Common::Less<Key> >
|
|
class Tree {
|
|
public:
|
|
using ValueType = pair<Key, Val>;
|
|
|
|
struct Node {
|
|
Node *parent;
|
|
Node *left;
|
|
Node *right;
|
|
ValueType value;
|
|
};
|
|
|
|
template<typename Ref, typename Ptr>
|
|
class Iterator {
|
|
public:
|
|
friend Tree;
|
|
|
|
Iterator() = default;
|
|
Iterator(const Iterator &) = default;
|
|
Iterator &operator=(const Iterator &) = default;
|
|
|
|
Ref operator*() const { return _current->value; }
|
|
|
|
Ptr operator->() const { return &_current->value; }
|
|
|
|
Iterator &operator++() {
|
|
if (_current->right) {
|
|
_current = leftmost(_current->right);
|
|
} else {
|
|
auto p = _current->parent;
|
|
while (p && p->right == _current) {
|
|
_current = p;
|
|
p = p->parent;
|
|
}
|
|
_current = p;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
Iterator operator++(int) {
|
|
auto temp = *this;
|
|
++(*this);
|
|
return temp;
|
|
}
|
|
|
|
bool operator==(const Iterator &rhs) const {
|
|
return _current == rhs._current;
|
|
}
|
|
|
|
bool operator!=(const Iterator &rhs) const {
|
|
return _current != rhs._current;
|
|
}
|
|
|
|
private:
|
|
Iterator(Node *n) : _current(n) {}
|
|
|
|
Node *_current = nullptr;
|
|
};
|
|
|
|
using BasicIterator = Iterator<ValueType &, ValueType *>;
|
|
using ConstIterator = Iterator<const ValueType &, const ValueType *>;
|
|
|
|
Tree(KeyComp comp = {}) : _comp(Common::move(comp)) {
|
|
}
|
|
|
|
Tree(const Tree &other) : _comp(other._comp) {
|
|
for (const auto &val : other)
|
|
insert(val);
|
|
}
|
|
|
|
Tree(Tree &&other) : _root(other._root), _leftmost(other._leftmost), _size(other._size), _comp(Common::move(other._comp)) {
|
|
}
|
|
|
|
Tree &operator=(const Tree &rhs) {
|
|
*this = Tree(rhs);
|
|
return *this;
|
|
}
|
|
|
|
Tree &operator=(Tree &&rhs) {
|
|
clear();
|
|
_root = rhs._root;
|
|
_leftmost = rhs._leftmost;
|
|
_size = rhs._size;
|
|
_comp = Common::move(rhs._comp);
|
|
rhs._root = nullptr;
|
|
rhs._leftmost = nullptr;
|
|
rhs._size = 0;
|
|
return *this;
|
|
}
|
|
|
|
void clear() {
|
|
erase(begin(), end());
|
|
_size = 0;
|
|
_root = nullptr;
|
|
_leftmost = nullptr;
|
|
}
|
|
|
|
BasicIterator begin() { return BasicIterator{_leftmost}; }
|
|
|
|
ConstIterator begin() const { return ConstIterator{_leftmost}; }
|
|
|
|
BasicIterator end() { return BasicIterator{nullptr}; }
|
|
|
|
ConstIterator end() const { return ConstIterator{nullptr}; }
|
|
|
|
BasicIterator lowerBound(const Key &key) {
|
|
Node *it = _root;
|
|
Node *res = nullptr;
|
|
while (it) {
|
|
if (!_comp(it->value.first, key)) {
|
|
res = it;
|
|
it = it->left;
|
|
} else {
|
|
it = it->right;
|
|
}
|
|
}
|
|
return BasicIterator{res};
|
|
}
|
|
|
|
ConstIterator lowerBound(const Key &key) const {
|
|
Node *it = _root;
|
|
Node *res = nullptr;
|
|
while (it) {
|
|
if (!_comp(it->value.first, key)) {
|
|
res = it;
|
|
it = it->left;
|
|
} else {
|
|
it = it->right;
|
|
}
|
|
}
|
|
return ConstIterator{res};
|
|
}
|
|
|
|
BasicIterator upperBound(const Key &key) {
|
|
Node *it = _root;
|
|
Node *res = nullptr;
|
|
while (it) {
|
|
if (!_comp(key, it->value.first)) {
|
|
it = it->right;
|
|
} else {
|
|
res = it;
|
|
it = it->left;
|
|
}
|
|
}
|
|
return BasicIterator{res};
|
|
}
|
|
|
|
ConstIterator upperBound(const Key &key) const {
|
|
Node *it = _root;
|
|
Node *res = nullptr;
|
|
while (it) {
|
|
if (!_comp(key, it->value.first)) {
|
|
it = it->right;
|
|
} else {
|
|
res = it;
|
|
it = it->left;
|
|
}
|
|
}
|
|
return ConstIterator{res};
|
|
}
|
|
|
|
BasicIterator erase(BasicIterator it) {
|
|
auto const u = it._current;
|
|
if (!u)
|
|
return {nullptr};
|
|
auto v = merge(u->left, u->right);
|
|
if (u->parent) {
|
|
auto const p = u->parent;
|
|
if (p->left == u)
|
|
p->left = v;
|
|
else
|
|
p->right = v;
|
|
} else {
|
|
_root = v;
|
|
}
|
|
if (v)
|
|
v->parent = u->parent;
|
|
if (u == _leftmost)
|
|
_leftmost = v ? v : u->parent;
|
|
--_size;
|
|
auto const ret = ++it;
|
|
delete u;
|
|
return ret;
|
|
}
|
|
|
|
BasicIterator erase(BasicIterator first, BasicIterator last) {
|
|
while (first != last)
|
|
erase(first++);
|
|
return last;
|
|
}
|
|
|
|
BasicIterator insert(const ValueType &val) {
|
|
auto it = &_root;
|
|
Node *parent = nullptr;
|
|
bool wentRight = false;
|
|
while (*it) {
|
|
parent = *it;
|
|
if (_comp((*it)->value.first, val.first)) {
|
|
it = &(*it)->right;
|
|
wentRight = true;
|
|
} else {
|
|
it = &(*it)->left;
|
|
}
|
|
}
|
|
*it = new Node{parent, nullptr, nullptr, val};
|
|
if (!wentRight)
|
|
_leftmost = *it;
|
|
++_size;
|
|
return BasicIterator{*it};
|
|
}
|
|
|
|
std::size_t size() const { return _size; }
|
|
|
|
bool isEmpty() const { return _size == 0; }
|
|
|
|
~Tree() { clear(); }
|
|
|
|
private:
|
|
KeyComp _comp;
|
|
Node *_root = nullptr;
|
|
Node *_leftmost = nullptr;
|
|
std::size_t _size = 0;
|
|
|
|
Node *merge(Node *left, Node *right) {
|
|
if (!right)
|
|
return left;
|
|
else if (!left)
|
|
return right;
|
|
else {
|
|
auto lm = leftmost(right);
|
|
lm->left = left;
|
|
left->parent = lm;
|
|
return right;
|
|
}
|
|
}
|
|
|
|
static Node *leftmost(Node *n) {
|
|
while (n->left)
|
|
n = n->left;
|
|
return n;
|
|
}
|
|
};
|
|
|
|
} // namespace Std
|
|
} // namespace Hpl1
|
|
|
|
#endif |