00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef _util_container_eavlmmap_h
00029 #define _util_container_eavlmmap_h
00030
00031 #ifdef HAVE_CONFIG_H
00032 # include <scconfig.h>
00033 #endif
00034 #include <iostream>
00035 #include <util/misc/exenv.h>
00036 #include <util/container/compare.h>
00037 #include <unistd.h>
00038 #include <stdlib.h>
00039
00040 #ifdef __GNUC__
00041
00042 # define eavl_typename
00043 #else
00044 # define eavl_typename typename
00045 #endif
00046
00047 template <class K, class T>
00048 class EAVLMMapNode {
00049 public:
00050 K key;
00051 T* lt;
00052 T* rt;
00053 T* up;
00054 int balance;
00055 public:
00056 EAVLMMapNode(const K& k): key(k) {}
00057 };
00058
00059 template <class K, class T>
00060 class EAVLMMap {
00061 private:
00062 size_t length_;
00063 T *root_;
00064 T *start_;
00065 EAVLMMapNode<K,T> T::* node_;
00066 public:
00067 #if defined(__GNUC__) && defined(__alpha__)
00068 T*& rlink(const T* n) const { T*& r = (n->*node_).rt; return r; }
00069 T*& llink(const T* n) const { T*& r = (n->*node_).lt; return r; }
00070 T*& uplink(const T* n) const { T*& r = (n->*node_).up; return r; }
00071 int& balance(const T* n) const { int& r = (n->*node_).balance; return r; }
00072 K& key(T* n) const { K& r = (n->*node_).key; return r; }
00073 const K& key(const T* n) const { K& r = (n->*node_).key; return r; }
00074 #else
00075 T*& rlink(T* n) const { return (n->*node_).rt; }
00076 T* rlink(const T* n) const { return (n->*node_).rt; }
00077 T*& llink(T* n) const { return (n->*node_).lt; }
00078 T* llink(const T* n) const { return (n->*node_).lt; }
00079 T*& uplink(T* n) const { return (n->*node_).up; }
00080 T* uplink(const T* n) const { return (n->*node_).up; }
00081 int& balance(T* n) const { return (n->*node_).balance; }
00082 int balance(const T* n) const { return (n->*node_).balance; }
00083 K& key(T* n) const { return (n->*node_).key; }
00084 const K& key(const T* n) const { return (n->*node_).key; }
00085 #endif
00086 int compare(T*n,T*m) const { return ::compare(key(n), key(m)); }
00087 int compare(T*n,const K&m) const { return ::compare(key(n), m); }
00088 private:
00089 void adjust_balance_insert(T* A, T* child);
00090 void adjust_balance_remove(T* A, T* child);
00091 void clear(T*);
00092 public:
00093 class iterator {
00094 private:
00095 EAVLMMap<K,T> *map_;
00096 T *node;
00097 public:
00098 iterator(EAVLMMap<K,T> *m, T *n):map_(m),node(n){}
00099 iterator(const eavl_typename EAVLMMap<K,T>::iterator &i) { map_=i.map_; node=i.node; }
00100 void operator++() { map_->next(node); }
00101 void operator++(int) { operator++(); }
00102 int operator == (const eavl_typename EAVLMMap<K,T>::iterator &i) const
00103 { return map_ == i.map_ && node == i.node; }
00104 int operator != (const eavl_typename EAVLMMap<K,T>::iterator &i) const
00105 { return !operator == (i); }
00106 void operator = (const eavl_typename EAVLMMap<K,T>::iterator &i)
00107 { map_ = i.map_; node = i.node; }
00108 const K &key() const { return map_->key(node); }
00109 T & operator *() { return *node; }
00110 T * operator->() { return node; }
00111 };
00112 public:
00113 EAVLMMap();
00114 EAVLMMap(EAVLMMapNode<K,T> T::* node);
00115 ~EAVLMMap() { clear(root_); }
00116 void initialize(EAVLMMapNode<K,T> T::* node);
00117 void clear_without_delete() { initialize(node_); }
00118 void clear() { clear(root_); initialize(node_); }
00119 void insert(T*);
00120 void remove(T*);
00121 T* find(const K&) const;
00122
00123 int height(T* node);
00124 int height() { return height(root_); }
00125 void check();
00126 void check_node(T*) const;
00127
00128 T* start() const { return start_; }
00129 void next(const T*&) const;
00130 void next(T*&) const;
00131
00132 iterator begin() { return iterator(this,start()); }
00133 iterator end() { return iterator(this,0); }
00134
00135 void print();
00136 int length() const { return length_; }
00137 int depth(T*);
00138 };
00139
00140 template <class K, class T>
00141 T*
00142 EAVLMMap<K,T>::find(const K& key) const
00143 {
00144 T* n = root_;
00145
00146 while (n) {
00147 int cmp = compare(n, key);
00148 if (cmp < 0) n = rlink(n);
00149 else if (cmp > 0) n = llink(n);
00150 else return n;
00151 }
00152
00153 return 0;
00154 }
00155
00156 template <class K, class T>
00157 void
00158 EAVLMMap<K,T>::remove(T* node)
00159 {
00160 if (!node) return;
00161
00162 length_--;
00163
00164 if (node == start_) {
00165 next(start_);
00166 }
00167
00168 T *rebalance_point;
00169 T *q;
00170
00171 if (llink(node) == 0) {
00172 q = rlink(node);
00173 rebalance_point = uplink(node);
00174
00175 if (q) uplink(q) = rebalance_point;
00176
00177 if (rebalance_point) {
00178 if (rlink(rebalance_point) == node) rlink(rebalance_point) = q;
00179 else llink(rebalance_point) = q;
00180 }
00181 else root_ = q;
00182 }
00183 else if (rlink(node) == 0) {
00184 q = llink(node);
00185 rebalance_point = uplink(node);
00186
00187 if (q) uplink(q) = rebalance_point;
00188
00189 if (rebalance_point) {
00190 if (rlink(rebalance_point) == node) rlink(rebalance_point) = q;
00191 else llink(rebalance_point) = q;
00192 }
00193 else root_ = q;
00194 }
00195 else {
00196 T *r = node;
00197 next(r);
00198
00199 if (r == 0 || llink(r) != 0) {
00200 ExEnv::err() << "EAVLMMap::remove: inconsistency" << std::endl;
00201 abort();
00202 }
00203
00204 if (r == rlink(node)) {
00205 llink(r) = llink(node);
00206 if (llink(r)) uplink(llink(r)) = r;
00207 balance(r) = balance(node);
00208 rebalance_point = r;
00209 q = rlink(r);
00210 }
00211 else {
00212 q = rlink(r);
00213
00214 rebalance_point = uplink(r);
00215
00216 if (llink(rebalance_point) == r) llink(rebalance_point) = q;
00217 else rlink(rebalance_point) = q;
00218
00219 if (q) uplink(q) = rebalance_point;
00220
00221 balance(r) = balance(node);
00222 rlink(r) = rlink(node);
00223 llink(r) = llink(node);
00224 if (rlink(r)) uplink(rlink(r)) = r;
00225 if (llink(r)) uplink(llink(r)) = r;
00226 }
00227 if (r) {
00228 T* up = uplink(node);
00229 uplink(r) = up;
00230 if (up) {
00231 if (rlink(up) == node) rlink(up) = r;
00232 else llink(up) = r;
00233 }
00234 if (up == 0) root_ = r;
00235 }
00236 }
00237
00238
00239
00240 if (rebalance_point &&
00241 llink(rebalance_point) == 0 && rlink(rebalance_point) == 0) {
00242 balance(rebalance_point) = 0;
00243 q = rebalance_point;
00244 rebalance_point = uplink(rebalance_point);
00245 }
00246 adjust_balance_remove(rebalance_point, q);
00247 }
00248
00249 template <class K, class T>
00250 void
00251 EAVLMMap<K,T>::print()
00252 {
00253 for (T*n=start(); n; next(n)) {
00254 int d = depth(n) + 1;
00255 for (int i=0; i<d; i++) ExEnv::out() << " ";
00256 if (balance(n) == 1) ExEnv::out() << " (+)" << std::endl;
00257 else if (balance(n) == -1) ExEnv::out() << " (-)" << std::endl;
00258 else if (balance(n) == 0) ExEnv::out() << " (.)" << std::endl;
00259 else ExEnv::out() << " (" << balance(n) << ")" << std::endl;
00260 }
00261 }
00262
00263 template <class K, class T>
00264 int
00265 EAVLMMap<K,T>::depth(T*node)
00266 {
00267 int d = 0;
00268 while (node) {
00269 node = uplink(node);
00270 d++;
00271 }
00272 return d;
00273 }
00274
00275 template <class K, class T>
00276 void
00277 EAVLMMap<K,T>::check_node(T*n) const
00278 {
00279 if (uplink(n) && uplink(n) == n) abort();
00280 if (llink(n) && llink(n) == n) abort();
00281 if (rlink(n) && rlink(n) == n) abort();
00282 if (rlink(n) && rlink(n) == llink(n)) abort();
00283 if (uplink(n) && uplink(n) == llink(n)) abort();
00284 if (uplink(n) && uplink(n) == rlink(n)) abort();
00285 if (uplink(n) && !(llink(uplink(n)) == n
00286 || rlink(uplink(n)) == n)) abort();
00287 }
00288
00289 template <class K, class T>
00290 void
00291 EAVLMMap<K,T>::clear(T*n)
00292 {
00293 if (!n) return;
00294 clear(llink(n));
00295 clear(rlink(n));
00296 delete n;
00297 }
00298
00299 template <class K, class T>
00300 int
00301 EAVLMMap<K,T>::height(T* node)
00302 {
00303 if (!node) return 0;
00304 int rh = height(rlink(node)) + 1;
00305 int lh = height(llink(node)) + 1;
00306 return rh>lh?rh:lh;
00307 }
00308
00309 template <class K, class T>
00310 void
00311 EAVLMMap<K,T>::check()
00312 {
00313 T* node;
00314 T* prev=0;
00315 size_t computed_length = 0;
00316 for (node = start(); node; next(node)) {
00317 check_node(node);
00318 if (prev && compare(prev,node) > 0) {
00319 ExEnv::err() << "nodes out of order" << std::endl;
00320 abort();
00321 }
00322 prev = node;
00323 computed_length++;
00324 }
00325 for (node = start(); node; next(node)) {
00326 if (balance(node) != height(rlink(node)) - height(llink(node))) {
00327 ExEnv::err() << "balance inconsistency" << std::endl;
00328 abort();
00329 }
00330 if (balance(node) < -1 || balance(node) > 1) {
00331 ExEnv::err() << "balance out of range" << std::endl;
00332 abort();
00333 }
00334 }
00335 if (length_ != computed_length) {
00336 ExEnv::err() << "length error" << std::endl;
00337 abort();
00338 }
00339 }
00340
00341 template <class K, class T>
00342 void
00343 EAVLMMap<K,T>::next(const T*& node) const
00344 {
00345 const T* r;
00346 if (r = rlink(node)) {
00347 node = r;
00348 while (r = llink(node)) node = r;
00349 return;
00350 }
00351 while (r = uplink(node)) {
00352 if (node == llink(r)) {
00353 node = r;
00354 return;
00355 }
00356 node = r;
00357 }
00358 node = 0;
00359 }
00360
00361 template <class K, class T>
00362 void
00363 EAVLMMap<K,T>::next(T*& node) const
00364 {
00365 T* r;
00366 if (r = rlink(node)) {
00367 node = r;
00368 while (r = llink(node)) node = r;
00369 return;
00370 }
00371 while (r = uplink(node)) {
00372 if (node == llink(r)) {
00373 node = r;
00374 return;
00375 }
00376 node = r;
00377 }
00378 node = 0;
00379 }
00380
00381 template <class K, class T>
00382 void
00383 EAVLMMap<K,T>::insert(T* n)
00384 {
00385 if (!n) {
00386 return;
00387 }
00388
00389 length_++;
00390
00391 rlink(n) = 0;
00392 llink(n) = 0;
00393 balance(n) = 0;
00394
00395 if (!root_) {
00396 uplink(n) = 0;
00397 root_ = n;
00398 start_ = n;
00399 return;
00400 }
00401
00402
00403 T* p = root_;
00404 T* prev_p = 0;
00405 int cmp;
00406 int have_start = 1;
00407 while (p) {
00408 if (p == n) {
00409 abort();
00410 }
00411 prev_p = p;
00412 cmp = compare(n,p);
00413 if (cmp < 0) p = llink(p);
00414 else {
00415 p = rlink(p);
00416 have_start = 0;
00417 }
00418 }
00419
00420
00421 uplink(n) = prev_p;
00422 if (prev_p) {
00423 if (cmp < 0) llink(prev_p) = n;
00424 else rlink(prev_p) = n;
00425 }
00426
00427
00428 if (have_start) start_ = n;
00429
00430
00431 if (prev_p) {
00432 adjust_balance_insert(prev_p, n);
00433 }
00434 }
00435
00436 template <class K, class T>
00437 void
00438 EAVLMMap<K,T>::adjust_balance_insert(T* A, T* child)
00439 {
00440 if (!A) return;
00441 int adjustment;
00442 if (llink(A) == child) adjustment = -1;
00443 else adjustment = 1;
00444 int bal = balance(A) + adjustment;
00445 if (bal == 0) {
00446 balance(A) = 0;
00447 }
00448 else if (bal == -1 || bal == 1) {
00449 balance(A) = bal;
00450 adjust_balance_insert(uplink(A), A);
00451 }
00452 else if (bal == 2) {
00453 T* B = rlink(A);
00454 if (balance(B) == 1) {
00455 balance(B) = 0;
00456 balance(A) = 0;
00457 rlink(A) = llink(B);
00458 llink(B) = A;
00459 uplink(B) = uplink(A);
00460 uplink(A) = B;
00461 if (rlink(A)) uplink(rlink(A)) = A;
00462 if (llink(B)) uplink(llink(B)) = B;
00463 if (uplink(B) == 0) root_ = B;
00464 else {
00465 if (rlink(uplink(B)) == A) rlink(uplink(B)) = B;
00466 else llink(uplink(B)) = B;
00467 }
00468 }
00469 else {
00470 T* X = llink(B);
00471 rlink(A) = llink(X);
00472 llink(B) = rlink(X);
00473 llink(X) = A;
00474 rlink(X) = B;
00475 if (balance(X) == 1) {
00476 balance(A) = -1;
00477 balance(B) = 0;
00478 }
00479 else if (balance(X) == -1) {
00480 balance(A) = 0;
00481 balance(B) = 1;
00482 }
00483 else {
00484 balance(A) = 0;
00485 balance(B) = 0;
00486 }
00487 balance(X) = 0;
00488 uplink(X) = uplink(A);
00489 uplink(A) = X;
00490 uplink(B) = X;
00491 if (rlink(A)) uplink(rlink(A)) = A;
00492 if (llink(B)) uplink(llink(B)) = B;
00493 if (uplink(X) == 0) root_ = X;
00494 else {
00495 if (rlink(uplink(X)) == A) rlink(uplink(X)) = X;
00496 else llink(uplink(X)) = X;
00497 }
00498 }
00499 }
00500 else if (bal == -2) {
00501 T* B = llink(A);
00502 if (balance(B) == -1) {
00503 balance(B) = 0;
00504 balance(A) = 0;
00505 llink(A) = rlink(B);
00506 rlink(B) = A;
00507 uplink(B) = uplink(A);
00508 uplink(A) = B;
00509 if (llink(A)) uplink(llink(A)) = A;
00510 if (rlink(B)) uplink(rlink(B)) = B;
00511 if (uplink(B) == 0) root_ = B;
00512 else {
00513 if (llink(uplink(B)) == A) llink(uplink(B)) = B;
00514 else rlink(uplink(B)) = B;
00515 }
00516 }
00517 else {
00518 T* X = rlink(B);
00519 llink(A) = rlink(X);
00520 rlink(B) = llink(X);
00521 rlink(X) = A;
00522 llink(X) = B;
00523 if (balance(X) == -1) {
00524 balance(A) = 1;
00525 balance(B) = 0;
00526 }
00527 else if (balance(X) == 1) {
00528 balance(A) = 0;
00529 balance(B) = -1;
00530 }
00531 else {
00532 balance(A) = 0;
00533 balance(B) = 0;
00534 }
00535 balance(X) = 0;
00536 uplink(X) = uplink(A);
00537 uplink(A) = X;
00538 uplink(B) = X;
00539 if (llink(A)) uplink(llink(A)) = A;
00540 if (rlink(B)) uplink(rlink(B)) = B;
00541 if (uplink(X) == 0) root_ = X;
00542 else {
00543 if (llink(uplink(X)) == A) llink(uplink(X)) = X;
00544 else rlink(uplink(X)) = X;
00545 }
00546 }
00547 }
00548 }
00549
00550 template <class K, class T>
00551 void
00552 EAVLMMap<K,T>::adjust_balance_remove(T* A, T* child)
00553 {
00554 if (!A) return;
00555 int adjustment;
00556 if (llink(A) == child) adjustment = 1;
00557 else adjustment = -1;
00558 int bal = balance(A) + adjustment;
00559 if (bal == 0) {
00560 balance(A) = 0;
00561 adjust_balance_remove(uplink(A), A);
00562 }
00563 else if (bal == -1 || bal == 1) {
00564 balance(A) = bal;
00565 }
00566 else if (bal == 2) {
00567 T* B = rlink(A);
00568 if (balance(B) == 0) {
00569 balance(B) = -1;
00570 balance(A) = 1;
00571 rlink(A) = llink(B);
00572 llink(B) = A;
00573 uplink(B) = uplink(A);
00574 uplink(A) = B;
00575 if (rlink(A)) uplink(rlink(A)) = A;
00576 if (llink(B)) uplink(llink(B)) = B;
00577 if (uplink(B) == 0) root_ = B;
00578 else {
00579 if (rlink(uplink(B)) == A) rlink(uplink(B)) = B;
00580 else llink(uplink(B)) = B;
00581 }
00582 }
00583 else if (balance(B) == 1) {
00584 balance(B) = 0;
00585 balance(A) = 0;
00586 rlink(A) = llink(B);
00587 llink(B) = A;
00588 uplink(B) = uplink(A);
00589 uplink(A) = B;
00590 if (rlink(A)) uplink(rlink(A)) = A;
00591 if (llink(B)) uplink(llink(B)) = B;
00592 if (uplink(B) == 0) root_ = B;
00593 else {
00594 if (rlink(uplink(B)) == A) rlink(uplink(B)) = B;
00595 else llink(uplink(B)) = B;
00596 }
00597 adjust_balance_remove(uplink(B), B);
00598 }
00599 else {
00600 T* X = llink(B);
00601 rlink(A) = llink(X);
00602 llink(B) = rlink(X);
00603 llink(X) = A;
00604 rlink(X) = B;
00605 if (balance(X) == 0) {
00606 balance(A) = 0;
00607 balance(B) = 0;
00608 }
00609 else if (balance(X) == 1) {
00610 balance(A) = -1;
00611 balance(B) = 0;
00612 }
00613 else {
00614 balance(A) = 0;
00615 balance(B) = 1;
00616 }
00617 balance(X) = 0;
00618 uplink(X) = uplink(A);
00619 uplink(A) = X;
00620 uplink(B) = X;
00621 if (rlink(A)) uplink(rlink(A)) = A;
00622 if (llink(B)) uplink(llink(B)) = B;
00623 if (uplink(X) == 0) root_ = X;
00624 else {
00625 if (rlink(uplink(X)) == A) rlink(uplink(X)) = X;
00626 else llink(uplink(X)) = X;
00627 }
00628 adjust_balance_remove(uplink(X), X);
00629 }
00630 }
00631 else if (bal == -2) {
00632 T* B = llink(A);
00633 if (balance(B) == 0) {
00634 balance(B) = 1;
00635 balance(A) = -1;
00636 llink(A) = rlink(B);
00637 rlink(B) = A;
00638 uplink(B) = uplink(A);
00639 uplink(A) = B;
00640 if (llink(A)) uplink(llink(A)) = A;
00641 if (rlink(B)) uplink(rlink(B)) = B;
00642 if (uplink(B) == 0) root_ = B;
00643 else {
00644 if (llink(uplink(B)) == A) llink(uplink(B)) = B;
00645 else rlink(uplink(B)) = B;
00646 }
00647 }
00648 else if (balance(B) == -1) {
00649 balance(B) = 0;
00650 balance(A) = 0;
00651 llink(A) = rlink(B);
00652 rlink(B) = A;
00653 uplink(B) = uplink(A);
00654 uplink(A) = B;
00655 if (llink(A)) uplink(llink(A)) = A;
00656 if (rlink(B)) uplink(rlink(B)) = B;
00657 if (uplink(B) == 0) root_ = B;
00658 else {
00659 if (llink(uplink(B)) == A) llink(uplink(B)) = B;
00660 else rlink(uplink(B)) = B;
00661 }
00662 adjust_balance_remove(uplink(B), B);
00663 }
00664 else {
00665 T* X = rlink(B);
00666 llink(A) = rlink(X);
00667 rlink(B) = llink(X);
00668 rlink(X) = A;
00669 llink(X) = B;
00670 if (balance(X) == 0) {
00671 balance(A) = 0;
00672 balance(B) = 0;
00673 }
00674 else if (balance(X) == -1) {
00675 balance(A) = 1;
00676 balance(B) = 0;
00677 }
00678 else {
00679 balance(A) = 0;
00680 balance(B) = -1;
00681 }
00682 balance(X) = 0;
00683 uplink(X) = uplink(A);
00684 uplink(A) = X;
00685 uplink(B) = X;
00686 if (llink(A)) uplink(llink(A)) = A;
00687 if (rlink(B)) uplink(rlink(B)) = B;
00688 if (uplink(X) == 0) root_ = X;
00689 else {
00690 if (llink(uplink(X)) == A) llink(uplink(X)) = X;
00691 else rlink(uplink(X)) = X;
00692 }
00693 adjust_balance_remove(uplink(X), X);
00694 }
00695 }
00696 }
00697
00698 template <class K, class T>
00699 inline
00700 EAVLMMap<K,T>::EAVLMMap()
00701 {
00702 initialize(0);
00703 }
00704
00705 template <class K, class T>
00706 inline
00707 EAVLMMap<K,T>::EAVLMMap(EAVLMMapNode<K,T> T::* node)
00708 {
00709 initialize(node);
00710 }
00711
00712 template <class K, class T>
00713 inline void
00714 EAVLMMap<K,T>::initialize(EAVLMMapNode<K,T> T::* node)
00715 {
00716 node_ = node;
00717 root_ = 0;
00718 start_ = 0;
00719 length_ = 0;
00720 }
00721
00722 #endif
00723
00724
00725
00726
00727
00728
00729