gfx/skia/trunk/src/gpu/GrRedBlackTree.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * Copyright 2011 Google Inc.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #ifndef GrRedBlackTree_DEFINED
michael@0 9 #define GrRedBlackTree_DEFINED
michael@0 10
michael@0 11 #include "GrConfig.h"
michael@0 12 #include "SkTypes.h"
michael@0 13
michael@0 14 template <typename T>
michael@0 15 class GrLess {
michael@0 16 public:
michael@0 17 bool operator()(const T& a, const T& b) const { return a < b; }
michael@0 18 };
michael@0 19
michael@0 20 template <typename T>
michael@0 21 class GrLess<T*> {
michael@0 22 public:
michael@0 23 bool operator()(const T* a, const T* b) const { return *a < *b; }
michael@0 24 };
michael@0 25
michael@0 26 class GrStrLess {
michael@0 27 public:
michael@0 28 bool operator()(const char* a, const char* b) const { return strcmp(a,b) < 0; }
michael@0 29 };
michael@0 30
michael@0 31 /**
michael@0 32 * In debug build this will cause full traversals of the tree when the validate
michael@0 33 * is called on insert and remove. Useful for debugging but very slow.
michael@0 34 */
michael@0 35 #define DEEP_VALIDATE 0
michael@0 36
michael@0 37 /**
michael@0 38 * A sorted tree that uses the red-black tree algorithm. Allows duplicate
michael@0 39 * entries. Data is of type T and is compared using functor C. A single C object
michael@0 40 * will be created and used for all comparisons.
michael@0 41 */
michael@0 42 template <typename T, typename C = GrLess<T> >
michael@0 43 class GrRedBlackTree : public SkNoncopyable {
michael@0 44 public:
michael@0 45 /**
michael@0 46 * Creates an empty tree.
michael@0 47 */
michael@0 48 GrRedBlackTree();
michael@0 49 virtual ~GrRedBlackTree();
michael@0 50
michael@0 51 /**
michael@0 52 * Class used to iterater through the tree. The valid range of the tree
michael@0 53 * is given by [begin(), end()). It is legal to dereference begin() but not
michael@0 54 * end(). The iterator has preincrement and predecrement operators, it is
michael@0 55 * legal to decerement end() if the tree is not empty to get the last
michael@0 56 * element. However, a last() helper is provided.
michael@0 57 */
michael@0 58 class Iter;
michael@0 59
michael@0 60 /**
michael@0 61 * Add an element to the tree. Duplicates are allowed.
michael@0 62 * @param t the item to add.
michael@0 63 * @return an iterator to the item.
michael@0 64 */
michael@0 65 Iter insert(const T& t);
michael@0 66
michael@0 67 /**
michael@0 68 * Removes all items in the tree.
michael@0 69 */
michael@0 70 void reset();
michael@0 71
michael@0 72 /**
michael@0 73 * @return true if there are no items in the tree, false otherwise.
michael@0 74 */
michael@0 75 bool empty() const {return 0 == fCount;}
michael@0 76
michael@0 77 /**
michael@0 78 * @return the number of items in the tree.
michael@0 79 */
michael@0 80 int count() const {return fCount;}
michael@0 81
michael@0 82 /**
michael@0 83 * @return an iterator to the first item in sorted order, or end() if empty
michael@0 84 */
michael@0 85 Iter begin();
michael@0 86 /**
michael@0 87 * Gets the last valid iterator. This is always valid, even on an empty.
michael@0 88 * However, it can never be dereferenced. Useful as a loop terminator.
michael@0 89 * @return an iterator that is just beyond the last item in sorted order.
michael@0 90 */
michael@0 91 Iter end();
michael@0 92 /**
michael@0 93 * @return an iterator that to the last item in sorted order, or end() if
michael@0 94 * empty.
michael@0 95 */
michael@0 96 Iter last();
michael@0 97
michael@0 98 /**
michael@0 99 * Finds an occurrence of an item.
michael@0 100 * @param t the item to find.
michael@0 101 * @return an iterator to a tree element equal to t or end() if none exists.
michael@0 102 */
michael@0 103 Iter find(const T& t);
michael@0 104 /**
michael@0 105 * Finds the first of an item in iterator order.
michael@0 106 * @param t the item to find.
michael@0 107 * @return an iterator to the first element equal to t or end() if
michael@0 108 * none exists.
michael@0 109 */
michael@0 110 Iter findFirst(const T& t);
michael@0 111 /**
michael@0 112 * Finds the last of an item in iterator order.
michael@0 113 * @param t the item to find.
michael@0 114 * @return an iterator to the last element equal to t or end() if
michael@0 115 * none exists.
michael@0 116 */
michael@0 117 Iter findLast(const T& t);
michael@0 118 /**
michael@0 119 * Gets the number of items in the tree equal to t.
michael@0 120 * @param t the item to count.
michael@0 121 * @return number of items equal to t in the tree
michael@0 122 */
michael@0 123 int countOf(const T& t) const;
michael@0 124
michael@0 125 /**
michael@0 126 * Removes the item indicated by an iterator. The iterator will not be valid
michael@0 127 * afterwards.
michael@0 128 *
michael@0 129 * @param iter iterator of item to remove. Must be valid (not end()).
michael@0 130 */
michael@0 131 void remove(const Iter& iter) { deleteAtNode(iter.fN); }
michael@0 132
michael@0 133 private:
michael@0 134 enum Color {
michael@0 135 kRed_Color,
michael@0 136 kBlack_Color
michael@0 137 };
michael@0 138
michael@0 139 enum Child {
michael@0 140 kLeft_Child = 0,
michael@0 141 kRight_Child = 1
michael@0 142 };
michael@0 143
michael@0 144 struct Node {
michael@0 145 T fItem;
michael@0 146 Color fColor;
michael@0 147
michael@0 148 Node* fParent;
michael@0 149 Node* fChildren[2];
michael@0 150 };
michael@0 151
michael@0 152 void rotateRight(Node* n);
michael@0 153 void rotateLeft(Node* n);
michael@0 154
michael@0 155 static Node* SuccessorNode(Node* x);
michael@0 156 static Node* PredecessorNode(Node* x);
michael@0 157
michael@0 158 void deleteAtNode(Node* x);
michael@0 159 static void RecursiveDelete(Node* x);
michael@0 160
michael@0 161 int onCountOf(const Node* n, const T& t) const;
michael@0 162
michael@0 163 #ifdef SK_DEBUG
michael@0 164 void validate() const;
michael@0 165 int checkNode(Node* n, int* blackHeight) const;
michael@0 166 // checks relationship between a node and its children. allowRedRed means
michael@0 167 // node may be in an intermediate state where a red parent has a red child.
michael@0 168 bool validateChildRelations(const Node* n, bool allowRedRed) const;
michael@0 169 // place to stick break point if validateChildRelations is failing.
michael@0 170 bool validateChildRelationsFailed() const { return false; }
michael@0 171 #else
michael@0 172 void validate() const {}
michael@0 173 #endif
michael@0 174
michael@0 175 int fCount;
michael@0 176 Node* fRoot;
michael@0 177 Node* fFirst;
michael@0 178 Node* fLast;
michael@0 179
michael@0 180 const C fComp;
michael@0 181 };
michael@0 182
michael@0 183 template <typename T, typename C>
michael@0 184 class GrRedBlackTree<T,C>::Iter {
michael@0 185 public:
michael@0 186 Iter() {};
michael@0 187 Iter(const Iter& i) {fN = i.fN; fTree = i.fTree;}
michael@0 188 Iter& operator =(const Iter& i) {
michael@0 189 fN = i.fN;
michael@0 190 fTree = i.fTree;
michael@0 191 return *this;
michael@0 192 }
michael@0 193 // altering the sort value of the item using this method will cause
michael@0 194 // errors.
michael@0 195 T& operator *() const { return fN->fItem; }
michael@0 196 bool operator ==(const Iter& i) const {
michael@0 197 return fN == i.fN && fTree == i.fTree;
michael@0 198 }
michael@0 199 bool operator !=(const Iter& i) const { return !(*this == i); }
michael@0 200 Iter& operator ++() {
michael@0 201 SkASSERT(*this != fTree->end());
michael@0 202 fN = SuccessorNode(fN);
michael@0 203 return *this;
michael@0 204 }
michael@0 205 Iter& operator --() {
michael@0 206 SkASSERT(*this != fTree->begin());
michael@0 207 if (NULL != fN) {
michael@0 208 fN = PredecessorNode(fN);
michael@0 209 } else {
michael@0 210 *this = fTree->last();
michael@0 211 }
michael@0 212 return *this;
michael@0 213 }
michael@0 214
michael@0 215 private:
michael@0 216 friend class GrRedBlackTree;
michael@0 217 explicit Iter(Node* n, GrRedBlackTree* tree) {
michael@0 218 fN = n;
michael@0 219 fTree = tree;
michael@0 220 }
michael@0 221 Node* fN;
michael@0 222 GrRedBlackTree* fTree;
michael@0 223 };
michael@0 224
michael@0 225 template <typename T, typename C>
michael@0 226 GrRedBlackTree<T,C>::GrRedBlackTree() : fComp() {
michael@0 227 fRoot = NULL;
michael@0 228 fFirst = NULL;
michael@0 229 fLast = NULL;
michael@0 230 fCount = 0;
michael@0 231 validate();
michael@0 232 }
michael@0 233
michael@0 234 template <typename T, typename C>
michael@0 235 GrRedBlackTree<T,C>::~GrRedBlackTree() {
michael@0 236 RecursiveDelete(fRoot);
michael@0 237 }
michael@0 238
michael@0 239 template <typename T, typename C>
michael@0 240 typename GrRedBlackTree<T,C>::Iter GrRedBlackTree<T,C>::begin() {
michael@0 241 return Iter(fFirst, this);
michael@0 242 }
michael@0 243
michael@0 244 template <typename T, typename C>
michael@0 245 typename GrRedBlackTree<T,C>::Iter GrRedBlackTree<T,C>::end() {
michael@0 246 return Iter(NULL, this);
michael@0 247 }
michael@0 248
michael@0 249 template <typename T, typename C>
michael@0 250 typename GrRedBlackTree<T,C>::Iter GrRedBlackTree<T,C>::last() {
michael@0 251 return Iter(fLast, this);
michael@0 252 }
michael@0 253
michael@0 254 template <typename T, typename C>
michael@0 255 typename GrRedBlackTree<T,C>::Iter GrRedBlackTree<T,C>::find(const T& t) {
michael@0 256 Node* n = fRoot;
michael@0 257 while (NULL != n) {
michael@0 258 if (fComp(t, n->fItem)) {
michael@0 259 n = n->fChildren[kLeft_Child];
michael@0 260 } else {
michael@0 261 if (!fComp(n->fItem, t)) {
michael@0 262 return Iter(n, this);
michael@0 263 }
michael@0 264 n = n->fChildren[kRight_Child];
michael@0 265 }
michael@0 266 }
michael@0 267 return end();
michael@0 268 }
michael@0 269
michael@0 270 template <typename T, typename C>
michael@0 271 typename GrRedBlackTree<T,C>::Iter GrRedBlackTree<T,C>::findFirst(const T& t) {
michael@0 272 Node* n = fRoot;
michael@0 273 Node* leftMost = NULL;
michael@0 274 while (NULL != n) {
michael@0 275 if (fComp(t, n->fItem)) {
michael@0 276 n = n->fChildren[kLeft_Child];
michael@0 277 } else {
michael@0 278 if (!fComp(n->fItem, t)) {
michael@0 279 // found one. check if another in left subtree.
michael@0 280 leftMost = n;
michael@0 281 n = n->fChildren[kLeft_Child];
michael@0 282 } else {
michael@0 283 n = n->fChildren[kRight_Child];
michael@0 284 }
michael@0 285 }
michael@0 286 }
michael@0 287 return Iter(leftMost, this);
michael@0 288 }
michael@0 289
michael@0 290 template <typename T, typename C>
michael@0 291 typename GrRedBlackTree<T,C>::Iter GrRedBlackTree<T,C>::findLast(const T& t) {
michael@0 292 Node* n = fRoot;
michael@0 293 Node* rightMost = NULL;
michael@0 294 while (NULL != n) {
michael@0 295 if (fComp(t, n->fItem)) {
michael@0 296 n = n->fChildren[kLeft_Child];
michael@0 297 } else {
michael@0 298 if (!fComp(n->fItem, t)) {
michael@0 299 // found one. check if another in right subtree.
michael@0 300 rightMost = n;
michael@0 301 }
michael@0 302 n = n->fChildren[kRight_Child];
michael@0 303 }
michael@0 304 }
michael@0 305 return Iter(rightMost, this);
michael@0 306 }
michael@0 307
michael@0 308 template <typename T, typename C>
michael@0 309 int GrRedBlackTree<T,C>::countOf(const T& t) const {
michael@0 310 return onCountOf(fRoot, t);
michael@0 311 }
michael@0 312
michael@0 313 template <typename T, typename C>
michael@0 314 int GrRedBlackTree<T,C>::onCountOf(const Node* n, const T& t) const {
michael@0 315 // this is count*log(n) :(
michael@0 316 while (NULL != n) {
michael@0 317 if (fComp(t, n->fItem)) {
michael@0 318 n = n->fChildren[kLeft_Child];
michael@0 319 } else {
michael@0 320 if (!fComp(n->fItem, t)) {
michael@0 321 int count = 1;
michael@0 322 count += onCountOf(n->fChildren[kLeft_Child], t);
michael@0 323 count += onCountOf(n->fChildren[kRight_Child], t);
michael@0 324 return count;
michael@0 325 }
michael@0 326 n = n->fChildren[kRight_Child];
michael@0 327 }
michael@0 328 }
michael@0 329 return 0;
michael@0 330
michael@0 331 }
michael@0 332
michael@0 333 template <typename T, typename C>
michael@0 334 void GrRedBlackTree<T,C>::reset() {
michael@0 335 RecursiveDelete(fRoot);
michael@0 336 fRoot = NULL;
michael@0 337 fFirst = NULL;
michael@0 338 fLast = NULL;
michael@0 339 fCount = 0;
michael@0 340 }
michael@0 341
michael@0 342 template <typename T, typename C>
michael@0 343 typename GrRedBlackTree<T,C>::Iter GrRedBlackTree<T,C>::insert(const T& t) {
michael@0 344 validate();
michael@0 345
michael@0 346 ++fCount;
michael@0 347
michael@0 348 Node* x = SkNEW(Node);
michael@0 349 x->fChildren[kLeft_Child] = NULL;
michael@0 350 x->fChildren[kRight_Child] = NULL;
michael@0 351 x->fItem = t;
michael@0 352
michael@0 353 Node* returnNode = x;
michael@0 354
michael@0 355 Node* gp = NULL;
michael@0 356 Node* p = NULL;
michael@0 357 Node* n = fRoot;
michael@0 358 Child pc = kLeft_Child; // suppress uninit warning
michael@0 359 Child gpc = kLeft_Child;
michael@0 360
michael@0 361 bool first = true;
michael@0 362 bool last = true;
michael@0 363 while (NULL != n) {
michael@0 364 gpc = pc;
michael@0 365 pc = fComp(x->fItem, n->fItem) ? kLeft_Child : kRight_Child;
michael@0 366 first = first && kLeft_Child == pc;
michael@0 367 last = last && kRight_Child == pc;
michael@0 368 gp = p;
michael@0 369 p = n;
michael@0 370 n = p->fChildren[pc];
michael@0 371 }
michael@0 372 if (last) {
michael@0 373 fLast = x;
michael@0 374 }
michael@0 375 if (first) {
michael@0 376 fFirst = x;
michael@0 377 }
michael@0 378
michael@0 379 if (NULL == p) {
michael@0 380 fRoot = x;
michael@0 381 x->fColor = kBlack_Color;
michael@0 382 x->fParent = NULL;
michael@0 383 SkASSERT(1 == fCount);
michael@0 384 return Iter(returnNode, this);
michael@0 385 }
michael@0 386 p->fChildren[pc] = x;
michael@0 387 x->fColor = kRed_Color;
michael@0 388 x->fParent = p;
michael@0 389
michael@0 390 do {
michael@0 391 // assumptions at loop start.
michael@0 392 SkASSERT(NULL != x);
michael@0 393 SkASSERT(kRed_Color == x->fColor);
michael@0 394 // can't have a grandparent but no parent.
michael@0 395 SkASSERT(!(NULL != gp && NULL == p));
michael@0 396 // make sure pc and gpc are correct
michael@0 397 SkASSERT(NULL == p || p->fChildren[pc] == x);
michael@0 398 SkASSERT(NULL == gp || gp->fChildren[gpc] == p);
michael@0 399
michael@0 400 // if x's parent is black then we didn't violate any of the
michael@0 401 // red/black properties when we added x as red.
michael@0 402 if (kBlack_Color == p->fColor) {
michael@0 403 return Iter(returnNode, this);
michael@0 404 }
michael@0 405 // gp must be valid because if p was the root then it is black
michael@0 406 SkASSERT(NULL != gp);
michael@0 407 // gp must be black since it's child, p, is red.
michael@0 408 SkASSERT(kBlack_Color == gp->fColor);
michael@0 409
michael@0 410
michael@0 411 // x and its parent are red, violating red-black property.
michael@0 412 Node* u = gp->fChildren[1-gpc];
michael@0 413 // if x's uncle (p's sibling) is also red then we can flip
michael@0 414 // p and u to black and make gp red. But then we have to recurse
michael@0 415 // up to gp since it's parent may also be red.
michael@0 416 if (NULL != u && kRed_Color == u->fColor) {
michael@0 417 p->fColor = kBlack_Color;
michael@0 418 u->fColor = kBlack_Color;
michael@0 419 gp->fColor = kRed_Color;
michael@0 420 x = gp;
michael@0 421 p = x->fParent;
michael@0 422 if (NULL == p) {
michael@0 423 // x (prev gp) is the root, color it black and be done.
michael@0 424 SkASSERT(fRoot == x);
michael@0 425 x->fColor = kBlack_Color;
michael@0 426 validate();
michael@0 427 return Iter(returnNode, this);
michael@0 428 }
michael@0 429 gp = p->fParent;
michael@0 430 pc = (p->fChildren[kLeft_Child] == x) ? kLeft_Child :
michael@0 431 kRight_Child;
michael@0 432 if (NULL != gp) {
michael@0 433 gpc = (gp->fChildren[kLeft_Child] == p) ? kLeft_Child :
michael@0 434 kRight_Child;
michael@0 435 }
michael@0 436 continue;
michael@0 437 } break;
michael@0 438 } while (true);
michael@0 439 // Here p is red but u is black and we still have to resolve the fact
michael@0 440 // that x and p are both red.
michael@0 441 SkASSERT(NULL == gp->fChildren[1-gpc] || kBlack_Color == gp->fChildren[1-gpc]->fColor);
michael@0 442 SkASSERT(kRed_Color == x->fColor);
michael@0 443 SkASSERT(kRed_Color == p->fColor);
michael@0 444 SkASSERT(kBlack_Color == gp->fColor);
michael@0 445
michael@0 446 // make x be on the same side of p as p is of gp. If it isn't already
michael@0 447 // the case then rotate x up to p and swap their labels.
michael@0 448 if (pc != gpc) {
michael@0 449 if (kRight_Child == pc) {
michael@0 450 rotateLeft(p);
michael@0 451 Node* temp = p;
michael@0 452 p = x;
michael@0 453 x = temp;
michael@0 454 pc = kLeft_Child;
michael@0 455 } else {
michael@0 456 rotateRight(p);
michael@0 457 Node* temp = p;
michael@0 458 p = x;
michael@0 459 x = temp;
michael@0 460 pc = kRight_Child;
michael@0 461 }
michael@0 462 }
michael@0 463 // we now rotate gp down, pulling up p to be it's new parent.
michael@0 464 // gp's child, u, that is not affected we know to be black. gp's new
michael@0 465 // child is p's previous child (x's pre-rotation sibling) which must be
michael@0 466 // black since p is red.
michael@0 467 SkASSERT(NULL == p->fChildren[1-pc] ||
michael@0 468 kBlack_Color == p->fChildren[1-pc]->fColor);
michael@0 469 // Since gp's two children are black it can become red if p is made
michael@0 470 // black. This leaves the black-height of both of p's new subtrees
michael@0 471 // preserved and removes the red/red parent child relationship.
michael@0 472 p->fColor = kBlack_Color;
michael@0 473 gp->fColor = kRed_Color;
michael@0 474 if (kLeft_Child == pc) {
michael@0 475 rotateRight(gp);
michael@0 476 } else {
michael@0 477 rotateLeft(gp);
michael@0 478 }
michael@0 479 validate();
michael@0 480 return Iter(returnNode, this);
michael@0 481 }
michael@0 482
michael@0 483
michael@0 484 template <typename T, typename C>
michael@0 485 void GrRedBlackTree<T,C>::rotateRight(Node* n) {
michael@0 486 /* d? d?
michael@0 487 * / /
michael@0 488 * n s
michael@0 489 * / \ ---> / \
michael@0 490 * s a? c? n
michael@0 491 * / \ / \
michael@0 492 * c? b? b? a?
michael@0 493 */
michael@0 494 Node* d = n->fParent;
michael@0 495 Node* s = n->fChildren[kLeft_Child];
michael@0 496 SkASSERT(NULL != s);
michael@0 497 Node* b = s->fChildren[kRight_Child];
michael@0 498
michael@0 499 if (NULL != d) {
michael@0 500 Child c = d->fChildren[kLeft_Child] == n ? kLeft_Child :
michael@0 501 kRight_Child;
michael@0 502 d->fChildren[c] = s;
michael@0 503 } else {
michael@0 504 SkASSERT(fRoot == n);
michael@0 505 fRoot = s;
michael@0 506 }
michael@0 507 s->fParent = d;
michael@0 508 s->fChildren[kRight_Child] = n;
michael@0 509 n->fParent = s;
michael@0 510 n->fChildren[kLeft_Child] = b;
michael@0 511 if (NULL != b) {
michael@0 512 b->fParent = n;
michael@0 513 }
michael@0 514
michael@0 515 GR_DEBUGASSERT(validateChildRelations(d, true));
michael@0 516 GR_DEBUGASSERT(validateChildRelations(s, true));
michael@0 517 GR_DEBUGASSERT(validateChildRelations(n, false));
michael@0 518 GR_DEBUGASSERT(validateChildRelations(n->fChildren[kRight_Child], true));
michael@0 519 GR_DEBUGASSERT(validateChildRelations(b, true));
michael@0 520 GR_DEBUGASSERT(validateChildRelations(s->fChildren[kLeft_Child], true));
michael@0 521 }
michael@0 522
michael@0 523 template <typename T, typename C>
michael@0 524 void GrRedBlackTree<T,C>::rotateLeft(Node* n) {
michael@0 525
michael@0 526 Node* d = n->fParent;
michael@0 527 Node* s = n->fChildren[kRight_Child];
michael@0 528 SkASSERT(NULL != s);
michael@0 529 Node* b = s->fChildren[kLeft_Child];
michael@0 530
michael@0 531 if (NULL != d) {
michael@0 532 Child c = d->fChildren[kRight_Child] == n ? kRight_Child :
michael@0 533 kLeft_Child;
michael@0 534 d->fChildren[c] = s;
michael@0 535 } else {
michael@0 536 SkASSERT(fRoot == n);
michael@0 537 fRoot = s;
michael@0 538 }
michael@0 539 s->fParent = d;
michael@0 540 s->fChildren[kLeft_Child] = n;
michael@0 541 n->fParent = s;
michael@0 542 n->fChildren[kRight_Child] = b;
michael@0 543 if (NULL != b) {
michael@0 544 b->fParent = n;
michael@0 545 }
michael@0 546
michael@0 547 GR_DEBUGASSERT(validateChildRelations(d, true));
michael@0 548 GR_DEBUGASSERT(validateChildRelations(s, true));
michael@0 549 GR_DEBUGASSERT(validateChildRelations(n, true));
michael@0 550 GR_DEBUGASSERT(validateChildRelations(n->fChildren[kLeft_Child], true));
michael@0 551 GR_DEBUGASSERT(validateChildRelations(b, true));
michael@0 552 GR_DEBUGASSERT(validateChildRelations(s->fChildren[kRight_Child], true));
michael@0 553 }
michael@0 554
michael@0 555 template <typename T, typename C>
michael@0 556 typename GrRedBlackTree<T,C>::Node* GrRedBlackTree<T,C>::SuccessorNode(Node* x) {
michael@0 557 SkASSERT(NULL != x);
michael@0 558 if (NULL != x->fChildren[kRight_Child]) {
michael@0 559 x = x->fChildren[kRight_Child];
michael@0 560 while (NULL != x->fChildren[kLeft_Child]) {
michael@0 561 x = x->fChildren[kLeft_Child];
michael@0 562 }
michael@0 563 return x;
michael@0 564 }
michael@0 565 while (NULL != x->fParent && x == x->fParent->fChildren[kRight_Child]) {
michael@0 566 x = x->fParent;
michael@0 567 }
michael@0 568 return x->fParent;
michael@0 569 }
michael@0 570
michael@0 571 template <typename T, typename C>
michael@0 572 typename GrRedBlackTree<T,C>::Node* GrRedBlackTree<T,C>::PredecessorNode(Node* x) {
michael@0 573 SkASSERT(NULL != x);
michael@0 574 if (NULL != x->fChildren[kLeft_Child]) {
michael@0 575 x = x->fChildren[kLeft_Child];
michael@0 576 while (NULL != x->fChildren[kRight_Child]) {
michael@0 577 x = x->fChildren[kRight_Child];
michael@0 578 }
michael@0 579 return x;
michael@0 580 }
michael@0 581 while (NULL != x->fParent && x == x->fParent->fChildren[kLeft_Child]) {
michael@0 582 x = x->fParent;
michael@0 583 }
michael@0 584 return x->fParent;
michael@0 585 }
michael@0 586
michael@0 587 template <typename T, typename C>
michael@0 588 void GrRedBlackTree<T,C>::deleteAtNode(Node* x) {
michael@0 589 SkASSERT(NULL != x);
michael@0 590 validate();
michael@0 591 --fCount;
michael@0 592
michael@0 593 bool hasLeft = NULL != x->fChildren[kLeft_Child];
michael@0 594 bool hasRight = NULL != x->fChildren[kRight_Child];
michael@0 595 Child c = hasLeft ? kLeft_Child : kRight_Child;
michael@0 596
michael@0 597 if (hasLeft && hasRight) {
michael@0 598 // first and last can't have two children.
michael@0 599 SkASSERT(fFirst != x);
michael@0 600 SkASSERT(fLast != x);
michael@0 601 // if x is an interior node then we find it's successor
michael@0 602 // and swap them.
michael@0 603 Node* s = x->fChildren[kRight_Child];
michael@0 604 while (NULL != s->fChildren[kLeft_Child]) {
michael@0 605 s = s->fChildren[kLeft_Child];
michael@0 606 }
michael@0 607 SkASSERT(NULL != s);
michael@0 608 // this might be expensive relative to swapping node ptrs around.
michael@0 609 // depends on T.
michael@0 610 x->fItem = s->fItem;
michael@0 611 x = s;
michael@0 612 c = kRight_Child;
michael@0 613 } else if (NULL == x->fParent) {
michael@0 614 // if x was the root we just replace it with its child and make
michael@0 615 // the new root (if the tree is not empty) black.
michael@0 616 SkASSERT(fRoot == x);
michael@0 617 fRoot = x->fChildren[c];
michael@0 618 if (NULL != fRoot) {
michael@0 619 fRoot->fParent = NULL;
michael@0 620 fRoot->fColor = kBlack_Color;
michael@0 621 if (x == fLast) {
michael@0 622 SkASSERT(c == kLeft_Child);
michael@0 623 fLast = fRoot;
michael@0 624 } else if (x == fFirst) {
michael@0 625 SkASSERT(c == kRight_Child);
michael@0 626 fFirst = fRoot;
michael@0 627 }
michael@0 628 } else {
michael@0 629 SkASSERT(fFirst == fLast && x == fFirst);
michael@0 630 fFirst = NULL;
michael@0 631 fLast = NULL;
michael@0 632 SkASSERT(0 == fCount);
michael@0 633 }
michael@0 634 delete x;
michael@0 635 validate();
michael@0 636 return;
michael@0 637 }
michael@0 638
michael@0 639 Child pc;
michael@0 640 Node* p = x->fParent;
michael@0 641 pc = p->fChildren[kLeft_Child] == x ? kLeft_Child : kRight_Child;
michael@0 642
michael@0 643 if (NULL == x->fChildren[c]) {
michael@0 644 if (fLast == x) {
michael@0 645 fLast = p;
michael@0 646 SkASSERT(p == PredecessorNode(x));
michael@0 647 } else if (fFirst == x) {
michael@0 648 fFirst = p;
michael@0 649 SkASSERT(p == SuccessorNode(x));
michael@0 650 }
michael@0 651 // x has two implicit black children.
michael@0 652 Color xcolor = x->fColor;
michael@0 653 p->fChildren[pc] = NULL;
michael@0 654 delete x;
michael@0 655 x = NULL;
michael@0 656 // when x is red it can be with an implicit black leaf without
michael@0 657 // violating any of the red-black tree properties.
michael@0 658 if (kRed_Color == xcolor) {
michael@0 659 validate();
michael@0 660 return;
michael@0 661 }
michael@0 662 // s is p's other child (x's sibling)
michael@0 663 Node* s = p->fChildren[1-pc];
michael@0 664
michael@0 665 //s cannot be an implicit black node because the original
michael@0 666 // black-height at x was >= 2 and s's black-height must equal the
michael@0 667 // initial black height of x.
michael@0 668 SkASSERT(NULL != s);
michael@0 669 SkASSERT(p == s->fParent);
michael@0 670
michael@0 671 // assigned in loop
michael@0 672 Node* sl;
michael@0 673 Node* sr;
michael@0 674 bool slRed;
michael@0 675 bool srRed;
michael@0 676
michael@0 677 do {
michael@0 678 // When we start this loop x may already be deleted it is/was
michael@0 679 // p's child on its pc side. x's children are/were black. The
michael@0 680 // first time through the loop they are implict children.
michael@0 681 // On later passes we will be walking up the tree and they will
michael@0 682 // be real nodes.
michael@0 683 // The x side of p has a black-height that is one less than the
michael@0 684 // s side. It must be rebalanced.
michael@0 685 SkASSERT(NULL != s);
michael@0 686 SkASSERT(p == s->fParent);
michael@0 687 SkASSERT(NULL == x || x->fParent == p);
michael@0 688
michael@0 689 //sl and sr are s's children, which may be implicit.
michael@0 690 sl = s->fChildren[kLeft_Child];
michael@0 691 sr = s->fChildren[kRight_Child];
michael@0 692
michael@0 693 // if the s is red we will rotate s and p, swap their colors so
michael@0 694 // that x's new sibling is black
michael@0 695 if (kRed_Color == s->fColor) {
michael@0 696 // if s is red then it's parent must be black.
michael@0 697 SkASSERT(kBlack_Color == p->fColor);
michael@0 698 // s's children must also be black since s is red. They can't
michael@0 699 // be implicit since s is red and it's black-height is >= 2.
michael@0 700 SkASSERT(NULL != sl && kBlack_Color == sl->fColor);
michael@0 701 SkASSERT(NULL != sr && kBlack_Color == sr->fColor);
michael@0 702 p->fColor = kRed_Color;
michael@0 703 s->fColor = kBlack_Color;
michael@0 704 if (kLeft_Child == pc) {
michael@0 705 rotateLeft(p);
michael@0 706 s = sl;
michael@0 707 } else {
michael@0 708 rotateRight(p);
michael@0 709 s = sr;
michael@0 710 }
michael@0 711 sl = s->fChildren[kLeft_Child];
michael@0 712 sr = s->fChildren[kRight_Child];
michael@0 713 }
michael@0 714 // x and s are now both black.
michael@0 715 SkASSERT(kBlack_Color == s->fColor);
michael@0 716 SkASSERT(NULL == x || kBlack_Color == x->fColor);
michael@0 717 SkASSERT(p == s->fParent);
michael@0 718 SkASSERT(NULL == x || p == x->fParent);
michael@0 719
michael@0 720 // when x is deleted its subtree will have reduced black-height.
michael@0 721 slRed = (NULL != sl && kRed_Color == sl->fColor);
michael@0 722 srRed = (NULL != sr && kRed_Color == sr->fColor);
michael@0 723 if (!slRed && !srRed) {
michael@0 724 // if s can be made red that will balance out x's removal
michael@0 725 // to make both subtrees of p have the same black-height.
michael@0 726 if (kBlack_Color == p->fColor) {
michael@0 727 s->fColor = kRed_Color;
michael@0 728 // now subtree at p has black-height of one less than
michael@0 729 // p's parent's other child's subtree. We move x up to
michael@0 730 // p and go through the loop again. At the top of loop
michael@0 731 // we assumed x and x's children are black, which holds
michael@0 732 // by above ifs.
michael@0 733 // if p is the root there is no other subtree to balance
michael@0 734 // against.
michael@0 735 x = p;
michael@0 736 p = x->fParent;
michael@0 737 if (NULL == p) {
michael@0 738 SkASSERT(fRoot == x);
michael@0 739 validate();
michael@0 740 return;
michael@0 741 } else {
michael@0 742 pc = p->fChildren[kLeft_Child] == x ? kLeft_Child :
michael@0 743 kRight_Child;
michael@0 744
michael@0 745 }
michael@0 746 s = p->fChildren[1-pc];
michael@0 747 SkASSERT(NULL != s);
michael@0 748 SkASSERT(p == s->fParent);
michael@0 749 continue;
michael@0 750 } else if (kRed_Color == p->fColor) {
michael@0 751 // we can make p black and s red. This balance out p's
michael@0 752 // two subtrees and keep the same black-height as it was
michael@0 753 // before the delete.
michael@0 754 s->fColor = kRed_Color;
michael@0 755 p->fColor = kBlack_Color;
michael@0 756 validate();
michael@0 757 return;
michael@0 758 }
michael@0 759 }
michael@0 760 break;
michael@0 761 } while (true);
michael@0 762 // if we made it here one or both of sl and sr is red.
michael@0 763 // s and x are black. We make sure that a red child is on
michael@0 764 // the same side of s as s is of p.
michael@0 765 SkASSERT(slRed || srRed);
michael@0 766 if (kLeft_Child == pc && !srRed) {
michael@0 767 s->fColor = kRed_Color;
michael@0 768 sl->fColor = kBlack_Color;
michael@0 769 rotateRight(s);
michael@0 770 sr = s;
michael@0 771 s = sl;
michael@0 772 //sl = s->fChildren[kLeft_Child]; don't need this
michael@0 773 } else if (kRight_Child == pc && !slRed) {
michael@0 774 s->fColor = kRed_Color;
michael@0 775 sr->fColor = kBlack_Color;
michael@0 776 rotateLeft(s);
michael@0 777 sl = s;
michael@0 778 s = sr;
michael@0 779 //sr = s->fChildren[kRight_Child]; don't need this
michael@0 780 }
michael@0 781 // now p is either red or black, x and s are red and s's 1-pc
michael@0 782 // child is red.
michael@0 783 // We rotate p towards x, pulling s up to replace p. We make
michael@0 784 // p be black and s takes p's old color.
michael@0 785 // Whether p was red or black, we've increased its pc subtree
michael@0 786 // rooted at x by 1 (balancing the imbalance at the start) and
michael@0 787 // we've also its subtree rooted at s's black-height by 1. This
michael@0 788 // can be balanced by making s's red child be black.
michael@0 789 s->fColor = p->fColor;
michael@0 790 p->fColor = kBlack_Color;
michael@0 791 if (kLeft_Child == pc) {
michael@0 792 SkASSERT(NULL != sr && kRed_Color == sr->fColor);
michael@0 793 sr->fColor = kBlack_Color;
michael@0 794 rotateLeft(p);
michael@0 795 } else {
michael@0 796 SkASSERT(NULL != sl && kRed_Color == sl->fColor);
michael@0 797 sl->fColor = kBlack_Color;
michael@0 798 rotateRight(p);
michael@0 799 }
michael@0 800 }
michael@0 801 else {
michael@0 802 // x has exactly one implicit black child. x cannot be red.
michael@0 803 // Proof by contradiction: Assume X is red. Let c0 be x's implicit
michael@0 804 // child and c1 be its non-implicit child. c1 must be black because
michael@0 805 // red nodes always have two black children. Then the two subtrees
michael@0 806 // of x rooted at c0 and c1 will have different black-heights.
michael@0 807 SkASSERT(kBlack_Color == x->fColor);
michael@0 808 // So we know x is black and has one implicit black child, c0. c1
michael@0 809 // must be red, otherwise the subtree at c1 will have a different
michael@0 810 // black-height than the subtree rooted at c0.
michael@0 811 SkASSERT(kRed_Color == x->fChildren[c]->fColor);
michael@0 812 // replace x with c1, making c1 black, preserves all red-black tree
michael@0 813 // props.
michael@0 814 Node* c1 = x->fChildren[c];
michael@0 815 if (x == fFirst) {
michael@0 816 SkASSERT(c == kRight_Child);
michael@0 817 fFirst = c1;
michael@0 818 while (NULL != fFirst->fChildren[kLeft_Child]) {
michael@0 819 fFirst = fFirst->fChildren[kLeft_Child];
michael@0 820 }
michael@0 821 SkASSERT(fFirst == SuccessorNode(x));
michael@0 822 } else if (x == fLast) {
michael@0 823 SkASSERT(c == kLeft_Child);
michael@0 824 fLast = c1;
michael@0 825 while (NULL != fLast->fChildren[kRight_Child]) {
michael@0 826 fLast = fLast->fChildren[kRight_Child];
michael@0 827 }
michael@0 828 SkASSERT(fLast == PredecessorNode(x));
michael@0 829 }
michael@0 830 c1->fParent = p;
michael@0 831 p->fChildren[pc] = c1;
michael@0 832 c1->fColor = kBlack_Color;
michael@0 833 delete x;
michael@0 834 validate();
michael@0 835 }
michael@0 836 validate();
michael@0 837 }
michael@0 838
michael@0 839 template <typename T, typename C>
michael@0 840 void GrRedBlackTree<T,C>::RecursiveDelete(Node* x) {
michael@0 841 if (NULL != x) {
michael@0 842 RecursiveDelete(x->fChildren[kLeft_Child]);
michael@0 843 RecursiveDelete(x->fChildren[kRight_Child]);
michael@0 844 delete x;
michael@0 845 }
michael@0 846 }
michael@0 847
michael@0 848 #ifdef SK_DEBUG
michael@0 849 template <typename T, typename C>
michael@0 850 void GrRedBlackTree<T,C>::validate() const {
michael@0 851 if (fCount) {
michael@0 852 SkASSERT(NULL == fRoot->fParent);
michael@0 853 SkASSERT(NULL != fFirst);
michael@0 854 SkASSERT(NULL != fLast);
michael@0 855
michael@0 856 SkASSERT(kBlack_Color == fRoot->fColor);
michael@0 857 if (1 == fCount) {
michael@0 858 SkASSERT(fFirst == fRoot);
michael@0 859 SkASSERT(fLast == fRoot);
michael@0 860 SkASSERT(0 == fRoot->fChildren[kLeft_Child]);
michael@0 861 SkASSERT(0 == fRoot->fChildren[kRight_Child]);
michael@0 862 }
michael@0 863 } else {
michael@0 864 SkASSERT(NULL == fRoot);
michael@0 865 SkASSERT(NULL == fFirst);
michael@0 866 SkASSERT(NULL == fLast);
michael@0 867 }
michael@0 868 #if DEEP_VALIDATE
michael@0 869 int bh;
michael@0 870 int count = checkNode(fRoot, &bh);
michael@0 871 SkASSERT(count == fCount);
michael@0 872 #endif
michael@0 873 }
michael@0 874
michael@0 875 template <typename T, typename C>
michael@0 876 int GrRedBlackTree<T,C>::checkNode(Node* n, int* bh) const {
michael@0 877 if (NULL != n) {
michael@0 878 SkASSERT(validateChildRelations(n, false));
michael@0 879 if (kBlack_Color == n->fColor) {
michael@0 880 *bh += 1;
michael@0 881 }
michael@0 882 SkASSERT(!fComp(n->fItem, fFirst->fItem));
michael@0 883 SkASSERT(!fComp(fLast->fItem, n->fItem));
michael@0 884 int leftBh = *bh;
michael@0 885 int rightBh = *bh;
michael@0 886 int cl = checkNode(n->fChildren[kLeft_Child], &leftBh);
michael@0 887 int cr = checkNode(n->fChildren[kRight_Child], &rightBh);
michael@0 888 SkASSERT(leftBh == rightBh);
michael@0 889 *bh = leftBh;
michael@0 890 return 1 + cl + cr;
michael@0 891 }
michael@0 892 return 0;
michael@0 893 }
michael@0 894
michael@0 895 template <typename T, typename C>
michael@0 896 bool GrRedBlackTree<T,C>::validateChildRelations(const Node* n,
michael@0 897 bool allowRedRed) const {
michael@0 898 if (NULL != n) {
michael@0 899 if (NULL != n->fChildren[kLeft_Child] ||
michael@0 900 NULL != n->fChildren[kRight_Child]) {
michael@0 901 if (n->fChildren[kLeft_Child] == n->fChildren[kRight_Child]) {
michael@0 902 return validateChildRelationsFailed();
michael@0 903 }
michael@0 904 if (n->fChildren[kLeft_Child] == n->fParent &&
michael@0 905 NULL != n->fParent) {
michael@0 906 return validateChildRelationsFailed();
michael@0 907 }
michael@0 908 if (n->fChildren[kRight_Child] == n->fParent &&
michael@0 909 NULL != n->fParent) {
michael@0 910 return validateChildRelationsFailed();
michael@0 911 }
michael@0 912 if (NULL != n->fChildren[kLeft_Child]) {
michael@0 913 if (!allowRedRed &&
michael@0 914 kRed_Color == n->fChildren[kLeft_Child]->fColor &&
michael@0 915 kRed_Color == n->fColor) {
michael@0 916 return validateChildRelationsFailed();
michael@0 917 }
michael@0 918 if (n->fChildren[kLeft_Child]->fParent != n) {
michael@0 919 return validateChildRelationsFailed();
michael@0 920 }
michael@0 921 if (!(fComp(n->fChildren[kLeft_Child]->fItem, n->fItem) ||
michael@0 922 (!fComp(n->fChildren[kLeft_Child]->fItem, n->fItem) &&
michael@0 923 !fComp(n->fItem, n->fChildren[kLeft_Child]->fItem)))) {
michael@0 924 return validateChildRelationsFailed();
michael@0 925 }
michael@0 926 }
michael@0 927 if (NULL != n->fChildren[kRight_Child]) {
michael@0 928 if (!allowRedRed &&
michael@0 929 kRed_Color == n->fChildren[kRight_Child]->fColor &&
michael@0 930 kRed_Color == n->fColor) {
michael@0 931 return validateChildRelationsFailed();
michael@0 932 }
michael@0 933 if (n->fChildren[kRight_Child]->fParent != n) {
michael@0 934 return validateChildRelationsFailed();
michael@0 935 }
michael@0 936 if (!(fComp(n->fItem, n->fChildren[kRight_Child]->fItem) ||
michael@0 937 (!fComp(n->fChildren[kRight_Child]->fItem, n->fItem) &&
michael@0 938 !fComp(n->fItem, n->fChildren[kRight_Child]->fItem)))) {
michael@0 939 return validateChildRelationsFailed();
michael@0 940 }
michael@0 941 }
michael@0 942 }
michael@0 943 }
michael@0 944 return true;
michael@0 945 }
michael@0 946 #endif
michael@0 947
michael@0 948 #endif

mercurial