28 #ifndef _util_container_eavlmmap_h
29 #define _util_container_eavlmmap_h
32 # include <mpqc_config.h>
35 #include <util/misc/exenv.h>
36 #include <util/container/compare.h>
42 # define eavl_typename
44 # define eavl_typename typename
49 template <
class K,
class T>
61 template <
class K,
class T>
69 T*& rlink(T* n)
const {
return (n->*node_).rt; }
70 T* rlink(
const T* n)
const {
return (n->*node_).rt; }
71 T*& llink(T* n)
const {
return (n->*node_).lt; }
72 T* llink(
const T* n)
const {
return (n->*node_).lt; }
73 T*& uplink(T* n)
const {
return (n->*node_).up; }
74 T* uplink(
const T* n)
const {
return (n->*node_).up; }
75 int& balance(T* n)
const {
return (n->*node_).balance; }
76 int balance(
const T* n)
const {
return (n->*node_).balance; }
77 K& key(T* n)
const {
return (n->*node_).key; }
78 const K& key(
const T* n)
const {
return (n->*node_).key; }
79 int compare(T*n,T*m)
const {
return sc::compare(key(n), key(m)); }
80 int compare(T*n,
const K&m)
const {
return sc::compare(key(n), m); }
82 void adjust_balance_insert(T* A, T* child);
83 void adjust_balance_remove(T* A, T* child);
93 void operator++() { map_->next(node); }
94 void operator++(
int) { operator++(); }
96 {
return map_ == i.map_ && node == i.node; }
98 {
return !operator == (i); }
100 { map_ = i.map_; node = i.node; }
101 const K &key()
const {
return map_->key(node); }
102 T & operator *() {
return *node; }
103 T * operator->() {
return node; }
110 void clear_without_delete() { initialize(node_); }
111 void clear() { clear(root_); initialize(node_); }
114 T* find(
const K&)
const;
117 int height() {
return height(root_); }
119 void check_node(T*)
const;
121 T* start()
const {
return start_; }
122 void next(
const T*&)
const;
123 void next(T*&)
const;
125 iterator begin() {
return iterator(
this,start()); }
126 iterator end() {
return iterator(
this,0); }
129 void detailed_print()
const;
130 int length()
const {
return length_; }
134 template <
class K,
class T>
136 EAVLMMap<K,T>::find(
const K& key)
const
141 int cmp = compare(n, key);
142 if (cmp < 0) n = rlink(n);
143 else if (cmp > 0) n = llink(n);
150 template <
class K,
class T>
152 EAVLMMap<K,T>::remove(T* node)
158 if (node == start_) {
165 if (llink(node) == 0) {
167 rebalance_point = uplink(node);
169 if (q) uplink(q) = rebalance_point;
171 if (rebalance_point) {
172 if (rlink(rebalance_point) == node) rlink(rebalance_point) = q;
173 else llink(rebalance_point) = q;
177 else if (rlink(node) == 0) {
179 rebalance_point = uplink(node);
181 if (q) uplink(q) = rebalance_point;
183 if (rebalance_point) {
184 if (rlink(rebalance_point) == node) rlink(rebalance_point) = q;
185 else llink(rebalance_point) = q;
193 if (r == 0 || llink(r) != 0) {
194 ExEnv::errn() <<
"EAVLMMap::remove: inconsistency" << std::endl;
198 if (r == rlink(node)) {
199 llink(r) = llink(node);
200 if (llink(r)) uplink(llink(r)) = r;
201 balance(r) = balance(node);
208 rebalance_point = uplink(r);
210 if (llink(rebalance_point) == r) llink(rebalance_point) = q;
211 else rlink(rebalance_point) = q;
213 if (q) uplink(q) = rebalance_point;
215 balance(r) = balance(node);
216 rlink(r) = rlink(node);
217 llink(r) = llink(node);
218 if (rlink(r)) uplink(rlink(r)) = r;
219 if (llink(r)) uplink(llink(r)) = r;
222 T* up = uplink(node);
225 if (rlink(up) == node) rlink(up) = r;
228 if (up == 0) root_ = r;
234 if (rebalance_point &&
235 llink(rebalance_point) == 0 && rlink(rebalance_point) == 0) {
236 balance(rebalance_point) = 0;
238 rebalance_point = uplink(rebalance_point);
240 adjust_balance_remove(rebalance_point, q);
243 template <
class K,
class T>
245 EAVLMMap<K,T>::print()
const
247 for (T*n=start(); n; next(n)) {
248 int d = depth(n) + 1;
250 if (balance(n) == 1)
ExEnv::out0() <<
" (+)" << std::endl;
251 else if (balance(n) == -1)
ExEnv::out0() <<
" (-)" << std::endl;
252 else if (balance(n) == 0)
ExEnv::out0() <<
" (.)" << std::endl;
253 else ExEnv::out0() <<
" (" << balance(n) <<
")" << std::endl;
257 template <
class K,
class T>
259 EAVLMMap<K,T>::detailed_print()
const
261 for (T*n=start(); n; next(n)) {
262 int d = depth(n) + 1;
265 << key(n) << std::endl;
266 else if (balance(n) == -1)
ExEnv::out0() <<
" (-) "
267 << key(n) << std::endl;
269 << key(n) << std::endl;
271 << key(n) << std::endl;
275 template <
class K,
class T>
277 EAVLMMap<K,T>::depth(T*node)
const
287 template <
class K,
class T>
289 EAVLMMap<K,T>::check_node(T*n)
const
291 if (uplink(n) && uplink(n) == n) abort();
292 if (llink(n) && llink(n) == n) abort();
293 if (rlink(n) && rlink(n) == n) abort();
294 if (rlink(n) && rlink(n) == llink(n)) abort();
295 if (uplink(n) && uplink(n) == llink(n)) abort();
296 if (uplink(n) && uplink(n) == rlink(n)) abort();
297 if (uplink(n) && !(llink(uplink(n)) == n
298 || rlink(uplink(n)) == n)) abort();
301 template <
class K,
class T>
303 EAVLMMap<K,T>::clear(T*n)
311 template <
class K,
class T>
313 EAVLMMap<K,T>::height(T* node)
316 int rh = height(rlink(node)) + 1;
317 int lh = height(llink(node)) + 1;
321 template <
class K,
class T>
323 EAVLMMap<K,T>::check()
327 size_t computed_length = 0;
328 for (node = start(); node; next(node)) {
330 if (prev && compare(prev,node) > 0) {
331 ExEnv::errn() <<
"nodes out of order" << std::endl;
337 for (node = start(); node; next(node)) {
338 if (balance(node) != height(rlink(node)) - height(llink(node))) {
339 ExEnv::errn() <<
"balance inconsistency" << std::endl;
342 if (balance(node) < -1 || balance(node) > 1) {
343 ExEnv::errn() <<
"balance out of range" << std::endl;
347 if (length_ != computed_length) {
353 template <
class K,
class T>
355 EAVLMMap<K,T>::next(
const T*& node)
const
357 const T* r = rlink(node);
360 while ((r = llink(node))) node = r;
363 while ((r = uplink(node))) {
364 if (node == llink(r)) {
373 template <
class K,
class T>
375 EAVLMMap<K,T>::next(T*& node)
const
380 while ((r = llink(node))) node = r;
383 while ((r = uplink(node))) {
384 if (node == llink(r)) {
393 template <
class K,
class T>
395 EAVLMMap<K,T>::insert(T* n)
425 if (cmp < 0) p = llink(p);
435 if (cmp < 0) llink(prev_p) = n;
436 else rlink(prev_p) = n;
440 if (have_start) start_ = n;
444 adjust_balance_insert(prev_p, n);
448 template <
class K,
class T>
450 EAVLMMap<K,T>::adjust_balance_insert(T* A, T* child)
454 if (llink(A) == child) adjustment = -1;
456 int bal = balance(A) + adjustment;
460 else if (bal == -1 || bal == 1) {
462 adjust_balance_insert(uplink(A), A);
466 if (balance(B) == 1) {
471 uplink(B) = uplink(A);
473 if (rlink(A)) uplink(rlink(A)) = A;
474 if (llink(B)) uplink(llink(B)) = B;
475 if (uplink(B) == 0) root_ = B;
477 if (rlink(uplink(B)) == A) rlink(uplink(B)) = B;
478 else llink(uplink(B)) = B;
487 if (balance(X) == 1) {
491 else if (balance(X) == -1) {
500 uplink(X) = uplink(A);
503 if (rlink(A)) uplink(rlink(A)) = A;
504 if (llink(B)) uplink(llink(B)) = B;
505 if (uplink(X) == 0) root_ = X;
507 if (rlink(uplink(X)) == A) rlink(uplink(X)) = X;
508 else llink(uplink(X)) = X;
512 else if (bal == -2) {
514 if (balance(B) == -1) {
519 uplink(B) = uplink(A);
521 if (llink(A)) uplink(llink(A)) = A;
522 if (rlink(B)) uplink(rlink(B)) = B;
523 if (uplink(B) == 0) root_ = B;
525 if (llink(uplink(B)) == A) llink(uplink(B)) = B;
526 else rlink(uplink(B)) = B;
535 if (balance(X) == -1) {
539 else if (balance(X) == 1) {
548 uplink(X) = uplink(A);
551 if (llink(A)) uplink(llink(A)) = A;
552 if (rlink(B)) uplink(rlink(B)) = B;
553 if (uplink(X) == 0) root_ = X;
555 if (llink(uplink(X)) == A) llink(uplink(X)) = X;
556 else rlink(uplink(X)) = X;
562 template <
class K,
class T>
564 EAVLMMap<K,T>::adjust_balance_remove(T* A, T* child)
568 if (llink(A) == child) adjustment = 1;
569 else adjustment = -1;
570 int bal = balance(A) + adjustment;
573 adjust_balance_remove(uplink(A), A);
575 else if (bal == -1 || bal == 1) {
580 if (balance(B) == 0) {
585 uplink(B) = uplink(A);
587 if (rlink(A)) uplink(rlink(A)) = A;
588 if (llink(B)) uplink(llink(B)) = B;
589 if (uplink(B) == 0) root_ = B;
591 if (rlink(uplink(B)) == A) rlink(uplink(B)) = B;
592 else llink(uplink(B)) = B;
595 else if (balance(B) == 1) {
600 uplink(B) = uplink(A);
602 if (rlink(A)) uplink(rlink(A)) = A;
603 if (llink(B)) uplink(llink(B)) = B;
604 if (uplink(B) == 0) root_ = B;
606 if (rlink(uplink(B)) == A) rlink(uplink(B)) = B;
607 else llink(uplink(B)) = B;
609 adjust_balance_remove(uplink(B), B);
617 if (balance(X) == 0) {
621 else if (balance(X) == 1) {
630 uplink(X) = uplink(A);
633 if (rlink(A)) uplink(rlink(A)) = A;
634 if (llink(B)) uplink(llink(B)) = B;
635 if (uplink(X) == 0) root_ = X;
637 if (rlink(uplink(X)) == A) rlink(uplink(X)) = X;
638 else llink(uplink(X)) = X;
640 adjust_balance_remove(uplink(X), X);
643 else if (bal == -2) {
645 if (balance(B) == 0) {
650 uplink(B) = uplink(A);
652 if (llink(A)) uplink(llink(A)) = A;
653 if (rlink(B)) uplink(rlink(B)) = B;
654 if (uplink(B) == 0) root_ = B;
656 if (llink(uplink(B)) == A) llink(uplink(B)) = B;
657 else rlink(uplink(B)) = B;
660 else if (balance(B) == -1) {
665 uplink(B) = uplink(A);
667 if (llink(A)) uplink(llink(A)) = A;
668 if (rlink(B)) uplink(rlink(B)) = B;
669 if (uplink(B) == 0) root_ = B;
671 if (llink(uplink(B)) == A) llink(uplink(B)) = B;
672 else rlink(uplink(B)) = B;
674 adjust_balance_remove(uplink(B), B);
682 if (balance(X) == 0) {
686 else if (balance(X) == -1) {
695 uplink(X) = uplink(A);
698 if (llink(A)) uplink(llink(A)) = A;
699 if (rlink(B)) uplink(rlink(B)) = B;
700 if (uplink(X) == 0) root_ = X;
702 if (llink(uplink(X)) == A) llink(uplink(X)) = X;
703 else rlink(uplink(X)) = X;
705 adjust_balance_remove(uplink(X), X);
710 template <
class K,
class T>
712 EAVLMMap<K,T>::EAVLMMap()
717 template <
class K,
class T>
719 EAVLMMap<K,T>::EAVLMMap(EAVLMMapNode<K,T> T::* node)
724 template <
class K,
class T>
726 EAVLMMap<K,T>::initialize(EAVLMMapNode<K,T> T::* node)