RBTree implementation with const null_node
This commit is contained in:
parent
2050eb4d46
commit
da1dfd4c13
@ -2,10 +2,14 @@
|
|||||||
|
|
||||||
namespace GraphC::GraphModel {
|
namespace GraphC::GraphModel {
|
||||||
|
|
||||||
|
|
||||||
Attribute::Attribute(id_t _id, Node* _parent_node, Attribute::Type _type, std::string _title)
|
Attribute::Attribute(id_t _id, Node* _parent_node, Attribute::Type _type, std::string _title)
|
||||||
: type(_type), id(_id), parent_node(_parent_node), title(_title)
|
: type(_type), id(_id), parent_node(_parent_node), title(_title)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
Attribute::Attribute() : Attribute(id_t_invalid, nullptr, Attribute::Type::Static, "NULL_ATTR")
|
||||||
|
{}
|
||||||
|
|
||||||
const RBTree<id_t, Edge*>& Attribute::getIncomingEdges() const {
|
const RBTree<id_t, Edge*>& Attribute::getIncomingEdges() const {
|
||||||
return incoming_edges;
|
return incoming_edges;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,4 +6,7 @@ Edge::Edge(id_t _id, id_t _from_attr_id, id_t _to_attr_id)
|
|||||||
: id(_id), to_attr_id(_to_attr_id), from_attr_id(_from_attr_id)
|
: id(_id), to_attr_id(_to_attr_id), from_attr_id(_from_attr_id)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
Edge::Edge() : Edge(id_t_invalid, id_t_invalid, id_t_invalid)
|
||||||
|
{}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ bool Graph::tryGetNode(id_t node_id, Node** result) const {
|
|||||||
|
|
||||||
void Graph::deleteNode(Node& n){
|
void Graph::deleteNode(Node& n){
|
||||||
for(const auto& attr_p : n.attributes)
|
for(const auto& attr_p : n.attributes)
|
||||||
deleteAttribute(*attr_p.second);
|
deleteAttribute(*attr_p.value);
|
||||||
useful_assert(nodes.tryDelete(n.id),
|
useful_assert(nodes.tryDelete(n.id),
|
||||||
format("can't delete node with id %i", n.id));
|
format("can't delete node with id %i", n.id));
|
||||||
}
|
}
|
||||||
@ -141,12 +141,12 @@ Attribute* Graph::createAttribute(Attribute&& a){
|
|||||||
|
|
||||||
void Graph::deleteAttribute(Attribute& a){
|
void Graph::deleteAttribute(Attribute& a){
|
||||||
for(const auto& edge_p : a.incoming_edges){
|
for(const auto& edge_p : a.incoming_edges){
|
||||||
useful_assert(edges.tryDelete(edge_p.second->id),
|
useful_assert(edges.tryDelete(edge_p.value->id),
|
||||||
format("can't find edge with id %i", edge_p.second->id));
|
format("can't find edge with id %i", edge_p.value->id));
|
||||||
}
|
}
|
||||||
for(const auto& edge_p : a.outgoing_edges){
|
for(const auto& edge_p : a.outgoing_edges){
|
||||||
useful_assert(edges.tryDelete(edge_p.second->id),
|
useful_assert(edges.tryDelete(edge_p.value->id),
|
||||||
format("can't find edge with id %i", edge_p.second->id));
|
format("can't find edge with id %i", edge_p.value->id));
|
||||||
}
|
}
|
||||||
useful_assert(attributes.tryDelete(a.id),
|
useful_assert(attributes.tryDelete(a.id),
|
||||||
format("can't delete attribute with id %i", a.id));
|
format("can't delete attribute with id %i", a.id));
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
namespace GraphC::GraphModel {
|
namespace GraphC::GraphModel {
|
||||||
|
|
||||||
typedef i32 id_t;
|
typedef i32 id_t;
|
||||||
|
#define id_t_invalid ((id_t)-1)
|
||||||
|
|
||||||
class IdGenerator {
|
class IdGenerator {
|
||||||
id_t next_id=1;
|
id_t next_id=1;
|
||||||
@ -39,6 +40,8 @@ public:
|
|||||||
Node *const parent_node;
|
Node *const parent_node;
|
||||||
std::string title;
|
std::string title;
|
||||||
|
|
||||||
|
///@warning empty constructor for RBTree null-value node, do not use it
|
||||||
|
Attribute();
|
||||||
Attribute(id_t _id, Node* _parent_node, Attribute::Type _type, std::string _title);
|
Attribute(id_t _id, Node* _parent_node, Attribute::Type _type, std::string _title);
|
||||||
|
|
||||||
const RBTree<id_t, Edge*>& getIncomingEdges() const;
|
const RBTree<id_t, Edge*>& getIncomingEdges() const;
|
||||||
@ -54,6 +57,8 @@ public:
|
|||||||
const id_t id;
|
const id_t id;
|
||||||
std::string title;
|
std::string title;
|
||||||
|
|
||||||
|
///@warning empty constructor for RBTree null-value node, do not use it
|
||||||
|
Node();
|
||||||
Node(id_t _id, std::string _title);
|
Node(id_t _id, std::string _title);
|
||||||
|
|
||||||
const RBTree<id_t, Attribute*>& getAttributes() const;
|
const RBTree<id_t, Attribute*>& getAttributes() const;
|
||||||
@ -64,6 +69,8 @@ struct Edge {
|
|||||||
const id_t to_attr_id;
|
const id_t to_attr_id;
|
||||||
const id_t from_attr_id;
|
const id_t from_attr_id;
|
||||||
|
|
||||||
|
///@warning empty constructor for RBTree null-value node, do not use it
|
||||||
|
Edge();
|
||||||
Edge(id_t _id, id_t _from_attr_id, id_t _to_attr_id);
|
Edge(id_t _id, id_t _from_attr_id, id_t _to_attr_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,9 @@ namespace GraphC::GraphModel {
|
|||||||
Node::Node(id_t _id, std::string _title)
|
Node::Node(id_t _id, std::string _title)
|
||||||
: id(_id), title(_title)
|
: id(_id), title(_title)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
Node::Node() : Node(id_t_invalid, "NULL_NODE")
|
||||||
|
{}
|
||||||
|
|
||||||
const RBTree<id_t, Attribute*>& Node::getAttributes() const {
|
const RBTree<id_t, Attribute*>& Node::getAttributes() const {
|
||||||
return attributes;
|
return attributes;
|
||||||
|
|||||||
423
src/RBTree.hpp
423
src/RBTree.hpp
@ -1,80 +1,87 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../dependencies/kerep/src/base/base.h"
|
|
||||||
#include <map>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include "UsefulException.hpp"
|
||||||
|
|
||||||
// typedef char* TKey;
|
|
||||||
// typedef char* TVal;
|
|
||||||
template<typename TKey, typename TVal>
|
template<typename TKey, typename TVal>
|
||||||
class RBTree {
|
class RBTree {
|
||||||
enum class Color {
|
enum class Color {
|
||||||
Red, Black
|
Red, Black
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Node {
|
// public version of struct Node
|
||||||
TKey key;
|
// TreeIterator returns a reference to KVPair to hide all other stuff from users
|
||||||
|
public:
|
||||||
|
struct KVPair {
|
||||||
|
// members are in reverse order to minimize padding and make struct Node smaller
|
||||||
|
|
||||||
TVal value;
|
TVal value;
|
||||||
|
TKey key;
|
||||||
|
|
||||||
|
KVPair(TKey& k, TVal& v) : value(v), key(k)
|
||||||
|
{}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// special constructor for tree leafs (null nodes)
|
||||||
|
// leaves key and value uninitialized
|
||||||
|
KVPair()
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Node : public KVPair {
|
||||||
|
// stacks with KVPair::key if it is 32-bit or smaller
|
||||||
Color color;
|
Color color;
|
||||||
Node* parent;
|
Node* parent;
|
||||||
Node* left = nullptr;
|
Node* left;
|
||||||
Node* right = nullptr;
|
Node* right;
|
||||||
|
|
||||||
Node(TKey _key, TVal _val, Color _color, Node* _parent)
|
Node(TKey& _key, TVal& _val, Color _color, Node* _parent, Node* _left, Node* _right)
|
||||||
: key(_key), value(_val), color(_color), parent(_parent)
|
: KVPair(_key, _val), color(_color), parent(_parent), left(_left), right(_right)
|
||||||
{
|
{}
|
||||||
|
|
||||||
|
Node() : color(Color::Black), parent(this), left(this), right(this)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool isLeaf() const {
|
||||||
|
return parent == this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Node(){
|
~Node(){
|
||||||
delete left;
|
if(!left->isLeaf())
|
||||||
delete right;
|
delete left;
|
||||||
|
if(!right->isLeaf())
|
||||||
|
delete right;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Node* getSibling(){
|
/// if is leaf returns itself
|
||||||
if(parent == nullptr)
|
Node* getMinChild() {
|
||||||
return nullptr;
|
|
||||||
else if(parent->left == this)
|
|
||||||
return parent->right;
|
|
||||||
else return parent->left;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Node* getGrandparent(){
|
|
||||||
if(parent == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
else return parent->parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Node* getUncle(){
|
|
||||||
if(parent == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
return parent->getSibling();
|
|
||||||
}
|
|
||||||
|
|
||||||
// n should be not null
|
|
||||||
Node* getMinChild(){
|
|
||||||
Node* n = this;
|
Node* n = this;
|
||||||
while(n->left != nullptr)
|
while(!n->left->isLeaf())
|
||||||
n = n->left;
|
n = n->left;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// n should be not null
|
/// if is leaf returns itself
|
||||||
Node* getMaxChild(){
|
Node* getMaxChild() {
|
||||||
Node* n = this;
|
Node* n = this;
|
||||||
while(n->right != nullptr)
|
while(!n->right->isLeaf())
|
||||||
n = n->right;
|
n = n->right;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Node* root = nullptr;
|
static Node null_node;
|
||||||
|
static Node* null_node_ptr;
|
||||||
|
Node* root = &null_node;
|
||||||
|
|
||||||
|
|
||||||
///@returns null if root is null
|
///@returns null if root is null
|
||||||
Node* findParentForKey(TKey key) const {
|
Node* findParentForKey(TKey key) const {
|
||||||
Node* n = root;
|
Node* n = root;
|
||||||
Node* parent = nullptr;
|
Node* parent = null_node_ptr;
|
||||||
while(n != nullptr){
|
while(n != null_node_ptr){
|
||||||
parent = n;
|
parent = n;
|
||||||
if(key < n->key)
|
if(key < n->key)
|
||||||
n = n->left;
|
n = n->left;
|
||||||
@ -90,7 +97,7 @@ class RBTree {
|
|||||||
Node* y = x->right;
|
Node* y = x->right;
|
||||||
// 2. move y to the position of x
|
// 2. move y to the position of x
|
||||||
y->parent = x->parent;
|
y->parent = x->parent;
|
||||||
if (x->parent != nullptr){ // x != root
|
if(x->parent != null_node_ptr){ // x != root
|
||||||
if(x == x->parent->left)
|
if(x == x->parent->left)
|
||||||
x->parent->left = y;
|
x->parent->left = y;
|
||||||
else x->parent->right = y;
|
else x->parent->right = y;
|
||||||
@ -98,7 +105,7 @@ class RBTree {
|
|||||||
else root = y;
|
else root = y;
|
||||||
// 3. move y.left to x.right if it exists
|
// 3. move y.left to x.right if it exists
|
||||||
x->right = y->left;
|
x->right = y->left;
|
||||||
if (x->right != nullptr)
|
if(x->right != null_node_ptr)
|
||||||
x->right->parent = x;
|
x->right->parent = x;
|
||||||
// 4. move x to y.left
|
// 4. move x to y.left
|
||||||
y->left = x;
|
y->left = x;
|
||||||
@ -110,7 +117,7 @@ class RBTree {
|
|||||||
Node* y = x->left;
|
Node* y = x->left;
|
||||||
// 2. move y up
|
// 2. move y up
|
||||||
y->parent = x->parent;
|
y->parent = x->parent;
|
||||||
if (x->parent != nullptr){ // x != root
|
if(x->parent != null_node_ptr){ // x != root
|
||||||
if(x == x->parent->left)
|
if(x == x->parent->left)
|
||||||
x->parent->left = y;
|
x->parent->left = y;
|
||||||
else x->parent->right = y;
|
else x->parent->right = y;
|
||||||
@ -118,7 +125,7 @@ class RBTree {
|
|||||||
else root = y;
|
else root = y;
|
||||||
// 3. move y.right to x.left if it exists
|
// 3. move y.right to x.left if it exists
|
||||||
x->left = y->right;
|
x->left = y->right;
|
||||||
if (x->left != nullptr)
|
if(x->left != null_node_ptr)
|
||||||
x->left->parent = x;
|
x->left->parent = x;
|
||||||
// 4. move x to y.right
|
// 4. move x to y.right
|
||||||
y->right = x;
|
y->right = x;
|
||||||
@ -126,128 +133,124 @@ class RBTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void transplantNode(Node* old, Node* neww){
|
void transplantNode(Node* old, Node* neww){
|
||||||
if(old->parent == nullptr)
|
if(old->parent == null_node_ptr)
|
||||||
root = neww;
|
root = neww;
|
||||||
else if(old->parent->left == old)
|
else if(old->parent->left == old)
|
||||||
old->parent->left = neww;
|
old->parent->left = neww;
|
||||||
else old->parent->right = neww;
|
else old->parent->right = neww;
|
||||||
if(neww != nullptr)
|
if(neww != null_node_ptr)
|
||||||
neww->parent = old->parent;
|
neww->parent = old->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fixupInsertion(Node* n){
|
void fixupInsertion(Node* x){
|
||||||
// case 1: n is root -- root must be black
|
while(x != root && x->parent->color == Color::Red) {
|
||||||
if (n->parent == nullptr){
|
if(x->parent == x->parent->parent->left) {
|
||||||
n->color = Color::Black;
|
Node* y = x->parent->parent->right;
|
||||||
return;
|
// uncle is red
|
||||||
}
|
if(y->color == Color::Red) {
|
||||||
|
x->parent->color = Color::Black;
|
||||||
// case 2: parent is black -- no requirements mismatch
|
y->color = Color::Black;
|
||||||
if (n->parent->color == Color::Black)
|
x->parent->parent->color = Color::Red;
|
||||||
return;
|
x = x->parent->parent;
|
||||||
|
}
|
||||||
// case 3: parent and uncle are red -- red nodes must have black parents
|
// uncle is black
|
||||||
Node* u = n->getUncle();
|
else {
|
||||||
Node* g = n->getGrandparent();
|
if(x == x->parent->right) {
|
||||||
if(u != nullptr && u->color == Color::Red){
|
// make x a left child
|
||||||
n->parent->color = Color::Black;
|
x = x->parent;
|
||||||
u->color = Color::Black;
|
rotateLeft(x);
|
||||||
g->color = Color::Red;
|
}
|
||||||
fixupInsertion(g);
|
// recolor and rotate
|
||||||
return;
|
x->parent->color = Color::Black;
|
||||||
}
|
x->parent->parent->color = Color::Red;
|
||||||
|
rotateRight(x->parent->parent);
|
||||||
// case 4: parent is red and uncle is black -- red nodes must have black parents
|
}
|
||||||
if ((n == n->parent->right) && (n->parent == g->left)) {
|
}
|
||||||
rotateLeft(n->parent);
|
// mirrored above code
|
||||||
n = n->left;
|
else {
|
||||||
}
|
Node* y = x->parent->parent->left;
|
||||||
else if ((n == n->parent->left) && (n->parent == g->right)) {
|
// uncle is red
|
||||||
rotateRight(n->parent);
|
if(y->color == Color::Red) {
|
||||||
n = n->right;
|
x->parent->color = Color::Black;
|
||||||
}
|
y->color = Color::Black;
|
||||||
|
x->parent->parent->color = Color::Red;
|
||||||
// case 5
|
x = x->parent->parent;
|
||||||
n->parent->color = Color::Black;
|
}
|
||||||
g->color = Color::Red;
|
// uncle is black
|
||||||
if ((n == n->parent->left) && (n->parent == g->left))
|
else {
|
||||||
rotateRight(g);
|
if(x == x->parent->left) {
|
||||||
else rotateLeft(g);
|
// make x a right child
|
||||||
}
|
x = x->parent;
|
||||||
|
rotateRight(x);
|
||||||
void fixupDeletion(Node* n){
|
}
|
||||||
// case 1
|
// recolor and rotate
|
||||||
if(n->parent == nullptr)
|
x->parent->color = Color::Black;
|
||||||
return;
|
x->parent->parent->color = Color::Red;
|
||||||
|
rotateLeft(x->parent->parent);
|
||||||
// case 2
|
}
|
||||||
Node* s = n->getSibling();
|
|
||||||
if(s->color == Color::Red){
|
|
||||||
n->parent->color = Color::Red;
|
|
||||||
s->color = Color::Black;
|
|
||||||
if (n == n->parent->left)
|
|
||||||
rotateLeft(n->parent);
|
|
||||||
else rotateRight(n->parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// case 3
|
|
||||||
if ((n->parent->color == Color::Black) &&
|
|
||||||
(s->color == Color::Black) &&
|
|
||||||
(s->left->color == Color::Black) &&
|
|
||||||
(s->right->color == Color::Black))
|
|
||||||
{
|
|
||||||
s->color = Color::Red;
|
|
||||||
fixupDeletion(n->parent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// case 4
|
|
||||||
else if ((n->parent->color == Color::Red) &&
|
|
||||||
(s->color == Color::Black) &&
|
|
||||||
(s->left->color == Color::Black) &&
|
|
||||||
(s->right->color == Color::Black))
|
|
||||||
{
|
|
||||||
s->color = Color::Red;
|
|
||||||
n->parent->color = Color::Black;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// case 5
|
|
||||||
if(s->color == Color::Black) {
|
|
||||||
if ((n == n->parent->left) &&
|
|
||||||
(s->right->color == Color::Black) &&
|
|
||||||
(s->left->color == Color::Red))
|
|
||||||
{
|
|
||||||
s->color = Color::Red;
|
|
||||||
s->left->color = Color::Black;
|
|
||||||
rotateRight(s);
|
|
||||||
}
|
|
||||||
else if ((n == n->parent->right) &&
|
|
||||||
(s->left->color == Color::Black) &&
|
|
||||||
(s->right->color == Color::Red))
|
|
||||||
{
|
|
||||||
s->color = Color::Red;
|
|
||||||
s->right->color = Color::Black;
|
|
||||||
rotateLeft(s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
root->color = Color::Black;
|
||||||
// case 6
|
|
||||||
s->color = n->parent->color;
|
|
||||||
n->parent->color = Color::Black;
|
|
||||||
|
|
||||||
if (n == n->parent->left) {
|
|
||||||
s->right->color = Color::Black;
|
|
||||||
rotateLeft(n->parent);
|
|
||||||
} else {
|
|
||||||
s->left->color = Color::Black;
|
|
||||||
rotateRight(n->parent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fixupDeletion(Node* x){
|
||||||
|
while(x != root && x->color == Color::Black) {
|
||||||
|
if(x == x->parent->left) {
|
||||||
|
Node* w = x->parent->right;
|
||||||
|
if(w->color == Color::Red) {
|
||||||
|
w->color = Color::Black;
|
||||||
|
x->parent->color = Color::Red;
|
||||||
|
rotateLeft(x->parent);
|
||||||
|
w = x->parent->right;
|
||||||
|
}
|
||||||
|
if(w->left->color == Color::Black && w->right->color == Color::Black) {
|
||||||
|
w->color = Color::Red;
|
||||||
|
x = x->parent;
|
||||||
|
} else {
|
||||||
|
if(w->right->color == Color::Black) {
|
||||||
|
w->left->color = Color::Black;
|
||||||
|
w->color = Color::Red;
|
||||||
|
rotateRight(w);
|
||||||
|
w = x->parent->right;
|
||||||
|
}
|
||||||
|
w->color = x->parent->color;
|
||||||
|
x->parent->color = Color::Black;
|
||||||
|
w->right->color = Color::Black;
|
||||||
|
rotateLeft(x->parent);
|
||||||
|
x = root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Node* w = x->parent->left;
|
||||||
|
if(w->color == Color::Red) {
|
||||||
|
w->color = Color::Black;
|
||||||
|
x->parent->color = Color::Red;
|
||||||
|
rotateRight(x->parent);
|
||||||
|
w = x->parent->left;
|
||||||
|
}
|
||||||
|
if(w->right->color == Color::Black && w->left->color == Color::Black) {
|
||||||
|
w->color = Color::Red;
|
||||||
|
x = x->parent;
|
||||||
|
} else {
|
||||||
|
if(w->left->color == Color::Black) {
|
||||||
|
w->right->color = Color::Black;
|
||||||
|
w->color = Color::Red;
|
||||||
|
rotateLeft(w);
|
||||||
|
w = x->parent->left;
|
||||||
|
}
|
||||||
|
w->color = x->parent->color;
|
||||||
|
x->parent->color = Color::Black;
|
||||||
|
w->left->color = Color::Black;
|
||||||
|
rotateRight(x->parent);
|
||||||
|
x = root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x->color = Color::Black;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename TIteratorValue>
|
template<typename TreeIteratorValue>
|
||||||
struct TreeIterator : std::iterator<std::bidirectional_iterator_tag, TIteratorValue> {
|
struct TreeIterator {
|
||||||
Node* n;
|
Node* n;
|
||||||
|
|
||||||
TreeIterator(TreeIterator const& src){
|
TreeIterator(TreeIterator const& src){
|
||||||
@ -266,20 +269,20 @@ class RBTree {
|
|||||||
return n == other.n;
|
return n == other.n;
|
||||||
}
|
}
|
||||||
|
|
||||||
TIteratorValue& operator*() const {
|
TreeIteratorValue& operator*() const {
|
||||||
if(n == nullptr)
|
if(!n->isLeaf())
|
||||||
throw "RBTree::TreeIterator::operator*() error: n == nullptr";
|
return *n;
|
||||||
return *((TIteratorValue*)(void*)n);
|
else throw UsefulException("the caller has tried to get the value of the end of an iterator (null node value)");
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator++() {
|
void operator++() {
|
||||||
if(n == nullptr)
|
if(n->isLeaf())
|
||||||
return;
|
return;
|
||||||
if(n->right)
|
if(!n->right->isLeaf())
|
||||||
n = n->right->getMinChild();
|
n = n->right->getMinChild();
|
||||||
else {
|
else {
|
||||||
Node* p = n->parent;
|
Node* p = n->parent;
|
||||||
while(p != nullptr && n == p->right){
|
while(n == p->right){
|
||||||
n = p;
|
n = p;
|
||||||
p = p->parent;
|
p = p->parent;
|
||||||
}
|
}
|
||||||
@ -289,20 +292,21 @@ class RBTree {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using iterator = TreeIterator<std::pair<const TKey, TVal>>;
|
using iterator = TreeIterator<KVPair>;
|
||||||
using const_iterator = TreeIterator<std::pair<const TKey, const TVal>>;
|
using const_iterator = TreeIterator<const KVPair>;
|
||||||
|
|
||||||
RBTree() {}
|
RBTree() {}
|
||||||
|
|
||||||
~RBTree(){
|
~RBTree(){
|
||||||
delete root;
|
if(!root->isLeaf())
|
||||||
|
delete root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @param resultPtr nullable
|
/// @param resultPtr nullable
|
||||||
bool tryAdd(TKey key, TVal& value, TVal** resultPtr){
|
bool tryAdd(TKey key, TVal& value, TVal** resultPtr){
|
||||||
if(root == nullptr){
|
if(root == null_node_ptr){
|
||||||
root = new Node(key, value, Color::Black, nullptr);
|
root = new Node(key, value, Color::Black, null_node_ptr, null_node_ptr, null_node_ptr);
|
||||||
if(resultPtr)
|
if(resultPtr)
|
||||||
*resultPtr = &root->value;
|
*resultPtr = &root->value;
|
||||||
return true;
|
return true;
|
||||||
@ -316,14 +320,14 @@ public:
|
|||||||
else nodePtrPtr = &parent->right;
|
else nodePtrPtr = &parent->right;
|
||||||
|
|
||||||
// if a child node already exists at this place, returns false
|
// if a child node already exists at this place, returns false
|
||||||
if(*nodePtrPtr != nullptr){
|
if(*nodePtrPtr != null_node_ptr){
|
||||||
if(resultPtr)
|
if(resultPtr)
|
||||||
*resultPtr = nullptr;
|
*resultPtr = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// places newNode to left or right of the parent
|
// places newNode to left or right of the parent
|
||||||
Node* newNode = new Node(key, value, Color::Red, parent);
|
Node* newNode = new Node(key, value, Color::Red, parent, null_node_ptr, null_node_ptr);
|
||||||
if(resultPtr)
|
if(resultPtr)
|
||||||
*resultPtr = &newNode->value;
|
*resultPtr = &newNode->value;
|
||||||
*nodePtrPtr = newNode;
|
*nodePtrPtr = newNode;
|
||||||
@ -340,7 +344,7 @@ public:
|
|||||||
|
|
||||||
/// @param resultPtr nullable
|
/// @param resultPtr nullable
|
||||||
bool trySet(TKey key, TVal& value, TVal** resultPtr){
|
bool trySet(TKey key, TVal& value, TVal** resultPtr){
|
||||||
if(root == nullptr){
|
if(root == null_node_ptr){
|
||||||
if(resultPtr)
|
if(resultPtr)
|
||||||
*resultPtr = nullptr;
|
*resultPtr = nullptr;
|
||||||
return false;
|
return false;
|
||||||
@ -354,14 +358,14 @@ public:
|
|||||||
else nodePtrPtr = &parent->right;
|
else nodePtrPtr = &parent->right;
|
||||||
|
|
||||||
// if a child node with the given key doesn't exist, returns false
|
// if a child node with the given key doesn't exist, returns false
|
||||||
if(*nodePtrPtr == nullptr){
|
if(*nodePtrPtr == null_node_ptr){
|
||||||
if(resultPtr)
|
if(resultPtr)
|
||||||
*resultPtr = nullptr;
|
*resultPtr = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// replaces the value of left or right child of the parent
|
// replaces the value of left or right child of the parent
|
||||||
(*nodePtrPtr)->value = value;
|
(*nodePtrPtr)->value = value;
|
||||||
if(resultPtr)
|
if(resultPtr)
|
||||||
*resultPtr = &(*nodePtrPtr)->value;
|
*resultPtr = &(*nodePtrPtr)->value;
|
||||||
return true;
|
return true;
|
||||||
@ -375,8 +379,8 @@ public:
|
|||||||
|
|
||||||
/// @param resultPtr nullable
|
/// @param resultPtr nullable
|
||||||
void addOrSet(TKey key, TVal& value, TVal** resultPtr){
|
void addOrSet(TKey key, TVal& value, TVal** resultPtr){
|
||||||
if(root == nullptr){
|
if(root == null_node_ptr){
|
||||||
root = new Node(key, value, Color::Black, nullptr);
|
root = new Node(key, value, Color::Black, null_node_ptr, null_node_ptr, null_node_ptr);
|
||||||
if(resultPtr != nullptr)
|
if(resultPtr != nullptr)
|
||||||
*resultPtr = &root->value;
|
*resultPtr = &root->value;
|
||||||
return;
|
return;
|
||||||
@ -390,15 +394,15 @@ public:
|
|||||||
else nodePtrPtr = &parent->right;
|
else nodePtrPtr = &parent->right;
|
||||||
|
|
||||||
// if a child node already exists at this place, sets it's value
|
// if a child node already exists at this place, sets it's value
|
||||||
if(*nodePtrPtr != nullptr){
|
if(*nodePtrPtr != null_node_ptr){
|
||||||
(*nodePtrPtr)->value = value;
|
(*nodePtrPtr)->value = value;
|
||||||
if(resultPtr)
|
if(resultPtr)
|
||||||
*resultPtr = &(*nodePtrPtr)->value;
|
*resultPtr = &(*nodePtrPtr)->value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// places newNode to left or right of the parent
|
// places newNode to left or right of the parent
|
||||||
Node* newNode = new Node(key, value, Color::Red, parent);
|
Node* newNode = new Node(key, value, Color::Red, parent, null_node_ptr, null_node_ptr);
|
||||||
if(resultPtr != nullptr)
|
if(resultPtr != nullptr)
|
||||||
*resultPtr = &newNode->value;
|
*resultPtr = &newNode->value;
|
||||||
*nodePtrPtr = newNode;
|
*nodePtrPtr = newNode;
|
||||||
@ -416,14 +420,14 @@ public:
|
|||||||
if(!resultPtr)
|
if(!resultPtr)
|
||||||
return false;
|
return false;
|
||||||
Node* parent = findParentForKey(key);
|
Node* parent = findParentForKey(key);
|
||||||
Node* n = nullptr;
|
Node* n = null_node_ptr;
|
||||||
if(parent == nullptr)
|
if(parent == null_node_ptr)
|
||||||
n = root;
|
n = root;
|
||||||
else if(key < parent->key)
|
else if(key < parent->key)
|
||||||
n = parent->left;
|
n = parent->left;
|
||||||
else n = parent->right;
|
else n = parent->right;
|
||||||
// if there is no node with the given key
|
// if there is no node with the given key
|
||||||
if(n == nullptr){
|
if(n == null_node_ptr){
|
||||||
*resultPtr = nullptr;
|
*resultPtr = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -435,25 +439,25 @@ public:
|
|||||||
|
|
||||||
bool tryDelete(TKey key){
|
bool tryDelete(TKey key){
|
||||||
Node* parent = findParentForKey(key);
|
Node* parent = findParentForKey(key);
|
||||||
Node* n = nullptr;
|
Node* n = null_node_ptr;
|
||||||
if(parent == nullptr)
|
if(parent == null_node_ptr)
|
||||||
n = root;
|
n = root;
|
||||||
else if(key < parent->key)
|
else if(key < parent->key)
|
||||||
n = parent->left;
|
n = parent->left;
|
||||||
else n = parent->right;
|
else n = parent->right;
|
||||||
// key not found
|
// key not found
|
||||||
if(n == nullptr){
|
if(n == null_node_ptr){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(n->left == nullptr){
|
if(n->left == null_node_ptr){
|
||||||
transplantNode(n, n->right);
|
transplantNode(n, n->right);
|
||||||
if(n->color == Color::Black && n->right != nullptr)
|
if(n->color == Color::Black && n->right != null_node_ptr)
|
||||||
fixupDeletion(n->right);
|
fixupDeletion(n->right);
|
||||||
}
|
}
|
||||||
else if(n->right == nullptr){
|
else if(n->right == null_node_ptr){
|
||||||
transplantNode(n, n->left);
|
transplantNode(n, n->left);
|
||||||
if(n->color == Color::Black && n->left != nullptr)
|
if(n->color == Color::Black && n->left != null_node_ptr)
|
||||||
fixupDeletion(n->left);
|
fixupDeletion(n->left);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -471,55 +475,63 @@ public:
|
|||||||
fixupDeletion(minNode->right);
|
fixupDeletion(minNode->right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// delete node without children
|
||||||
|
n->left = null_node_ptr;
|
||||||
|
n->right = null_node_ptr;
|
||||||
delete n;
|
delete n;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
iterator begin(){
|
iterator begin(){
|
||||||
if(root == nullptr)
|
if(root == null_node_ptr)
|
||||||
return iterator(nullptr);
|
return iterator(null_node_ptr);
|
||||||
return iterator(root->getMinChild());
|
return iterator(root->getMinChild());
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator end(){
|
iterator end(){
|
||||||
if(root == nullptr)
|
return iterator(null_node_ptr);
|
||||||
return iterator(nullptr);
|
|
||||||
return iterator(root->getMaxChild());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator begin() const {
|
const_iterator begin() const {
|
||||||
if(root == nullptr)
|
if(root == null_node_ptr)
|
||||||
return const_iterator(nullptr);
|
return const_iterator(null_node_ptr);
|
||||||
return const_iterator(root->getMinChild());
|
return const_iterator(root->getMinChild());
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator end() const {
|
const_iterator end() const {
|
||||||
return const_iterator(nullptr);
|
return const_iterator(null_node_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _generateGraphVizCodeForChildren(std::stringstream& ss, Node* n) const {
|
void _generateGraphVizCodeForChildren(std::stringstream& ss, Node* n) const {
|
||||||
if(!n)
|
if(n == null_node_ptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(n->color == Color::Red)
|
if(n->color == Color::Red)
|
||||||
ss<<" \""<<n->key<<"\" [color=red]\n";
|
ss<<" \""<<n->key<<"\" [color=red]\n";
|
||||||
if(n->left){
|
|
||||||
|
if(n->left == null_node_ptr){
|
||||||
|
ss<<" \""<<n->key<<"\" -> \"null\" [side=L]\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
ss<<" \""<<n->key<<"\" -> \""<<n->left->key<<"\" [side=L]\n";
|
ss<<" \""<<n->key<<"\" -> \""<<n->left->key<<"\" [side=L]\n";
|
||||||
_generateGraphVizCodeForChildren(ss, n->left);
|
_generateGraphVizCodeForChildren(ss, n->left);
|
||||||
}
|
}
|
||||||
else ss<<" \""<<n->key<<"\" -> \"null\" [side=L]\n";
|
|
||||||
if(n->right){
|
if(n->right == null_node_ptr){
|
||||||
|
ss<<" \""<<n->key<<"\" -> \"null\" [side=R]\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
ss<<" \""<<n->key<<"\" -> \""<<n->right->key<<"\" [side=R]\n";
|
ss<<" \""<<n->key<<"\" -> \""<<n->right->key<<"\" [side=R]\n";
|
||||||
_generateGraphVizCodeForChildren(ss, n->right);
|
_generateGraphVizCodeForChildren(ss, n->right);
|
||||||
}
|
}
|
||||||
else ss<<" \""<<n->key<<"\" -> \"null\" [side=R]\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string generateGraphVizCode() const {
|
std::string generateGraphVizCode() const {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss<<"digraph {\n"
|
ss<<"digraph {\n"
|
||||||
" node [style=filled,color=gray];\n";
|
" node [style=filled,color=gray];\n";
|
||||||
if(root == nullptr)
|
if(root == null_node_ptr)
|
||||||
ss<<" \"null\"\n";
|
ss<<" \"null\"\n";
|
||||||
else {
|
else {
|
||||||
ss<<" \"null-parent\" -> \""<<root->key<<"\"\n";
|
ss<<" \"null-parent\" -> \""<<root->key<<"\"\n";
|
||||||
@ -529,3 +541,10 @@ public:
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename TKey, typename TVal>
|
||||||
|
typename RBTree<TKey, TVal>::Node RBTree<TKey, TVal>::null_node;
|
||||||
|
|
||||||
|
template<typename TKey, typename TVal>
|
||||||
|
typename RBTree<TKey, TVal>::Node* RBTree<TKey, TVal>::null_node_ptr = &RBTree<TKey, TVal>::null_node;
|
||||||
|
|||||||
@ -11,7 +11,7 @@ void GraphEditor::drawNode(const GraphModel::Node& node){
|
|||||||
ImNodes::EndNodeTitleBar();
|
ImNodes::EndNodeTitleBar();
|
||||||
|
|
||||||
for(auto& a_p : node.getAttributes()){
|
for(auto& a_p : node.getAttributes()){
|
||||||
auto&& a = *a_p.second;
|
auto&& a = *a_p.value;
|
||||||
switch (a.type){
|
switch (a.type){
|
||||||
case GraphModel::Attribute::Type::Input:
|
case GraphModel::Attribute::Type::Input:
|
||||||
ImNodes::BeginInputAttribute(a.id);
|
ImNodes::BeginInputAttribute(a.id);
|
||||||
@ -140,11 +140,11 @@ void GraphEditor::draw(){
|
|||||||
ImNodes::BeginNodeEditor();
|
ImNodes::BeginNodeEditor();
|
||||||
// draw nodes
|
// draw nodes
|
||||||
for(auto& n_p : graph.getNodes()){
|
for(auto& n_p : graph.getNodes()){
|
||||||
drawNode(n_p.second);
|
drawNode(n_p.value);
|
||||||
}
|
}
|
||||||
// draw edges
|
// draw edges
|
||||||
for(auto& p : graph.getEdges()){
|
for(auto& p : graph.getEdges()){
|
||||||
ImNodes::Link(p.second.id, p.second.to_attr_id, p.second.from_attr_id);
|
ImNodes::Link(p.value.id, p.value.to_attr_id, p.value.from_attr_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImNodes::EndNodeEditor();
|
ImNodes::EndNodeEditor();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user