Elm  2
ELM is a library providing generic data structures, OS-independent interface, plugins and XML.
GenTree.h
1 /*
2  * avl::GenTree class interface
3  *
4  * This file is part of OTAWA
5  * Copyright (c) 2008, IRIT UPS.
6  *
7  * OTAWA is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * OTAWA is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with OTAWA; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 #ifndef ELM_AVL_GENTREE_H
22 #define ELM_AVL_GENTREE_H
23 
24 #include <elm/utility.h>
25 #include <elm/PreIterator.h>
26 #include <elm/adapter.h>
27 #include <elm/array.h>
28 #include <elm/data/StaticStack.h>
29 #include <elm/data/Vector.h>
30 #include <elm/io.h>
31 
32 // uncomment for testing
33 //#define ELM_AVL_INVARIANT
34 
35 namespace elm { namespace avl {
36 
37 // Private class
38 class AbstractTree {
39  friend class Invariant;
40 public:
41  inline int count(void) const { return _cnt; }
42 
43 protected:
44  static const int MAX_HEIGHT = 32;
45  typedef signed char balance_t;
46  typedef enum {
47  LEFT = -1,
48  NONE = 0,
49  RIGHT = +1
50  } dir_t;
51 
52  inline AbstractTree(void): _root(nullptr), _cnt(0) { }
53 
54  class Node {
55  public:
56  inline Node(void): _left(nullptr), _right(nullptr), _bal(0) { }
59  };
60 
61  class Stack: public StaticStack<Pair<Node *, dir_t>, MAX_HEIGHT> {
62  public:
63  inline Stack(void) { }
64  inline void push(Node *node, dir_t dir)
66  inline dir_t topDir(void) const { return this->top().snd; }
67  inline Node *topNode(void) const { return this->top().fst; }
68  };
69 
70  Node **link(const Stack& s);
71  void exchange(Node *n, Node *m);
72  void insert(Stack& stack, Node *node);
73  void rotateRight(Stack& s);
74  void rotateLeft(Stack& s);
75  void remove(Stack& stack, Node *n);
76  Node *leftMost(Stack& s, Node *n);
77 
79  int _cnt;
80 
81 # ifdef ELM_AVL_INVARIANT
82  public:
83  virtual ~AbstractTree() { }
84  virtual int cmp(Node *n1, Node *n2) const = 0;
85  virtual void print(io::Output& out, Node *n) const = 0;
86  bool invariant(Node *n, int& h, Node *& max, Node *& min);
87  bool invariant(Node *n);
88  Node *pointed(const Stack& s) const;
89  void printTree(io::Output& out, Node *n, t::uint32 m, int l, dir_t d) const;
90  void printTree(io::Output& out, Node *n);
91  void printTree(io::Output& out);
92 # endif
93 };
94 
95 // GenAVLTree class
96 template <class T, class K = IdAdapter<T>, class C = elm::Comparator<typename K::key_t>, class A = DefaultAlloc>
97 class GenTree: public AbstractTree, public C, public A {
98 protected:
99 
100  class Node: public AbstractTree::Node {
101  public:
102  inline Node(const T& item): data(item) { }
103  inline Node(const Node *node): data(node->data) { _bal = node->_bal; }
104  inline Node *left(void) { return static_cast<Node *>(_left); }
105  inline Node *right(void) { return static_cast<Node *>(_right); }
106  inline const typename K::key_t& key(void) const { return K::key(data); }
107  T data;
108  inline static void *operator new(size_t s, A *a) { return a->allocate(s); }
109  inline void free(A& a) { this->~Node(); a.free(this); }
110  };
111 
112  inline Node *root(void) const { return static_cast<Node *>(_root); }
113 
114  class Stack: public AbstractTree::Stack {
115  public:
116  inline Node *topNode(void) const { return static_cast<Node *>(AbstractTree::Stack::topNode()); }
117  };
118 
119  class VisitStack: public StaticStack<Node *, MAX_HEIGHT> {
120  public:
121  inline VisitStack(void) { }
122  inline VisitStack(Node *n) { this->push(n); }
123  inline void copyLeft(A *a, VisitStack& s)
124  { s.top()->_left = new(a) Node(this->top()->left()); s.push(s.top()->left()); this->push(this->top()->left()); }
125  inline void copyRight(A *a, VisitStack& s)
126  { s.top()->_right = new(a) Node(this->top()->right()); s.push(s.top()->right()); this->push(this->top()->right()); }
127  };
128 
129 public:
130  typedef T t;
132 
133  GenTree(void) { }
134  GenTree(const GenTree<T>& tree) { copy(tree); }
135  ~GenTree(void) { clear(); }
136  inline const C& comparator() const { return *this; }
137  inline C& comparator() { return *this; }
138  inline const A& allocator() const { return *this; }
139  inline A& allocator() { return *this; }
140 
141  inline T *get(const typename K::key_t& key)
142  { Node *node = find(key); if(!node) return 0; else return &node->data; }
143  inline const T *get(const typename K::key_t& key) const
144  { const Node *node = find(key); if(!node) return 0; else return &node->data; }
145  void set(const T& item)
146  { add(item); }
147 
148  void removeByKey(const typename K::key_t& item) {
149  Stack s;
150  Node *n = lookup(s, item);
151  if(n == nullptr)
152  return;
153  remove(s, n);
154  }
155 
156  // Collection concept
157  inline int count(void) const { return _cnt; }
158  inline bool contains(const typename K::key_t& item) const { return find(item) != nullptr; }
159  template <class CC>
160  inline bool containsAll(const CC& c) const
161  { for(const auto x: c) if(!contains(x)) return false; return true; }
162  inline bool isEmpty(void) const { return _cnt == 0; }
163  inline operator bool(void) const { return !isEmpty(); }
164 
165  class Iter: public PreIterator<Iter, const T&> {
166  public:
167  inline Iter() { }
168  inline Iter(const self_t& tree)
169  { if(tree.root()) visit(tree.root()); }
170  inline bool ended(void) const { return s.isEmpty(); }
171  void next(void) {
172  while(true) {
173  Node *last = s.pop();
174  if(ended()) return;
175  if(last == s.top()->left()) { s.push(s.top()); break; }
176  else if(last == s.top() && s.top()->right()) { visit(s.top()->right()); break; }
177  }
178  }
179  inline const T& item(void) const { return s.top()->data; }
180  inline bool equals(const Iter& i) const { return s.equals(i.s); }
181  protected:
182  inline T& data(void) { return s.top()->data; }
183  private:
184  void visit(Node *node) {
185  if(!node) return;
186  s.push(node);
187  while(s.top()->left()) s.push(s.top()->left());
188  s.push(s.top());
189  }
190  VisitStack s;
191  };
192  inline Iter begin(void) const { return Iter(*this); }
193  inline Iter end(void) const { return Iter(); }
194 
195  bool equals(const GenTree<T, K, C>& tree) const {
196  typename GenTree<T, K, C>::Iter ai(*this), bi(tree);
197  for(; ai() && bi(); ai++, bi++)
198  if(!(C::doCompare(K::key(*ai), K::key(*bi)) == 0))
199  return false;
200  return !ai && !bi;
201  }
202  inline bool operator==(const GenTree<T, K, C>& tree) const { return equals(tree); }
203  inline bool operator!=(const GenTree<T, K, C>& tree) const { return !equals(tree); }
204 
205  // MutableCollection concept
206  void clear(void) {
207  VisitStack s;
208  if(root() != nullptr)
209  s.push(root());
210  while(!s.isEmpty()) {
211  Node *n = s.pop();
212  if(n->left() != nullptr)
213  s.push(n->left());
214  if(n->right() != nullptr)
215  s.push(n->right());
216  n->free(*this);
217  }
218  _root = nullptr;
219  _cnt = 0;
220  }
221 
222  void add(const T& item) {
223  Stack s;
224  Node *n = lookup(s, K::key(item));
225  if(n == nullptr)
226  AbstractTree::insert(s, new(this) Node(item));
227  }
228 
229  template <class CC> inline void addAll(const CC& c)
230  { for(const auto x: c) add(x); }
231 
232  inline void remove(const T& x) { removeByKey(K::key(x)); }
233 
234  template <class CC> inline void removeAll(const CC& c)
235  { for(const auto x: c) remove(x); }
236 
237  inline void remove(const Iter& iter) { remove(iter.item()); }
238 
239  inline self_t& operator+=(const T& x) { add(x); return *this; }
240  inline self_t& operator-=(const T& x) { remove(x); return *this; }
241 
242  void copy(const GenTree<T, K, C>& tree) {
243  clear();
244  if(tree._root == nullptr)
245  return;
246  _root = new(this) Node(tree.root());
247  _cnt = tree._cnt;
248  VisitStack ss(tree.root()), st(root());
249  while(!ss.isEmpty()) {
250  if(ss.top()->left() != nullptr)
251  ss.copyLeft(this, st);
252  else {
253  while(ss.top()->right() == nullptr) {
254  Node *prv;
255  do {
256  prv = ss.pop();
257  st.pop();
258  if(ss.isEmpty())
259  return;
260  }
261  while(ss.top()->right() == prv);
262  }
263  ss.copyRight(this, st);
264  }
265  }
266  }
267  inline GenTree<T, K, C>& operator=(const GenTree<T, K, C>& tree) { copy(tree); return *this; }
268 
269 # ifdef ELM_AVL_INVARIANT
270  int cmp(AbstractTree::Node *n1, AbstractTree::Node *n2) const override {
271  return compare(static_cast<Node *>(n1)->key(), static_cast<Node *>(n2)->key());
272  }
273  void print(io::Output& out, AbstractTree::Node *n) const override {
274  out << static_cast<Node *>(n)->key();
275  }
276 # endif
277 
278 protected:
279 
280  inline void remove(Stack& s, Node *n) {
281 
282  // simple leaf cases
283  if(n->left() == nullptr)
284  AbstractTree::remove(s, n->right());
285  else if(n->right() == nullptr)
286  AbstractTree::remove(s, n->left());
287 
288  // in middle case
289  else {
290  s.push(n, RIGHT);
291  Node *p = static_cast<Node *>(leftMost(s, n->right()));
292  exchange(p, n);
293  AbstractTree::remove(s, p->right());
294  p->free(*this);
295  }
296 
297  }
298 
299  inline int compare(const typename K::key_t& k1, const typename K::key_t& k2) const
300  { return C::compare(k1, k2); }
301 
302  Node *lookup(Stack& s, const typename K::key_t& key) const {
303  Node *p = root();
304  while(p != nullptr) {
305  int cmp = compare(key, K::key(p->data));
306  if(cmp == 0)
307  break;
308  else if(cmp < 0) {
309  s.push(p, LEFT);
310  p = p->left();
311  }
312  else {
313  s.push(p, RIGHT);
314  p = p->right();
315  }
316  }
317  return p;
318  }
319 
320  Node *find(const typename K::key_t& key) const {
321  for(Node *p = root(); p;) {
322  int cmp = compare(key, p->key());
323  if(cmp < 0)
324  p = p->left();
325  else if(cmp > 0)
326  p = p->right();
327  else
328  return p;
329  }
330  return nullptr;
331  }
332 
333  void exchange(Node *n, Node *p) {
334  auto t = p->data;
335  p->data = n->data;
336  n->data = t;
337  }
338 
339 };
340 
341 } } // elm::avl
342 
343 #endif // ELM_AVL_GENTREE_H
elm::avl::GenTree::root
Node * root(void) const
Definition: GenTree.h:112
elm::avl::AbstractTree::insert
void insert(Stack &stack, Node *node)
Definition: avl_GenTree.cpp:256
elm::avl::GenTree::VisitStack::VisitStack
VisitStack(void)
Definition: GenTree.h:121
elm::avl::GenTree::operator!=
bool operator!=(const GenTree< T, K, C > &tree) const
Definition: GenTree.h:203
elm::avl::GenTree::VisitStack::copyLeft
void copyLeft(A *a, VisitStack &s)
Definition: GenTree.h:123
elm::avl::GenTree::operator+=
self_t & operator+=(const T &x)
Definition: GenTree.h:239
elm::avl::AbstractTree::exchange
void exchange(Node *n, Node *m)
Definition: avl_GenTree.cpp:195
elm::t::out
typename type_info< T >::out_t out
Definition: type_info.h:284
elm::avl::GenTree::remove
void remove(const T &x)
Definition: GenTree.h:232
elm::iter
Definition: util_WAHVector.cpp:157
elm::avl::AbstractTree::Node
Definition: GenTree.h:54
elm::io::p
Printable< T, M > p(const T &data, const M &man)
Definition: Output.h:302
elm::avl::GenTree::get
const T * get(const typename K::key_t &key) const
Definition: GenTree.h:143
elm::avl::GenTree::operator-=
self_t & operator-=(const T &x)
Definition: GenTree.h:240
elm::avl::GenTree::contains
bool contains(const typename K::key_t &item) const
Definition: GenTree.h:158
elm::avl::GenTree::allocator
A & allocator()
Definition: GenTree.h:139
elm::avl::GenTree::Node::right
Node * right(void)
Definition: GenTree.h:105
elm::avl::GenTree::remove
void remove(Stack &s, Node *n)
Definition: GenTree.h:280
elm::avl::AbstractTree::count
int count(void) const
Definition: GenTree.h:41
elm::avl::GenTree::Node::data
T data
Definition: GenTree.h:107
elm::avl::AbstractTree::Node::_right
Node * _right
Definition: GenTree.h:57
elm::avl::AbstractTree::RIGHT
@ RIGHT
Definition: GenTree.h:49
elm::StaticStack::isEmpty
bool isEmpty(void) const
Definition: StaticStack.h:41
elm::pair
Pair< T1, T2 > pair(const T1 &v1, const T2 &v2)
Definition: Pair.h:63
elm::avl::AbstractTree::leftMost
Node * leftMost(Stack &s, Node *n)
Definition: avl_GenTree.cpp:443
elm::Pair::snd
T2 snd
Definition: Pair.h:36
elm::avl::AbstractTree::_root
Node * _root
Definition: GenTree.h:78
elm::avl::AbstractTree::MAX_HEIGHT
static const int MAX_HEIGHT
Definition: GenTree.h:44
elm::max
const T & max(const T &x, const T &y)
Definition: compare.h:108
elm::avl::GenTree::Node::Node
Node(const T &item)
Definition: GenTree.h:102
elm::avl::GenTree::Iter::next
void next(void)
Definition: GenTree.h:171
elm::avl::GenTree::comparator
const C & comparator() const
Definition: GenTree.h:136
elm::avl::GenTree::Iter::equals
bool equals(const Iter &i) const
Definition: GenTree.h:180
elm::StaticStack::pop
const T & pop(void)
Definition: StaticStack.h:43
elm::avl::AbstractTree::Node::_left
Node * _left
Definition: GenTree.h:57
elm::avl::GenTree::removeAll
void removeAll(const CC &c)
Definition: GenTree.h:234
elm::avl::GenTree::Iter
Definition: GenTree.h:165
elm::avl::GenTree::begin
Iter begin(void) const
Definition: GenTree.h:192
elm::avl::GenTree::isEmpty
bool isEmpty(void) const
Definition: GenTree.h:162
elm::avl::AbstractTree::balance_t
signed char balance_t
Definition: GenTree.h:45
elm::avl::GenTree::find
Node * find(const typename K::key_t &key) const
Definition: GenTree.h:320
elm::avl::GenTree::count
int count(void) const
Definition: GenTree.h:157
bool
elm::avl::GenTree::VisitStack::VisitStack
VisitStack(Node *n)
Definition: GenTree.h:122
elm::min
const T & min(const T &x, const T &y)
Definition: compare.h:104
elm::avl::GenTree::Stack
Definition: GenTree.h:114
elm::avl::AbstractTree::_cnt
int _cnt
Definition: GenTree.h:79
elm::avl::GenTree::VisitStack
Definition: GenTree.h:119
elm::avl::GenTree::clear
void clear(void)
Definition: GenTree.h:206
elm::avl::AbstractTree::AbstractTree
AbstractTree(void)
Definition: GenTree.h:52
elm::avl::GenTree::~GenTree
~GenTree(void)
Definition: GenTree.h:135
elm::avl::GenTree::Iter::item
const T & item(void) const
Definition: GenTree.h:179
elm::avl::AbstractTree::dir_t
dir_t
Definition: GenTree.h:46
elm::avl::AbstractTree::Stack
Definition: GenTree.h:61
elm::avl::GenTree::Node
Definition: GenTree.h:100
elm::avl::GenTree::Node::Node
Node(const Node *node)
Definition: GenTree.h:103
elm::Comparator::t
T t
Definition: compare.h:36
elm::avl::GenTree::Stack::topNode
Node * topNode(void) const
Definition: GenTree.h:116
elm::avl::GenTree::Node::key
const K::key_t & key(void) const
Definition: GenTree.h:106
elm::avl::AbstractTree::Stack::Stack
Stack(void)
Definition: GenTree.h:63
elm
Definition: adapter.h:26
elm::avl::AbstractTree
Definition: GenTree.h:38
elm::avl::GenTree::get
T * get(const typename K::key_t &key)
Definition: GenTree.h:141
elm::avl::GenTree::t
T t
Definition: GenTree.h:130
elm::avl::GenTree::end
Iter end(void) const
Definition: GenTree.h:193
elm::avl::GenTree::containsAll
bool containsAll(const CC &c) const
Definition: GenTree.h:160
elm::avl::AbstractTree::rotateRight
void rotateRight(Stack &s)
Definition: avl_GenTree.cpp:213
elm::avl::GenTree::addAll
void addAll(const CC &c)
Definition: GenTree.h:229
elm::avl::GenTree::Iter::data
T & data(void)
Definition: GenTree.h:182
elm::avl::GenTree::Iter::Iter
Iter()
Definition: GenTree.h:167
elm::avl::GenTree::add
void add(const T &item)
Definition: GenTree.h:222
elm::avl::GenTree::GenTree
GenTree(void)
Definition: GenTree.h:133
elm::avl::GenTree::self_t
GenTree< T, K, C, A > self_t
Definition: GenTree.h:131
elm::avl::AbstractTree::Node::_bal
balance_t _bal
Definition: GenTree.h:58
elm::StaticStack
Definition: StaticStack.h:31
elm::avl::GenTree::comparator
C & comparator()
Definition: GenTree.h:137
elm::avl::GenTree::allocator
const A & allocator() const
Definition: GenTree.h:138
elm::avl::GenTree::VisitStack::copyRight
void copyRight(A *a, VisitStack &s)
Definition: GenTree.h:125
elm::avl::GenTree::Iter::Iter
Iter(const self_t &tree)
Definition: GenTree.h:168
elm::avl::GenTree::equals
bool equals(const GenTree< T, K, C > &tree) const
Definition: GenTree.h:195
elm::avl::AbstractTree::NONE
@ NONE
Definition: GenTree.h:48
elm::t::uint32
unsigned int uint32
Definition: arch.h:31
elm::avl::GenTree::compare
int compare(const typename K::key_t &k1, const typename K::key_t &k2) const
Definition: GenTree.h:299
elm::avl::GenTree::Node::free
void free(A &a)
Definition: GenTree.h:109
elm::avl::AbstractTree::remove
void remove(Stack &stack, Node *n)
Definition: avl_GenTree.cpp:318
elm::avl::AbstractTree::Stack::topDir
dir_t topDir(void) const
Definition: GenTree.h:66
elm::avl::GenTree
Definition: GenTree.h:97
elm::avl::GenTree::exchange
void exchange(Node *n, Node *p)
Definition: GenTree.h:333
elm::avl::GenTree::Iter::ended
bool ended(void) const
Definition: GenTree.h:170
elm::avl::AbstractTree::rotateLeft
void rotateLeft(Stack &s)
Definition: avl_GenTree.cpp:234
elm::avl::GenTree::copy
void copy(const GenTree< T, K, C > &tree)
Definition: GenTree.h:242
elm::avl::GenTree::set
void set(const T &item)
Definition: GenTree.h:145
elm::avl::AbstractTree::Node::Node
Node(void)
Definition: GenTree.h:56
elm::avl::AbstractTree::Stack::push
void push(Node *node, dir_t dir)
Definition: GenTree.h:64
elm::avl::AbstractTree::LEFT
@ LEFT
Definition: GenTree.h:47
elm::avl::GenTree::remove
void remove(const Iter &iter)
Definition: GenTree.h:237
elm::io::right
IntFormat right(IntFormat fmt)
Definition: Output.h:264
elm::io::left
IntFormat left(IntFormat fmt)
Definition: Output.h:263
elm::avl::GenTree::removeByKey
void removeByKey(const typename K::key_t &item)
Definition: GenTree.h:148
elm::PreIterator
Definition: iter.h:28
elm::io::Output
Definition: Output.h:179
elm::avl::AbstractTree::Stack::topNode
Node * topNode(void) const
Definition: GenTree.h:67
elm::avl::AbstractTree::link
Node ** link(const Stack &s)
Definition: avl_GenTree.cpp:180
elm::avl::GenTree::operator==
bool operator==(const GenTree< T, K, C > &tree) const
Definition: GenTree.h:202
elm::avl::GenTree::operator=
GenTree< T, K, C > & operator=(const GenTree< T, K, C > &tree)
Definition: GenTree.h:267
elm::avl::AbstractTree::Invariant
friend class Invariant
Definition: GenTree.h:39
elm::avl::GenTree::lookup
Node * lookup(Stack &s, const typename K::key_t &key) const
Definition: GenTree.h:302
elm::StaticStack< Node *, MAX_HEIGHT >::push
void push(const Node * &v)
Definition: StaticStack.h:44
elm::StaticStack< Pair< Node *, dir_t >, MAX_HEIGHT >::top
const Pair< Node *, dir_t > & top(void) const
Definition: StaticStack.h:42
elm::StaticStack::equals
bool equals(const StaticStack< T, N > &s) const
Definition: StaticStack.h:71
elm::avl::GenTree::Node::left
Node * left(void)
Definition: GenTree.h:104
elm::avl::GenTree::GenTree
GenTree(const GenTree< T > &tree)
Definition: GenTree.h:134
elm::Pair::fst
T1 fst
Definition: Pair.h:35