MPQC 3.0.0-alpha
Loading...
Searching...
No Matches
eavlmmap.h
1//
2// eavlmmap.h --- definition for embedded avl multimap class
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Curtis Janssen <cljanss@limitpt.com>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28#ifndef _util_container_eavlmmap_h
29#define _util_container_eavlmmap_h
30
31#ifdef HAVE_CONFIG_H
32# include <mpqc_config.h>
33#endif
34#include <iostream>
35#include <util/misc/exenv.h>
36#include <util/container/compare.h>
37#include <unistd.h> // for size_t on solaris
38#include <stdlib.h>
39
40#ifdef __GNUC__
41// gcc typename seems to be broken in some cases
42# define eavl_typename
43#else
44# define eavl_typename typename
45#endif
46
47namespace sc {
48
49template <class K, class T>
51 public:
52 K key;
53 T* lt;
54 T* rt;
55 T* up;
56 int balance;
57 public:
58 EAVLMMapNode(const K& k): key(k) {}
59};
60
61template <class K, class T>
62class EAVLMMap {
63 private:
64 size_t length_;
65 T *root_;
66 T *start_;
67 EAVLMMapNode<K,T> T::* node_;
68 public:
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); }
81 private:
82 void adjust_balance_insert(T* A, T* child);
83 void adjust_balance_remove(T* A, T* child);
84 void clear(T*);
85 public:
86 class iterator {
87 private:
88 EAVLMMap<K,T> *map_;
89 T *node;
90 public:
91 iterator(EAVLMMap<K,T> *m, T *n):map_(m),node(n){}
92 iterator(const eavl_typename EAVLMMap<K,T>::iterator &i) { map_=i.map_; node=i.node; }
93 void operator++() { map_->next(node); }
94 void operator++(int) { operator++(); }
95 int operator == (const eavl_typename EAVLMMap<K,T>::iterator &i) const
96 { return map_ == i.map_ && node == i.node; }
97 int operator != (const eavl_typename EAVLMMap<K,T>::iterator &i) const
98 { return !operator == (i); }
99 void operator = (const eavl_typename EAVLMMap<K,T>::iterator &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; }
104 };
105 public:
106 EAVLMMap();
107 EAVLMMap(EAVLMMapNode<K,T> T::* node);
108 ~EAVLMMap() { clear(root_); }
109 void initialize(EAVLMMapNode<K,T> T::* node);
110 void clear_without_delete() { initialize(node_); }
111 void clear() { clear(root_); initialize(node_); }
112 void insert(T*);
113 void remove(T*);
114 T* find(const K&) const;
115
116 int height(T* node);
117 int height() { return height(root_); }
118 void check();
119 void check_node(T*) const;
120
121 T* start() const { return start_; }
122 void next(const T*&) const;
123 void next(T*&) const;
124
125 iterator begin() { return iterator(this,start()); }
126 iterator end() { return iterator(this,0); }
127
128 void print() const;
129 void detailed_print() const;
130 int length() const { return length_; }
131 int depth(T*) const;
132};
133
134template <class K, class T>
135T*
136EAVLMMap<K,T>::find(const K& key) const
137{
138 T* n = root_;
139
140 while (n) {
141 int cmp = compare(n, key);
142 if (cmp < 0) n = rlink(n);
143 else if (cmp > 0) n = llink(n);
144 else return n;
145 }
146
147 return 0;
148}
149
150template <class K, class T>
151void
152EAVLMMap<K,T>::remove(T* node)
153{
154 if (!node) return;
155
156 length_--;
157
158 if (node == start_) {
159 next(start_);
160 }
161
162 T *rebalance_point;
163 T *q;
164
165 if (llink(node) == 0) {
166 q = rlink(node);
167 rebalance_point = uplink(node);
168
169 if (q) uplink(q) = rebalance_point;
170
171 if (rebalance_point) {
172 if (rlink(rebalance_point) == node) rlink(rebalance_point) = q;
173 else llink(rebalance_point) = q;
174 }
175 else root_ = q;
176 }
177 else if (rlink(node) == 0) {
178 q = llink(node);
179 rebalance_point = uplink(node);
180
181 if (q) uplink(q) = rebalance_point;
182
183 if (rebalance_point) {
184 if (rlink(rebalance_point) == node) rlink(rebalance_point) = q;
185 else llink(rebalance_point) = q;
186 }
187 else root_ = q;
188 }
189 else {
190 T *r = node;
191 next(r);
192
193 if (r == 0 || llink(r) != 0) {
194 ExEnv::errn() << "EAVLMMap::remove: inconsistency" << std::endl;
195 abort();
196 }
197
198 if (r == rlink(node)) {
199 llink(r) = llink(node);
200 if (llink(r)) uplink(llink(r)) = r;
201 balance(r) = balance(node);
202 rebalance_point = r;
203 q = rlink(r);
204 }
205 else {
206 q = rlink(r);
207
208 rebalance_point = uplink(r);
209
210 if (llink(rebalance_point) == r) llink(rebalance_point) = q;
211 else rlink(rebalance_point) = q;
212
213 if (q) uplink(q) = rebalance_point;
214
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;
220 }
221 if (r) {
222 T* up = uplink(node);
223 uplink(r) = up;
224 if (up) {
225 if (rlink(up) == node) rlink(up) = r;
226 else llink(up) = r;
227 }
228 if (up == 0) root_ = r;
229 }
230 }
231
232 // adjust balance won't work if both children are null,
233 // so handle this special case here
234 if (rebalance_point &&
235 llink(rebalance_point) == 0 && rlink(rebalance_point) == 0) {
236 balance(rebalance_point) = 0;
237 q = rebalance_point;
238 rebalance_point = uplink(rebalance_point);
239 }
240 adjust_balance_remove(rebalance_point, q);
241}
242
243template <class K, class T>
244void
245EAVLMMap<K,T>::print() const
246{
247 for (T*n=start(); n; next(n)) {
248 int d = depth(n) + 1;
249 for (int i=0; i<d; i++) ExEnv::out0() << " ";
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;
254 }
255}
256
257template <class K, class T>
258void
259EAVLMMap<K,T>::detailed_print() const
260{
261 for (T*n=start(); n; next(n)) {
262 int d = depth(n) + 1;
263 for (int i=0; i<d; i++) ExEnv::out0() << " ";
264 if (balance(n) == 1) ExEnv::out0() << " (+) "
265 << key(n) << std::endl;
266 else if (balance(n) == -1) ExEnv::out0() << " (-) "
267 << key(n) << std::endl;
268 else if (balance(n) == 0) ExEnv::out0() << " (.) "
269 << key(n) << std::endl;
270 else ExEnv::out0() << " (" << balance(n) << ") "
271 << key(n) << std::endl;
272 }
273}
274
275template <class K, class T>
276int
277EAVLMMap<K,T>::depth(T*node) const
278{
279 int d = 0;
280 while (node) {
281 node = uplink(node);
282 d++;
283 }
284 return d;
285}
286
287template <class K, class T>
288void
289EAVLMMap<K,T>::check_node(T*n) const
290{
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();
299}
300
301template <class K, class T>
302void
303EAVLMMap<K,T>::clear(T*n)
304{
305 if (!n) return;
306 clear(llink(n));
307 clear(rlink(n));
308 delete n;
309}
310
311template <class K, class T>
312int
313EAVLMMap<K,T>::height(T* node)
314{
315 if (!node) return 0;
316 int rh = height(rlink(node)) + 1;
317 int lh = height(llink(node)) + 1;
318 return rh>lh?rh:lh;
319}
320
321template <class K, class T>
322void
323EAVLMMap<K,T>::check()
324{
325 T* node;
326 T* prev=0;
327 size_t computed_length = 0;
328 for (node = start(); node; next(node)) {
329 check_node(node);
330 if (prev && compare(prev,node) > 0) {
331 ExEnv::errn() << "nodes out of order" << std::endl;
332 abort();
333 }
334 prev = node;
335 computed_length++;
336 }
337 for (node = start(); node; next(node)) {
338 if (balance(node) != height(rlink(node)) - height(llink(node))) {
339 ExEnv::errn() << "balance inconsistency" << std::endl;
340 abort();
341 }
342 if (balance(node) < -1 || balance(node) > 1) {
343 ExEnv::errn() << "balance out of range" << std::endl;
344 abort();
345 }
346 }
347 if (length_ != computed_length) {
348 ExEnv::errn() << "length error" << std::endl;
349 abort();
350 }
351}
352
353template <class K, class T>
354void
355EAVLMMap<K,T>::next(const T*& node) const
356{
357 const T* r = rlink(node);
358 if (r) {
359 node = r;
360 while ((r = llink(node))) node = r;
361 return;
362 }
363 while ((r = uplink(node))) {
364 if (node == llink(r)) {
365 node = r;
366 return;
367 }
368 node = r;
369 }
370 node = 0;
371}
372
373template <class K, class T>
374void
375EAVLMMap<K,T>::next(T*& node) const
376{
377 T* r = rlink(node);
378 if (r) {
379 node = r;
380 while ((r = llink(node))) node = r;
381 return;
382 }
383 while ((r = uplink(node))) {
384 if (node == llink(r)) {
385 node = r;
386 return;
387 }
388 node = r;
389 }
390 node = 0;
391}
392
393template <class K, class T>
394void
395EAVLMMap<K,T>::insert(T* n)
396{
397 if (!n) {
398 return;
399 }
400
401 length_++;
402
403 rlink(n) = 0;
404 llink(n) = 0;
405 balance(n) = 0;
406
407 if (!root_) {
408 uplink(n) = 0;
409 root_ = n;
410 start_ = n;
411 return;
412 }
413
414 // find an insertion point
415 T* p = root_;
416 T* prev_p = 0;
417 int cmp;
418 int have_start = 1;
419 while (p) {
420 if (p == n) {
421 abort();
422 }
423 prev_p = p;
424 cmp = compare(n,p);
425 if (cmp < 0) p = llink(p);
426 else {
427 p = rlink(p);
428 have_start = 0;
429 }
430 }
431
432 // insert the node
433 uplink(n) = prev_p;
434 if (prev_p) {
435 if (cmp < 0) llink(prev_p) = n;
436 else rlink(prev_p) = n;
437 }
438
439 // maybe update the first node in the map
440 if (have_start) start_ = n;
441
442 // adjust the balance factors
443 if (prev_p) {
444 adjust_balance_insert(prev_p, n);
445 }
446}
447
448template <class K, class T>
449void
450EAVLMMap<K,T>::adjust_balance_insert(T* A, T* child)
451{
452 if (!A) return;
453 int adjustment;
454 if (llink(A) == child) adjustment = -1;
455 else adjustment = 1;
456 int bal = balance(A) + adjustment;
457 if (bal == 0) {
458 balance(A) = 0;
459 }
460 else if (bal == -1 || bal == 1) {
461 balance(A) = bal;
462 adjust_balance_insert(uplink(A), A);
463 }
464 else if (bal == 2) {
465 T* B = rlink(A);
466 if (balance(B) == 1) {
467 balance(B) = 0;
468 balance(A) = 0;
469 rlink(A) = llink(B);
470 llink(B) = A;
471 uplink(B) = uplink(A);
472 uplink(A) = B;
473 if (rlink(A)) uplink(rlink(A)) = A;
474 if (llink(B)) uplink(llink(B)) = B;
475 if (uplink(B) == 0) root_ = B;
476 else {
477 if (rlink(uplink(B)) == A) rlink(uplink(B)) = B;
478 else llink(uplink(B)) = B;
479 }
480 }
481 else {
482 T* X = llink(B);
483 rlink(A) = llink(X);
484 llink(B) = rlink(X);
485 llink(X) = A;
486 rlink(X) = B;
487 if (balance(X) == 1) {
488 balance(A) = -1;
489 balance(B) = 0;
490 }
491 else if (balance(X) == -1) {
492 balance(A) = 0;
493 balance(B) = 1;
494 }
495 else {
496 balance(A) = 0;
497 balance(B) = 0;
498 }
499 balance(X) = 0;
500 uplink(X) = uplink(A);
501 uplink(A) = X;
502 uplink(B) = X;
503 if (rlink(A)) uplink(rlink(A)) = A;
504 if (llink(B)) uplink(llink(B)) = B;
505 if (uplink(X) == 0) root_ = X;
506 else {
507 if (rlink(uplink(X)) == A) rlink(uplink(X)) = X;
508 else llink(uplink(X)) = X;
509 }
510 }
511 }
512 else if (bal == -2) {
513 T* B = llink(A);
514 if (balance(B) == -1) {
515 balance(B) = 0;
516 balance(A) = 0;
517 llink(A) = rlink(B);
518 rlink(B) = A;
519 uplink(B) = uplink(A);
520 uplink(A) = B;
521 if (llink(A)) uplink(llink(A)) = A;
522 if (rlink(B)) uplink(rlink(B)) = B;
523 if (uplink(B) == 0) root_ = B;
524 else {
525 if (llink(uplink(B)) == A) llink(uplink(B)) = B;
526 else rlink(uplink(B)) = B;
527 }
528 }
529 else {
530 T* X = rlink(B);
531 llink(A) = rlink(X);
532 rlink(B) = llink(X);
533 rlink(X) = A;
534 llink(X) = B;
535 if (balance(X) == -1) {
536 balance(A) = 1;
537 balance(B) = 0;
538 }
539 else if (balance(X) == 1) {
540 balance(A) = 0;
541 balance(B) = -1;
542 }
543 else {
544 balance(A) = 0;
545 balance(B) = 0;
546 }
547 balance(X) = 0;
548 uplink(X) = uplink(A);
549 uplink(A) = X;
550 uplink(B) = X;
551 if (llink(A)) uplink(llink(A)) = A;
552 if (rlink(B)) uplink(rlink(B)) = B;
553 if (uplink(X) == 0) root_ = X;
554 else {
555 if (llink(uplink(X)) == A) llink(uplink(X)) = X;
556 else rlink(uplink(X)) = X;
557 }
558 }
559 }
560}
561
562template <class K, class T>
563void
564EAVLMMap<K,T>::adjust_balance_remove(T* A, T* child)
565{
566 if (!A) return;
567 int adjustment;
568 if (llink(A) == child) adjustment = 1;
569 else adjustment = -1;
570 int bal = balance(A) + adjustment;
571 if (bal == 0) {
572 balance(A) = 0;
573 adjust_balance_remove(uplink(A), A);
574 }
575 else if (bal == -1 || bal == 1) {
576 balance(A) = bal;
577 }
578 else if (bal == 2) {
579 T* B = rlink(A);
580 if (balance(B) == 0) {
581 balance(B) = -1;
582 balance(A) = 1;
583 rlink(A) = llink(B);
584 llink(B) = A;
585 uplink(B) = uplink(A);
586 uplink(A) = B;
587 if (rlink(A)) uplink(rlink(A)) = A;
588 if (llink(B)) uplink(llink(B)) = B;
589 if (uplink(B) == 0) root_ = B;
590 else {
591 if (rlink(uplink(B)) == A) rlink(uplink(B)) = B;
592 else llink(uplink(B)) = B;
593 }
594 }
595 else if (balance(B) == 1) {
596 balance(B) = 0;
597 balance(A) = 0;
598 rlink(A) = llink(B);
599 llink(B) = A;
600 uplink(B) = uplink(A);
601 uplink(A) = B;
602 if (rlink(A)) uplink(rlink(A)) = A;
603 if (llink(B)) uplink(llink(B)) = B;
604 if (uplink(B) == 0) root_ = B;
605 else {
606 if (rlink(uplink(B)) == A) rlink(uplink(B)) = B;
607 else llink(uplink(B)) = B;
608 }
609 adjust_balance_remove(uplink(B), B);
610 }
611 else {
612 T* X = llink(B);
613 rlink(A) = llink(X);
614 llink(B) = rlink(X);
615 llink(X) = A;
616 rlink(X) = B;
617 if (balance(X) == 0) {
618 balance(A) = 0;
619 balance(B) = 0;
620 }
621 else if (balance(X) == 1) {
622 balance(A) = -1;
623 balance(B) = 0;
624 }
625 else {
626 balance(A) = 0;
627 balance(B) = 1;
628 }
629 balance(X) = 0;
630 uplink(X) = uplink(A);
631 uplink(A) = X;
632 uplink(B) = X;
633 if (rlink(A)) uplink(rlink(A)) = A;
634 if (llink(B)) uplink(llink(B)) = B;
635 if (uplink(X) == 0) root_ = X;
636 else {
637 if (rlink(uplink(X)) == A) rlink(uplink(X)) = X;
638 else llink(uplink(X)) = X;
639 }
640 adjust_balance_remove(uplink(X), X);
641 }
642 }
643 else if (bal == -2) {
644 T* B = llink(A);
645 if (balance(B) == 0) {
646 balance(B) = 1;
647 balance(A) = -1;
648 llink(A) = rlink(B);
649 rlink(B) = A;
650 uplink(B) = uplink(A);
651 uplink(A) = B;
652 if (llink(A)) uplink(llink(A)) = A;
653 if (rlink(B)) uplink(rlink(B)) = B;
654 if (uplink(B) == 0) root_ = B;
655 else {
656 if (llink(uplink(B)) == A) llink(uplink(B)) = B;
657 else rlink(uplink(B)) = B;
658 }
659 }
660 else if (balance(B) == -1) {
661 balance(B) = 0;
662 balance(A) = 0;
663 llink(A) = rlink(B);
664 rlink(B) = A;
665 uplink(B) = uplink(A);
666 uplink(A) = B;
667 if (llink(A)) uplink(llink(A)) = A;
668 if (rlink(B)) uplink(rlink(B)) = B;
669 if (uplink(B) == 0) root_ = B;
670 else {
671 if (llink(uplink(B)) == A) llink(uplink(B)) = B;
672 else rlink(uplink(B)) = B;
673 }
674 adjust_balance_remove(uplink(B), B);
675 }
676 else {
677 T* X = rlink(B);
678 llink(A) = rlink(X);
679 rlink(B) = llink(X);
680 rlink(X) = A;
681 llink(X) = B;
682 if (balance(X) == 0) {
683 balance(A) = 0;
684 balance(B) = 0;
685 }
686 else if (balance(X) == -1) {
687 balance(A) = 1;
688 balance(B) = 0;
689 }
690 else {
691 balance(A) = 0;
692 balance(B) = -1;
693 }
694 balance(X) = 0;
695 uplink(X) = uplink(A);
696 uplink(A) = X;
697 uplink(B) = X;
698 if (llink(A)) uplink(llink(A)) = A;
699 if (rlink(B)) uplink(rlink(B)) = B;
700 if (uplink(X) == 0) root_ = X;
701 else {
702 if (llink(uplink(X)) == A) llink(uplink(X)) = X;
703 else rlink(uplink(X)) = X;
704 }
705 adjust_balance_remove(uplink(X), X);
706 }
707 }
708}
709
710template <class K, class T>
711inline
712EAVLMMap<K,T>::EAVLMMap()
713{
714 initialize(0);
715}
716
717template <class K, class T>
718inline
719EAVLMMap<K,T>::EAVLMMap(EAVLMMapNode<K,T> T::* node)
720{
721 initialize(node);
722}
723
724template <class K, class T>
725inline void
726EAVLMMap<K,T>::initialize(EAVLMMapNode<K,T> T::* node)
727{
728 node_ = node;
729 root_ = 0;
730 start_ = 0;
731 length_ = 0;
732}
733
734}
735
736#endif
737
738// ///////////////////////////////////////////////////////////////////////////
739
740// Local Variables:
741// mode: c++
742// c-file-style: "CLJ"
743// End:
Definition eavlmmap.h:50
Definition eavlmmap.h:86
Definition eavlmmap.h:62
static std::ostream & out0()
Return an ostream that writes from node 0.
static std::ostream & errn()
Return an ostream for error messages that writes from all nodes.
Definition exenv.h:83
Contains all MPQC code up to version 3.
Definition mpqcin.h:14

Generated at Wed Sep 25 2024 02:45:30 for MPQC 3.0.0-alpha using the documentation package Doxygen 1.12.0.