00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef EMBEDDED_FREE_TREE
00020 #define EMBEDDED_FREE_TREE
00021
00022 #include <sys/types.h>
00023 #include <limits>
00024 #include <stdlib.h>
00025 #include <QtCore/QPair>
00026 #include "kdevvarlengtharray.h"
00027 #include <iostream>
00028
00029
00030
00031 #define DEBUG_FREEITEM_COUNT
00032
00051 namespace KDevelop {
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00098 template<class Data, class ItemHandler>
00099 class EmbeddedTreeAlgorithms {
00100
00101 public:
00102
00103 EmbeddedTreeAlgorithms(const Data* items, uint itemCount, const int& centralFreeItem) : m_items(items), m_itemCount(itemCount), m_centralFreeItem(¢ralFreeItem) {
00104 }
00105 ~EmbeddedTreeAlgorithms() {
00106 }
00107
00110
00111 int indexOf(const Data& data) {
00112 return indexOf(data, 0, m_itemCount);
00113 }
00114
00116 int indexOf(const Data& data, uint start, uint end) {
00117 while(1) {
00118 if(start >= end)
00119 return -1;
00120
00121 int center = (start + end)/2;
00122
00123
00124 for(; center < (int)end; ) {
00125 if(!ItemHandler::isFree(m_items[center]))
00126 break;
00127 ++center;
00128 }
00129
00130 if(center == (int)end) {
00131 end = (start + end)/2;
00132 }else{
00133 if(ItemHandler::equals(data, m_items[center])) {
00134 return center;
00135 }else if(data < m_items[center]) {
00136 end = (start + end)/2;
00137 }else{
00138
00139 start = center+1;
00140 }
00141 }
00142 }
00143 }
00144
00147 int lowerBound(const Data& data, int start, int end) {
00148 int currentBound = -1;
00149 while(1) {
00150 if(start >= end)
00151 return currentBound;
00152
00153 int center = (start + end)/2;
00154
00155
00156 for(; center < end; ) {
00157 if(!ItemHandler::isFree(m_items[center]))
00158 break;
00159 ++center;
00160 }
00161
00162 if(center == end) {
00163 end = (start + end)/2;
00164 }else{
00165 if(ItemHandler::equals(data, m_items[center])) {
00166 return center;
00167 }else if(data < m_items[center]) {
00168 currentBound = center;
00169 end = (start + end)/2;
00170 }else{
00171
00172 start = center+1;
00173 }
00174 }
00175 }
00176 }
00177
00178 uint countFreeItems() const {
00179 return countFreeItemsInternal(*m_centralFreeItem);
00180 }
00181 uint countFreeItemsNaive() const {
00182 uint ret = 0;
00183 for(uint a = 0; a < m_itemCount; ++a) {
00184 if(ItemHandler::isFree(m_items[a]))
00185 ++ret;
00186 }
00187 return ret;
00188 }
00189
00190 void verifyOrder() {
00191 Data last;
00192
00193 for(uint a = 0; a < m_itemCount; ++a) {
00194 if(!ItemHandler::isFree(m_items[a])) {
00195 if(!ItemHandler::isFree(last))
00196 Q_ASSERT(last < m_items[a]);
00197 last = m_items[a];
00198 }
00199 }
00200 }
00201
00202 void verifyTreeConsistent() {
00203 verifyTreeConsistentInternal(*m_centralFreeItem, 0, m_itemCount);
00204 Q_ASSERT(countFreeItems() == countFreeItemsNaive());
00205 }
00206
00207 private:
00208 void verifyTreeConsistentInternal(int position, int lowerBound, int upperBound) {
00209 if(position == -1)
00210 return;
00211 Q_ASSERT(lowerBound <= position && position < upperBound);
00212 verifyTreeConsistentInternal(ItemHandler::leftChild(m_items[position]), lowerBound, position);
00213 verifyTreeConsistentInternal(ItemHandler::rightChild(m_items[position]), position+1, upperBound);
00214 }
00215
00216 uint countFreeItemsInternal(int item) const {
00217 if(item == -1)
00218 return 0;
00219
00220 return 1 + countFreeItemsInternal(ItemHandler::leftChild(m_items[item])) + countFreeItemsInternal(ItemHandler::rightChild(m_items[item]));
00221 }
00222
00223 const Data* m_items;
00224 uint m_itemCount;
00225 const int* m_centralFreeItem;
00226 };
00227
00241 template<class Data, class ItemHandler, int increaseFraction = 5, int rebuildIfInsertionMoreExpensive = 20>
00242 class EmbeddedTreeAddItem {
00243
00244 public:
00245
00246 EmbeddedTreeAddItem(Data* items, uint itemCount, int& centralFreeItem, const Data& add) : m_add(add), m_items(items), m_itemCount(itemCount), m_centralFreeItem(¢ralFreeItem), m_applied(false), m_needResize(false) {
00247 m_needResize = !apply();
00248 }
00249 ~EmbeddedTreeAddItem() {
00250 if(!m_applied)
00251 apply(true);
00252 }
00253
00256 uint newItemCount() const {
00257 if(!m_applied) {
00258 if(*m_centralFreeItem == -1) {
00259 uint realItemCount = m_itemCount - countFreeItems(*m_centralFreeItem);
00260 uint newItemCount = realItemCount + (realItemCount/increaseFraction);
00261 if(newItemCount <= m_itemCount)
00262 newItemCount = m_itemCount+1;
00263
00264 return newItemCount;
00265 }else if(m_needResize) {
00266 uint realItemCount = m_itemCount - countFreeItems(*m_centralFreeItem);
00267 uint newItemCount = realItemCount + (realItemCount/increaseFraction);
00268
00269 return newItemCount;
00270 }
00271 }
00272 return m_itemCount;
00273 }
00274
00276 void transferData(Data* newItems, uint newCount, int* newCentralFree = 0) {
00277 DEBUG_FREEITEM_COUNT
00278
00279 uint currentRealCount = m_itemCount - countFreeItems(*m_centralFreeItem);
00280
00281
00282
00283
00284 uint newFreeCount = newCount - currentRealCount;
00285 volatile uint freeItemRaster;
00286 if(newFreeCount)
00287 freeItemRaster = newCount / newFreeCount;
00288 else {
00289 freeItemRaster = newCount+1;
00290 }
00291
00294 Q_ASSERT(freeItemRaster);
00295 uint offset = 0;
00296 uint insertedValidCount = 0;
00297 for(uint a = 0; a < newCount; ++a) {
00298
00299 if(a % freeItemRaster == (freeItemRaster-1)) {
00300
00301 ItemHandler::createFreeItem(newItems[a]);
00302 ++offset;
00303 }else{
00304 ++insertedValidCount;
00305 while(ItemHandler::isFree(m_items[a-offset]) && a-offset < m_itemCount)
00306 --offset;
00307 Q_ASSERT(a-offset < m_itemCount);
00308 newItems[a] = m_items[a-offset];
00309
00310 }
00311 }
00312 Q_ASSERT(insertedValidCount == m_itemCount - countFreeItems(*m_centralFreeItem));
00313
00314
00315
00316 m_items = newItems;
00317 m_itemCount = newCount;
00318
00319 if(newCentralFree)
00320 m_centralFreeItem = newCentralFree;
00321
00322 *m_centralFreeItem = buildFreeTree(newFreeCount, freeItemRaster, freeItemRaster-1);
00323
00324
00325
00326
00327
00328 DEBUG_FREEITEM_COUNT
00329 }
00330
00332 bool apply(bool force = false) {
00333 if(m_applied)
00334 return true;
00335
00336 if(*m_centralFreeItem == -1) {
00337 Q_ASSERT(!force);
00338 return false;
00339 }
00340
00341
00342 int previousItem = -1;
00343 int currentItem = *m_centralFreeItem;
00344 int replaceCurrentWith = -1;
00345
00346
00347
00348 int currentLowerBound = 0;
00349 int currentUpperBound = m_itemCount;
00350
00351
00352
00353 while(1) {
00354 QPair<int, int> freeBounds = leftAndRightRealItems(currentItem);
00355 const Data& current(m_items[currentItem]);
00356 if(freeBounds.first != -1 && m_add < m_items[freeBounds.first]) {
00357
00358 currentUpperBound = freeBounds.first+1;
00359
00360 if(ItemHandler::leftChild(current) != -1) {
00361
00362 previousItem = currentItem;
00363 currentItem = ItemHandler::leftChild(current);
00364 }else{
00365 replaceCurrentWith = ItemHandler::rightChild(current);
00366 break;
00367 }
00368 }else if(freeBounds.second != -1 && m_items[freeBounds.second] < m_add) {
00369
00370 currentLowerBound = freeBounds.second;
00371
00372 if(ItemHandler::rightChild(current) != -1) {
00373
00374 previousItem = currentItem;
00375 currentItem = ItemHandler::rightChild(current);
00376 }else{
00377 replaceCurrentWith = ItemHandler::leftChild(current);
00378 break;
00379 }
00380 }else{
00381
00382 force = true;
00383 currentLowerBound = currentUpperBound = currentItem;
00384
00385 int leftReplaceCandidate = -1, rightReplaceCandidate = -1;
00386 if(ItemHandler::leftChild(current) != -1)
00387 leftReplaceCandidate = rightMostChild(ItemHandler::leftChild(current));
00388 if(ItemHandler::rightChild(current) != -1)
00389 rightReplaceCandidate = leftMostChild(ItemHandler::rightChild(current));
00390
00392
00393 int leftChildBound = leftMostChild(currentItem), rightChildBound = rightMostChild(currentItem);
00394 Q_ASSERT(leftChildBound != -1 && rightChildBound != -1);
00395 int childCenter = (leftChildBound + rightChildBound)/2;
00396
00397 if(leftReplaceCandidate == -1 && rightReplaceCandidate == -1) {
00398
00399 Q_ASSERT(ItemHandler::leftChild(current) == -1);
00400 Q_ASSERT(ItemHandler::rightChild(current) == -1);
00401 }else if(rightReplaceCandidate == -1 || abs(leftReplaceCandidate - childCenter) < abs(rightReplaceCandidate - childCenter)) {
00402
00403 Q_ASSERT(leftReplaceCandidate != -1);
00404 replaceCurrentWith = leftReplaceCandidate;
00405
00406 Data& replaceWith(m_items[replaceCurrentWith]);
00407
00408 if(replaceCurrentWith == ItemHandler::leftChild(current)) {
00409
00410 Q_ASSERT(ItemHandler::rightChild(replaceWith) == -1);
00411 }else{
00412 takeRightMostChild(ItemHandler::leftChild(current));
00413
00414
00415
00416 int addRightMostLeftChild = ItemHandler::leftChild(replaceWith);
00417
00418 ItemHandler::setLeftChild(replaceWith, -1);
00419
00420 Q_ASSERT(ItemHandler::leftChild(replaceWith) == -1);
00421 Q_ASSERT(ItemHandler::rightChild(replaceWith) == -1);
00422
00423 if(ItemHandler::leftChild(current) != -1)
00424 {
00425 Q_ASSERT(rightMostChild(ItemHandler::leftChild(current)) != replaceCurrentWith);
00426 Q_ASSERT(ItemHandler::leftChild(current) == -1 || ItemHandler::leftChild(current) < replaceCurrentWith);
00427 ItemHandler::setLeftChild(replaceWith, ItemHandler::leftChild(current));
00428
00429 if(addRightMostLeftChild != -1) {
00430 int rightMostLeft = rightMostChild(ItemHandler::leftChild(replaceWith));
00431 Q_ASSERT(rightMostLeft != -1);
00432
00433 Q_ASSERT(rightMostLeft < addRightMostLeftChild);
00434 ItemHandler::setRightChild(m_items[rightMostLeft], addRightMostLeftChild);
00435 }
00436 }else{
00437 Q_ASSERT(addRightMostLeftChild == -1 || addRightMostLeftChild < replaceCurrentWith);
00438 ItemHandler::setLeftChild(replaceWith, addRightMostLeftChild);
00439 }
00440 }
00441
00442 Q_ASSERT(ItemHandler::rightChild(current) == -1 || replaceCurrentWith < ItemHandler::rightChild(current));
00443 ItemHandler::setRightChild(replaceWith, ItemHandler::rightChild(current));
00444 }else{
00445
00446 Q_ASSERT(rightReplaceCandidate != -1);
00447 replaceCurrentWith = rightReplaceCandidate;
00448
00449 Data& replaceWith(m_items[replaceCurrentWith]);
00450
00451 if(replaceCurrentWith == ItemHandler::rightChild(current)) {
00452
00453 Q_ASSERT(ItemHandler::leftChild(replaceWith) == -1);
00454 }else{
00455 takeLeftMostChild(ItemHandler::rightChild(current));
00456
00457
00458
00459 int addLeftMostRightChild = ItemHandler::rightChild(replaceWith);
00460
00461 ItemHandler::setRightChild(replaceWith, -1);
00462
00463 Q_ASSERT(ItemHandler::rightChild(replaceWith) == -1);
00464 Q_ASSERT(ItemHandler::leftChild(replaceWith) == -1);
00465
00466 if(ItemHandler::rightChild(current) != -1)
00467 {
00468 Q_ASSERT(leftMostChild(ItemHandler::rightChild(current)) != replaceCurrentWith);
00469 Q_ASSERT(ItemHandler::rightChild(current) == -1 || replaceCurrentWith < ItemHandler::rightChild(current));
00470 ItemHandler::setRightChild(replaceWith, ItemHandler::rightChild(current));
00471
00472 if(addLeftMostRightChild != -1) {
00473 int leftMostRight = leftMostChild(ItemHandler::rightChild(replaceWith));
00474 Q_ASSERT(leftMostRight != -1);
00475 Q_ASSERT(ItemHandler::leftChild(m_items[leftMostRight]) == -1);
00476 Q_ASSERT(addLeftMostRightChild < leftMostRight);
00477 ItemHandler::setLeftChild(m_items[leftMostRight], addLeftMostRightChild);
00478 }
00479 }else{
00480 Q_ASSERT(addLeftMostRightChild == -1 || replaceCurrentWith < addLeftMostRightChild);
00481 ItemHandler::setRightChild(replaceWith, addLeftMostRightChild);
00482 }
00483 }
00484
00485 Q_ASSERT(ItemHandler::leftChild(current) == -1 || ItemHandler::leftChild(current) < replaceCurrentWith);
00486 ItemHandler::setLeftChild(replaceWith, ItemHandler::leftChild(current));
00487 }
00488 break;
00489 }
00490 }
00491
00492
00493
00494
00495
00496
00497
00498
00499 Q_ASSERT(currentItem < currentLowerBound || currentItem >= currentUpperBound);
00500
00501
00502
00503 if(currentLowerBound < currentUpperBound && (currentItem == currentLowerBound-1 || currentItem == currentUpperBound)) {
00504 if(!insertSorted(m_add, currentItem, currentLowerBound, currentUpperBound, force)) {
00505 return false;
00506 }
00507 }else{
00508 ItemHandler::copyTo(m_add, m_items[currentItem]);
00509 }
00510
00511 m_applied = true;
00512
00513
00514 if(previousItem != -1) {
00515 Data& previous(m_items[previousItem]);
00516 if(ItemHandler::leftChild(previous) == currentItem) {
00517 Q_ASSERT(replaceCurrentWith == -1 || replaceCurrentWith < previousItem);
00518 ItemHandler::setLeftChild(previous, replaceCurrentWith);
00519 } else if(ItemHandler::rightChild(previous) == currentItem) {
00520 Q_ASSERT(replaceCurrentWith == -1 || previousItem < replaceCurrentWith);
00521 ItemHandler::setRightChild(previous, replaceCurrentWith);
00522 } else {
00523 Q_ASSERT(0);
00524 }
00525 } else {
00526 *m_centralFreeItem = replaceCurrentWith;
00527 }
00528
00529 return true;
00530
00531 DEBUG_FREEITEM_COUNT
00532 }
00533
00534 private:
00535 void verifyTreeConsistent(int position, int lowerBound, int upperBound) {
00536 if(position == -1)
00537 return;
00538 Q_ASSERT(lowerBound <= position && position < upperBound);
00539 verifyTreeConsistent(ItemHandler::leftChild(m_items[position]), lowerBound, position);
00540 verifyTreeConsistent(ItemHandler::rightChild(m_items[position]), position+1, upperBound);
00541 }
00542
00543 void debugFreeItemCount() {
00544 uint count = 0;
00545 for(uint a = 0; a < m_itemCount; ++a) {
00546 if(isFree(m_items[a]))
00547 ++count;
00548 }
00549 uint counted = countFreeItems(*m_centralFreeItem);
00550 Q_ASSERT(count == counted);
00551 }
00552
00553 QPair<int, int> leftAndRightRealItems(int pos) {
00554 Q_ASSERT(ItemHandler::isFree(m_items[pos]));
00555 int left = -1, right = -1;
00556 for(int a = pos-1; a >= 0; --a) {
00557 if(!ItemHandler::isFree(m_items[a])) {
00558 left = a;
00559 break;
00560 }
00561 }
00562 for(uint a = pos+1; a < m_itemCount; ++a) {
00563 if(!ItemHandler::isFree(m_items[a])) {
00564 right = a;
00565 break;
00566 }
00567 }
00568 return qMakePair(left, right);
00569 }
00570
00571 int buildFreeTree(int count, uint raster, int start) {
00572 Q_ASSERT((start % raster) == (raster-1));
00573 Q_ASSERT(count != 0);
00574 Q_ASSERT(count <= (int)m_itemCount);
00575 if(count == 1) {
00576 ItemHandler::createFreeItem(m_items[start]);
00577 return start;
00578 }else{
00579 int central = start + (count / 2) * raster;
00580 int leftCount = count / 2;
00581 int midCount = 1;
00582 int rightCount = count - leftCount - midCount;
00583 Q_ASSERT(leftCount + midCount <= count);
00584 ItemHandler::createFreeItem(m_items[central]);
00585 Q_ASSERT(ItemHandler::isFree(m_items[central]));
00586
00587 int leftFreeTree = buildFreeTree(leftCount, raster, start);
00588 Q_ASSERT(leftFreeTree == -1 || leftFreeTree < central);
00589 ItemHandler::setLeftChild(m_items[central], leftFreeTree );
00590
00591 if(rightCount > 0) {
00592 int rightFreeTree = buildFreeTree(rightCount, raster, central+raster);
00593 Q_ASSERT(rightFreeTree == -1 || central < rightFreeTree);
00594 ItemHandler::setRightChild(m_items[central], rightFreeTree );
00595 }
00596
00597 return central;
00598 }
00599 }
00600
00601 uint countFreeItems(int item) const {
00602 if(item == -1)
00603 return 0;
00604 const Data& current(m_items[item]);
00605
00606 return 1 + countFreeItems(ItemHandler::leftChild(current)) + countFreeItems(ItemHandler::rightChild(current));
00607 }
00608
00609 int leftMostChild(int pos) const {
00610 while(1) {
00611 if(ItemHandler::leftChild(m_items[pos]) != -1)
00612 pos = ItemHandler::leftChild(m_items[pos]);
00613 else
00614 return pos;
00615 }
00616 }
00617
00618 int takeLeftMostChild(int pos) const {
00619 int parent = -1;
00620 while(1) {
00621 if(ItemHandler::leftChild(m_items[pos]) != -1) {
00622 parent = pos;
00623 pos = ItemHandler::leftChild(m_items[pos]);
00624 } else {
00625 ItemHandler::setLeftChild(m_items[parent], -1);
00626 return pos;
00627 }
00628 }
00629 }
00630
00631 int rightMostChild(int pos) const {
00632 while(1) {
00633 if(ItemHandler::rightChild(m_items[pos]) != -1)
00634 pos = ItemHandler::rightChild(m_items[pos]);
00635 else
00636 return pos;
00637 }
00638 }
00639
00640 int takeRightMostChild(int pos) const {
00641 int parent = -1;
00642 while(1) {
00643 if(ItemHandler::rightChild(m_items[pos]) != -1) {
00644 parent = pos;
00645 pos = ItemHandler::rightChild(m_items[pos]);
00646 } else {
00647 ItemHandler::setRightChild(m_items[parent], -1);
00648 return pos;
00649 }
00650 }
00651 }
00652
00653 void insertBubbleSorted(const Data& data, int pos) {
00654
00655 ItemHandler::copyTo(data, m_items[pos]);
00656 while(1) {
00657 int prev = pos-1;
00658 int next = pos+1;
00659 if(prev >= 0 && !ItemHandler::isFree(m_items[prev]) && m_items[pos] < m_items[prev]) {
00660 Data backup(m_items[prev]);
00661 m_items[prev] = m_items[pos];
00662 m_items[pos] = backup;
00663 pos = prev;
00664 }else if(next < m_itemCount && !ItemHandler::isFree(m_items[next]) && m_items[next] < m_items[pos]) {
00665 Data backup(m_items[next]);
00666 m_items[next] = m_items[pos];
00667 m_items[pos] = backup;
00668 pos = next;
00669 }else{
00670 break;
00671 }
00672 }
00673 }
00674
00676 inline int maxMoveAround() const {
00677 return increaseFraction * rebuildIfInsertionMoreExpensive;
00678 }
00679
00683 bool insertSorted(const Data& data, int pos, int start, int end, bool force) {
00684
00685 if(pos < start)
00686 start = pos;
00687 if(pos >= end)
00688 end = pos+1;
00689
00690
00691
00692
00693
00694
00695 EmbeddedTreeAlgorithms<Data, ItemHandler> alg(m_items, m_itemCount, *m_centralFreeItem);
00696 int bound = alg.lowerBound(data, start, end);
00697
00698 if(bound == -1)
00699 bound = end;
00700
00701
00702
00703 int target;
00704
00705 Q_ASSERT(bound != pos);
00706
00707
00708 char backup[sizeof(Data)];
00709 memcpy(backup, m_items+pos, sizeof(Data));
00710
00711 if(bound < pos) {
00712 if(!force && pos-bound > maxMoveAround()) {
00713
00714 return false;
00715 }
00716
00717 memmove(m_items+bound+1, m_items+bound, sizeof(Data)*(pos-bound));
00718 target = bound;
00719 }else {
00720 Q_ASSERT(bound > pos);
00721 if(!force && bound-pos-1 > maxMoveAround()) {
00722
00723 return false;
00724 }
00725
00726 memmove(m_items+pos, m_items+pos+1, sizeof(Data)*(bound-pos-1));
00727 target = bound-1;
00728 }
00729 memcpy(m_items+target, backup, sizeof(Data));
00730
00731 ItemHandler::copyTo(data, m_items[target]);
00732 return true;
00733 }
00734
00735 const Data& m_add;
00736 Data* m_items;
00737 uint m_itemCount;
00738 int* m_centralFreeItem;
00739 bool m_applied, m_needResize;
00740 };
00741
00751 template<class Data, class ItemHandler, int increaseFraction = 5 >
00752 class EmbeddedTreeRemoveItem {
00753
00754 public:
00755
00756 EmbeddedTreeRemoveItem(Data* items, uint itemCount, int& centralFreeItem, const Data& remove) : m_remove(remove), m_items(items), m_itemCount(itemCount), m_centralFreeItem(¢ralFreeItem), m_insertedAtDepth(0) {
00757 apply();
00758 }
00759
00760 ~EmbeddedTreeRemoveItem() {
00761 }
00762
00765 uint newItemCount() const {
00766 uint maxFreeItems = ((m_itemCount / increaseFraction)*3)/2 + 1;
00767
00768 if((1u << m_insertedAtDepth) >= maxFreeItems) {
00769 uint freeCount = countFreeItems(*m_centralFreeItem);
00770 if(freeCount > maxFreeItems || freeCount == m_itemCount) {
00771 return m_itemCount - freeCount;
00772 }
00773 }
00774
00775 return m_itemCount;
00776 }
00777
00779 void transferData(Data* newItems, uint newCount, int* newCentralFree = 0) {
00780 DEBUG_FREEITEM_COUNT
00781
00782
00783
00784 uint offset = 0;
00785 for(uint a = 0; a < m_itemCount; ++a) {
00786 if(!ItemHandler::isFree(m_items[a])) {
00787 newItems[offset] = m_items[a];
00788 ++offset;
00789 }
00790 }
00791 Q_ASSERT(offset == newCount);
00792
00793 if(newCentralFree)
00794 m_centralFreeItem = newCentralFree;
00795 *m_centralFreeItem = -1;
00796 m_items = newItems;
00797 m_itemCount = newCount;
00798 DEBUG_FREEITEM_COUNT
00799 }
00800
00801 private:
00802 void verifyTreeConsistent(int position, int lowerBound, int upperBound) {
00803 if(position == -1)
00804 return;
00805 Q_ASSERT(lowerBound <= position && position < upperBound);
00806 verifyTreeConsistent(ItemHandler::leftChild(m_items[position]), lowerBound, position);
00807 verifyTreeConsistent(ItemHandler::rightChild(m_items[position]), position+1, upperBound);
00808 }
00809
00810 uint countFreeItems(int item) const {
00811 if(item == -1)
00812 return 0;
00813 const Data& current(m_items[item]);
00814
00815 return 1 + countFreeItems(ItemHandler::leftChild(current)) + countFreeItems(ItemHandler::rightChild(current));
00816 }
00817
00818 int findItem(const Data& data, uint start, uint end) {
00819 EmbeddedTreeAlgorithms<Data, ItemHandler> alg(m_items, m_itemCount, *m_centralFreeItem);
00820 return alg.indexOf(data, start, end);
00821 }
00822
00823 void apply() {
00824 DEBUG_FREEITEM_COUNT
00825
00826 int removeIndex = findItem(m_remove, 0, m_itemCount);
00827 Q_ASSERT(removeIndex != -1);
00828 Q_ASSERT(!ItemHandler::isFree(m_items[removeIndex]));
00829
00830
00831 int previousItem = -1;
00832 int currentItem = *m_centralFreeItem;
00833
00834 int lowerBound = 0;
00835 int upperBound = m_itemCount;
00836
00837 if(*m_centralFreeItem == -1) {
00838 *m_centralFreeItem = removeIndex;
00839 Q_ASSERT(*m_centralFreeItem != -1);
00840 ItemHandler::createFreeItem(m_items[*m_centralFreeItem]);
00841 return;
00842 }
00843
00844
00847 while(1) {
00848 Q_ASSERT(removeIndex != currentItem);
00849 Data& current(m_items[currentItem]);
00850 ++m_insertedAtDepth;
00851 if(removeIndex < currentItem) {
00852 upperBound = currentItem;
00853
00854 if(ItemHandler::leftChild(current) != -1) {
00855
00856 previousItem = currentItem;
00857 currentItem = ItemHandler::leftChild(current);
00858 Q_ASSERT(currentItem >= lowerBound && currentItem < upperBound);
00859 }else{
00860
00861 int item = findItem(m_remove, lowerBound, upperBound);
00862 Q_ASSERT(item == removeIndex);
00863 ItemHandler::createFreeItem(m_items[item]);
00864 Q_ASSERT(item == -1 || item < currentItem);
00865 ItemHandler::setLeftChild(current, item);
00866 Q_ASSERT(item >= lowerBound && item < upperBound);
00867 break;
00868 }
00869 }else{
00870 lowerBound = currentItem+1;
00871
00872 if(ItemHandler::rightChild(current) != -1) {
00873
00874 previousItem = currentItem;
00875 currentItem = ItemHandler::rightChild(current);
00876 Q_ASSERT(currentItem >= lowerBound && currentItem < upperBound);
00877 }else{
00878
00879 int item = findItem(m_remove, lowerBound, upperBound);
00880 Q_ASSERT(item == removeIndex);
00881 ItemHandler::createFreeItem(m_items[item]);
00882 Q_ASSERT(item == -1 || currentItem < item);
00883 ItemHandler::setRightChild(current, item);
00884 Q_ASSERT(item >= lowerBound && item < upperBound);
00885 break;
00886 }
00887 }
00888 }
00889
00890 DEBUG_FREEITEM_COUNT
00891 }
00892
00893 void debugFreeItemCount() {
00894 uint count = 0;
00895 for(uint a = 0; a < m_itemCount; ++a) {
00896 if(ItemHandler::isFree(m_items[a]))
00897 ++count;
00898 }
00899 uint counted = countFreeItems(*m_centralFreeItem);
00900 Q_ASSERT(count == counted);
00901 }
00902
00903 const Data& m_remove;
00904 Data* m_items;
00905 uint m_itemCount;
00906 int* m_centralFreeItem;
00907 int m_insertedAtDepth;
00908 };
00909 }
00910
00911 #endif