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