25 #ifndef __I6ENGINE_UTILS_RANGEDMAP_H__
26 #define __I6ENGINE_UTILS_RANGEDMAP_H__
38 template<
typename Key,
typename Value>
48 return _cur !=
nullptr;
62 RangedMap(
const Key & minVal,
const Key & maxVal,
const Value & def) : _head(nullptr), _merged(false) {
63 _head =
new Element(minVal, maxVal, def);
76 void dump(
const std::string & fileName) {
78 of.open(fileName.c_str());
88 Value
get(
const Key & k)
const {
90 if (k < e->_start || k > e->_end) {
93 while (e->_next !=
nullptr) {
95 if (k > b->middleSplit) {
97 }
else if (k > b->leftSplit) {
109 void set(
const Key k,
const Value v) {
112 if (k < e->_start || k > e->_end) {
115 while(e->_next !=
nullptr) {
117 if (k > bLast->middleSplit) {
119 }
else if (k > bLast->leftSplit) {
131 e = tryMergeToLeft(e, k, v, 1);
134 r = e->_end - e->_start + 1;
136 e = tryMergeToRight(e, k, v, r);
137 }
else if (isLeft(e)) {
139 e = tryMergeToRight(e, k, v, 1);
142 r = e->_end - e->_start + 1;
144 e = tryMergeToLeft(e, k, v, r);
145 }
else if (isRight(e)) {
147 e = tryMergeToLeft(e, k, v, 1);
150 r = e->_end - e->_start + 1;
152 e = tryMergeToRight(e, k, v, r);
156 if (k == e->_start && k == e->_end) {
158 }
else if (isRight(e) && k == e->_start && !e->_leftNext->isValid()) {
159 e->_leftNext->_start = k;
160 e->_leftNext->_end = k;
162 e->_parent->_next->middleSplit++;
163 e->_leftNext->_val = v;
164 }
else if (isLeft(e) && k == e->_end && !e->_rightNext->isValid()) {
165 e->_rightNext->_start = k;
166 e->_rightNext->_end = k;
168 e->_parent->_next->leftSplit--;
169 e->_rightNext->_val = v;
171 Block * b =
new Block();
172 if (k == e->_start) {
173 b->left =
new Element(k, k, v);
174 b->mid =
new Element(k + 1, k, v);
175 b->right =
new Element(k + 1, e->_end, e->_val);
178 }
else if (k == e->_end) {
179 b->left =
new Element(e->_start, k - 1, e->_val);
180 b->mid =
new Element(k, k - 1, v);
181 b->right =
new Element(k, k, v);
182 b->leftSplit = k - 1;
183 b->middleSplit = k - 1;
185 b->left =
new Element(e->_start, k - 1, e->_val);
186 b->mid =
new Element(k, k, v);
187 b->right =
new Element(k + 1, e->_end, e->_val);
188 b->leftSplit = k - 1;
191 b->left->_parent = e;
193 b->right->_parent = e;
196 b->left->_leftNext = e->_leftNext;
197 if (e->_leftNext !=
nullptr) {
198 e->_leftNext->_rightNext = b->left;
201 b->mid->_leftNext = b->left;
202 b->left->_rightNext = b->mid;
203 b->mid->_rightNext = b->right;
204 b->right->_leftNext = b->mid;
206 b->right->_rightNext = e->_rightNext;
207 if (e->_rightNext !=
nullptr) {
208 e->_rightNext->_leftNext = b->right;
211 e->_leftNext =
nullptr;
212 e->_rightNext =
nullptr;
225 Key leftSplit, middleSplit;
227 Block() : left(nullptr), mid(nullptr), right(nullptr), leftSplit(), middleSplit() {
236 void dump(std::ostream & of) {
237 of <<
"\"" <<
this <<
"\"[label=\"Block\\n" << leftSplit <<
"|" << middleSplit <<
"\"];" << std::endl;
238 of <<
"\"" <<
this <<
"\"" <<
" -> " <<
"\"" << left <<
"\"" <<
"[color=red,label=\"L\"];" << std::endl;
239 of <<
"\"" <<
this <<
"\"" <<
" -> " <<
"\"" << mid <<
"\"" <<
"[color=red,label=\"M\"];" << std::endl;
240 of <<
"\"" <<
this <<
"\"" <<
" -> " <<
"\"" << right <<
"\"" <<
"[color=red,label=\"R\"];" << std::endl;
241 if (left) left->dump(of);
242 if (mid) mid->dump(of);
243 if (right) right->dump(of);
247 Element(
const Key & s,
const Key & e,
const Value & v) : _start(s), _end(e), _next(nullptr), _val(v), _leftNext(nullptr), _rightNext(nullptr), _parent(nullptr) {
253 Element * _rightNext;
260 void dump(std::ostream & of) {
261 of <<
"\"" <<
this <<
"\"" <<
"[label=\"" << _start <<
"-" << _end <<
":" << _val <<
"\"];" << std::endl;
262 of <<
"\"" <<
this <<
"\"" <<
" -> " <<
"\"" << _leftNext <<
"\"" <<
"[color=blue];" << std::endl;
263 of <<
"\"" <<
this <<
"\"" <<
" -> " <<
"\"" << _rightNext <<
"\"" <<
"[color=blue];" << std::endl;
264 of <<
"\"" <<
this <<
"\"" <<
" -> " <<
"\"" << _parent <<
"\"" <<
"[color=black];" << std::endl;
265 of <<
"\"" <<
this <<
"\"" <<
" -> " <<
"\"" << _next <<
"\"" <<
"[color=green];" << std::endl;
266 if (_next) _next->dump(of);
268 bool isValid()
const {
269 return _start <= _end;
276 void eraseElement(Element * e) {
278 e->_leftNext->_rightNext = e->_rightNext;
281 e->_rightNext->_leftNext = e->_leftNext;
289 void updateStart(Element * e,
const Key k,
int range) {
290 Element * previous = e;
291 while (e && e->_start == k) {
296 if (isLeft(previous)) {
298 }
else if (isMid(previous)) {
299 e->_next->leftSplit = previous->_start - 1;
300 }
else if (isRight(previous)) {
301 e->_next->middleSplit = previous->_start - 1;
309 void updateEnd(Element * e,
const Key k,
int range) {
310 Element * previous = e;
311 while (e && e->_end == k) {
316 if (isLeft(previous)) {
317 e->_next->leftSplit = previous->_end;
318 }
else if (isMid(previous)) {
319 e->_next->middleSplit = previous->_end;
320 }
else if (isRight(previous)) {
325 Element * combineBlockOneValid(Element * e) {
326 Element * par = e->_parent;
329 Element * ne =
nullptr;
330 Block * nex = par->_next;
332 if (!nex->left->isValid()) {
333 eraseElement(par->_next->left);
337 if (!nex->mid->isValid()) {
338 eraseElement(nex->mid);
342 if (!nex->right->isValid()) {
343 eraseElement(nex->right);
347 par->_start = ne->_start;
348 par->_end = ne->_end;
349 par->_val = ne->_val;
350 par->_next = ne->_next;
352 par->_next->left->_parent = par;
353 par->_next->mid->_parent = par;
354 par->_next->right->_parent = par;
356 par->_leftNext = ne->_leftNext;
358 ne->_leftNext->_rightNext = par;
360 par->_rightNext = ne->_rightNext;
361 if (ne->_rightNext) {
362 ne->_rightNext->_leftNext = par;
372 bool isLeft(
const Element * e)
const {
373 return e->_parent && e == e->_parent->_next->left;
376 bool isMid(
const Element * e)
const {
377 return e->_parent && e == e->_parent->_next->mid;
380 bool isRight(
const Element * e)
const {
381 return e->_parent && e == e->_parent->_next->right;
384 void swapLeftMid(Element * el) {
385 Element * em = el->_parent->_next->mid;
386 Element * right = el->_rightNext;
389 r2 = r2->_next->right;
393 std::swap(el->_parent->_next->left, el->_parent->_next->mid);
396 right->_leftNext = el->_leftNext;
398 el->_leftNext->_rightNext = right;
401 el->_rightNext = r2->_rightNext;
402 r2->_rightNext->_leftNext = el;
408 el->_start = r2->_end + 1;
412 el->_parent->_next->leftSplit = r2->_end;
413 el->_parent->_next->middleSplit = r2->_end;
416 void swapRightMid(Element * er) {
417 Element * em = er->_parent->_next->mid;
418 Element * left = er->_leftNext;
421 l2 = l2->_next->left;
425 std::swap(er->_parent->_next->right, er->_parent->_next->mid);
428 left->_rightNext = er->_rightNext;
429 if (er->_rightNext) {
430 er->_rightNext->_leftNext = left;
433 er->_leftNext = l2->_leftNext;
434 l2->_leftNext->_rightNext = er;
440 er->_start = l2->_start - 1;
441 er->_end = l2->_start - 2;
444 er->_parent->_next->leftSplit = l2->_start - 1;
445 er->_parent->_next->middleSplit = l2->_start - 1;
448 std::pair<Element *, bool> tryMergeLeftToMid(Element * e,
const Key k,
const Value v,
int range) {
449 if (k == e->_end && e->_rightNext->_val == v && e->_rightNext->isValid()) {
451 updateStart(e->_rightNext, e->_rightNext->_start, -range);
458 return std::make_pair(e,
true);
460 return std::make_pair(e,
false);
463 std::pair<Element *, bool> tryMergeRightToMid(Element * e,
const Key k,
const Value v,
int range) {
464 if (k == e->_start && e->_leftNext->_val == v && e->_leftNext->isValid()) {
466 updateEnd(e->_leftNext, e->_leftNext->_end, range);
473 return std::make_pair(e,
true);
475 return std::make_pair(e,
false);
478 std::pair<Element *, bool> tryMergeMidToLeft(Element * e,
const Key k,
const Value v,
int range) {
479 if (k == e->_start && e->_leftNext->_val == v) {
481 updateEnd(e->_leftNext, e->_leftNext->_end, range);
483 return std::make_pair(e->_leftNext,
true);
485 return std::make_pair(e,
false);
488 std::pair<Element *, bool> tryMergeMidToRight(Element * e,
const Key k,
const Value v,
int range) {
489 if (k == e->_end && e->_rightNext->_val == v) {
491 updateStart(e->_rightNext, e->_rightNext->_start, -range);
493 return std::make_pair(e->_rightNext,
true);
495 return std::make_pair(e,
false);
498 Element * tryMergeToLeft(Element * e,
const Key k,
const Value v,
int range) {
499 std::pair<Element *, bool> res;
501 res = tryMergeLeftToCrossLeftMid(e, k, v, range);
503 res = tryMergeLeftToCrossLeftLeft(e, k, v, range);
505 }
else if (isMid(e)) {
506 res = tryMergeMidToLeft(e, k, v, range);
507 }
else if (isRight(e)) {
508 res = tryMergeRightToMid(e, k, v, range);
510 res = tryMergeRightToLeft(e, k, v, range);
516 Element * tryMergeToRight(Element * e,
const Key k,
const Value v,
int range) {
517 std::pair<Element *, bool> res;
519 res = tryMergeLeftToMid(e, k, v, range);
521 res = tryMergeLeftToRight(e, k, v, range);
523 }
else if (isMid(e)) {
524 res = tryMergeMidToRight(e, k, v, range);
525 }
else if (isRight(e)) {
526 res = tryMergeRightToCrossRightMid(e, k, v, range);
528 res = tryMergeRightToCrossRightRight(e, k, v, range);
534 std::pair<Element *, bool> tryMergeLeftToCrossLeftLeft(Element * e,
const Key k,
const Value v,
int range) {
540 if (k == e->_start && e->_leftNext && !e->_leftNext->isValid() && e->_leftNext->_leftNext->_val == v) {
542 Element * target = e->_leftNext->_leftNext;
543 updateEnd(target, target->_end, range);
544 updateStart(e, e->_start, range);
546 e->_leftNext->_start += range;
547 e->_leftNext->_end += range;
551 if (e->_rightNext->isValid()) {
555 e = combineBlockOneValid(e->_rightNext);
559 return std::make_pair(target,
false);
561 return std::make_pair(e,
false);
564 std::pair<Element *, bool> tryMergeRightToCrossRightRight(Element * e,
const Key k,
const Value v,
int range) {
570 if (k == e->_end && e->_rightNext && !e->_rightNext->isValid() && e->_rightNext->_rightNext->_val == v) {
572 Element * target = e->_rightNext->_rightNext;
573 updateStart(target, target->_start, -range);
574 updateEnd(e, e->_end, -range);
576 e->_rightNext->_start -= range;
577 e->_rightNext->_end -= range;
581 if (e->_leftNext->isValid()) {
585 e = combineBlockOneValid(e->_leftNext);
589 return std::make_pair(target,
false);
591 return std::make_pair(e,
false);
594 std::pair<Element *, bool> tryMergeLeftToCrossLeftMid(Element * e,
const Key k,
const Value v,
int range) {
595 if (k == e->_start && e->_leftNext && e->_leftNext->_val == v && e->_leftNext->isValid()) {
599 Element * newE = e->_leftNext;
601 updateEnd(e->_leftNext, e->_leftNext->_end, range);
602 updateStart(e, e->_start, range);
605 if (e->_rightNext->isValid()) {
609 e = combineBlockOneValid(e->_rightNext);
612 return std::make_pair(newE,
true);
614 return std::make_pair(e,
false);
617 std::pair<Element *, bool> tryMergeRightToCrossRightMid(Element * e,
const Key k,
const Value v,
int range) {
618 if (k == e->_end && e->_rightNext && e->_rightNext->_val == v && e->_rightNext->isValid()) {
622 Element * newE = e->_rightNext;
624 updateStart(e->_rightNext, e->_rightNext->_start, -range);
625 updateEnd(e, e->_end, -range);
628 if (e->_leftNext->isValid()) {
632 e = combineBlockOneValid(e->_leftNext);
635 return std::make_pair(newE,
true);
637 return std::make_pair(e,
false);
640 std::pair<Element *, bool> tryMergeLeftToRight(Element * e,
const Key k,
const Value v,
int range) {
641 if (k == e->_end && !e->_rightNext->isValid() && e->_rightNext->_rightNext->_val == v) {
644 updateStart(e->_rightNext->_rightNext, e->_rightNext->_rightNext->_start, -range);
647 e->_rightNext->_start -= range;
648 e->_rightNext->_end -= range;
650 e->_parent->_next->leftSplit -= range;
652 Element * newE = e->_rightNext->_rightNext;
654 e = combineBlockOneValid(e->_rightNext);
657 if (e->_next ==
nullptr) {
663 return std::make_pair(newE,
true);
665 return std::make_pair(e,
false);
668 std::pair<Element *, bool> tryMergeRightToLeft(Element * e,
const Key k,
const Value v,
int range) {
669 if (k == e->_start && !e->_leftNext->isValid() && e->_leftNext->_leftNext->_val == v) {
672 updateEnd(e->_leftNext->_leftNext, e->_leftNext->_leftNext->_end, range);
675 e->_leftNext->_start += range;
676 e->_leftNext->_end += range;
679 e->_parent->_next->middleSplit += range;
681 Element * newE = e->_leftNext->_leftNext;
684 e = combineBlockOneValid(e->_leftNext);
687 if (e->_next ==
nullptr) {
693 return std::make_pair(newE,
true);
695 return std::make_pair(e,
false);
RangedMap(const Key &minVal, const Key &maxVal, const Value &def)
default constructor
#define ISIXE_THROW_FAILURE(module, message)
void dump(const std::string &fileName)
writes dot graph to given file
void set(const Key k, const Value v)
sets value for key