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