ScummVM API documentation
as_map.h
1 /*
2  AngelCode Scripting Library
3  Copyright (c) 2003-2013 Andreas Jonsson
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any
7  damages arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any
10  purpose, including commercial applications, and to alter it and
11  redistribute it freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you
14  must not claim that you wrote the original software. If you use
15  this software in a product, an acknowledgment in the product
16  documentation would be appreciated but is not required.
17 
18  2. Altered source versions must be plainly marked as such, and
19  must not be misrepresented as being the original software.
20 
21  3. This notice may not be removed or altered from any source
22  distribution.
23 
24  The original version of this library can be located at:
25  http://www.angelcode.com/angelscript/
26 
27  Andreas Jonsson
28  andreas@angelcode.com
29 */
30 
31 
32 //
33 // as_map.h
34 //
35 // This class is used for mapping a value to another
36 //
37 
38 
39 #ifndef AS_MAP_H
40 #define AS_MAP_H
41 
42 template <class KEY, class VAL> struct asSMapNode;
43 
44 template <class KEY, class VAL> class asCMap {
45 public:
46  asCMap();
47  ~asCMap();
48 
49  int Insert(const KEY &key, const VAL &value);
50  int Insert(asSMapNode<KEY, VAL> *node);
51  int GetCount() const;
52 
53  const KEY &GetKey(const asSMapNode<KEY, VAL> *cursor) const;
54  const VAL &GetValue(const asSMapNode<KEY, VAL> *cursor) const;
55  VAL &GetValue(asSMapNode<KEY, VAL> *cursor);
56 
57  void Erase(asSMapNode<KEY, VAL> *cursor);
59  void EraseAll();
60 
61  void SwapWith(asCMap<KEY, VAL> &other);
62 
63  // Returns true as long as cursor is valid
64 
65  bool MoveTo(asSMapNode<KEY, VAL> **out, const KEY &key) const;
66  bool MoveFirst(asSMapNode<KEY, VAL> **out) const;
67  bool MoveLast(asSMapNode<KEY, VAL> **out) const;
68  bool MoveNext(asSMapNode<KEY, VAL> **out, asSMapNode<KEY, VAL> *cursor) const;
69  bool MovePrev(asSMapNode<KEY, VAL> **out, asSMapNode<KEY, VAL> *cursor) const;
70 
71  // For debugging only
72 
73  int CheckIntegrity(asSMapNode<KEY, VAL> *node) const;
74 
75 protected:
76  // Don't allow value assignment
77  asCMap &operator=(const asCMap &) {
78  return *this;
79  }
80 
81  void BalanceInsert(asSMapNode<KEY, VAL> *node);
82  void BalanceErase(asSMapNode<KEY, VAL> *child, asSMapNode<KEY, VAL> *parent);
83 
84  int EraseAll(asSMapNode<KEY, VAL> *node);
85  int RotateLeft(asSMapNode<KEY, VAL> *node);
86  int RotateRight(asSMapNode<KEY, VAL> *node);
87 
90 
91  int count;
92 };
93 
94 //---------------------------------------------------------------------------
95 // Implementation
96 
97 // Properties of a Red-Black Tree
98 //
99 // 1. The root is always black
100 // 2. All single paths from the root to leafs
101 // contain the same amount of black nodes
102 // 3. No red node can have a red node as parent
103 
104 #define ISRED(x) ((x != 0) && (x)->isRed)
105 #define ISBLACK(x) (!ISRED(x))
106 
107 template <class KEY, class VAL> struct asSMapNode {
108  asSMapNode() {
109  parent = 0;
110  left = 0;
111  right = 0;
112  isRed = true;
113  }
114  void Init(KEY k, VAL v) {
115  key = k;
116  value = v;
117  parent = 0;
118  left = 0;
119  right = 0;
120  isRed = true;
121  }
122 
123  asSMapNode *parent;
124  asSMapNode *left;
125  asSMapNode *right;
126  bool isRed;
127 
128  KEY key;
129  VAL value;
130 };
131 
132 template <class KEY, class VAL>
134  root = 0;
135  count = 0;
136 }
137 
138 template <class KEY, class VAL>
140  EraseAll();
141 }
142 
143 template <class KEY, class VAL>
145  asSMapNode<KEY, VAL> *tmpRoot = root;
146  int tmpCount = count;
147 
148  root = other.root;
149  count = other.count;
150 
151  other.root = tmpRoot;
152  other.count = tmpCount;
153 }
154 
155 template <class KEY, class VAL>
157  EraseAll(root);
158  root = 0;
159 }
160 
161 template <class KEY, class VAL>
163  if (p == 0) return -1;
164 
165  EraseAll(p->left);
166  EraseAll(p->right);
167 
168  typedef asSMapNode<KEY, VAL> node_t;
169  asDELETE(p, node_t);
170 
171  count--;
172 
173  return 0;
174 }
175 
176 template <class KEY, class VAL>
177 int asCMap<KEY, VAL>::GetCount() const {
178  return count;
179 }
180 
181 template <class KEY, class VAL>
182 int asCMap<KEY, VAL>::Insert(const KEY &key, const VAL &value) {
183  typedef asSMapNode<KEY, VAL> node_t;
184  asSMapNode<KEY, VAL> *nnode = asNEW(node_t);
185  if (nnode == 0) {
186  // Out of memory
187  return -1;
188  }
189 
190  nnode->key = key;
191  nnode->value = value;
192 
193  return Insert(nnode);
194 }
195 
196 template <class KEY, class VAL>
198  // Insert the node
199  if (root == 0)
200  root = nnode;
201  else {
202  asSMapNode<KEY, VAL> *p = root;
203  for (;;) {
204  if (nnode->key < p->key) {
205  if (p->left == 0) {
206  nnode->parent = p;
207  p->left = nnode;
208  break;
209  } else
210  p = p->left;
211  } else {
212  if (p->right == 0) {
213  nnode->parent = p;
214  p->right = nnode;
215  break;
216  } else
217  p = p->right;
218  }
219  }
220  }
221 
222  BalanceInsert(nnode);
223 
224  count++;
225 
226  return 0;
227 }
228 
229 template <class KEY, class VAL>
231  // The node, that is red, can't have a red parent
232  while (node != root && node->parent->isRed) {
233  // Check color of uncle
234  if (node->parent == node->parent->parent->left) {
235  asSMapNode<KEY, VAL> *uncle = node->parent->parent->right;
236  if (ISRED(uncle)) {
237  // B
238  // R R
239  // N
240 
241  // Change color on parent, uncle, and grand parent
242  node->parent->isRed = false;
243  uncle->isRed = false;
244  node->parent->parent->isRed = true;
245 
246  // Continue balancing from grand parent
247  node = node->parent->parent;
248  } else {
249  // B
250  // R B
251  // N
252 
253  if (node == node->parent->right) {
254  // Make the node a left child
255  node = node->parent;
256  RotateLeft(node);
257  }
258 
259  // Change color on parent and grand parent
260  // Then rotate grand parent to the right
261  node->parent->isRed = false;
262  node->parent->parent->isRed = true;
263  RotateRight(node->parent->parent);
264  }
265  } else {
266  asSMapNode<KEY, VAL> *uncle = node->parent->parent->left;
267  if (ISRED(uncle)) {
268  // B
269  // R R
270  // N
271 
272  // Change color on parent, uncle, and grand parent
273  // Continue balancing from grand parent
274  node->parent->isRed = false;
275  uncle->isRed = false;
276  node = node->parent->parent;
277  node->isRed = true;
278  } else {
279  // B
280  // B R
281  // N
282 
283  if (node == node->parent->left) {
284  // Make the node a right child
285  node = node->parent;
286  RotateRight(node);
287  }
288 
289  // Change color on parent and grand parent
290  // Then rotate grand parent to the right
291  node->parent->isRed = false;
292  node->parent->parent->isRed = true;
293  RotateLeft(node->parent->parent);
294  }
295  }
296  }
297 
298  root->isRed = false;
299 }
300 
301 // For debugging purposes only
302 template <class KEY, class VAL>
304  if (node == 0) {
305  if (root == 0)
306  return 0;
307  else if (ISRED(root))
308  return -1;
309  else
310  node = root;
311  }
312 
313  int left = 0, right = 0;
314  if (node->left)
315  left = CheckIntegrity(node->left);
316  if (node->right)
317  right = CheckIntegrity(node->right);
318 
319  if (left != right || left == -1)
320  return -1;
321 
322  if (ISBLACK(node))
323  return left + 1;
324 
325  return left;
326 }
327 
328 // Returns true if successful
329 template <class KEY, class VAL>
330 bool asCMap<KEY, VAL>::MoveTo(asSMapNode<KEY, VAL> **out, const KEY &key) const {
331  asSMapNode<KEY, VAL> *p = root;
332  while (p) {
333  if (key < p->key)
334  p = p->left;
335  else if (key == p->key) {
336  if (out) *out = p;
337  return true;
338  } else
339  p = p->right;
340  }
341 
342  if (out) *out = 0;
343  return false;
344 }
345 
346 template <class KEY, class VAL>
348  asSMapNode<KEY, VAL> *node = Remove(cursor);
349  asASSERT(node == cursor);
350 
351  typedef asSMapNode<KEY, VAL> node_t;
352  asDELETE(node, node_t);
353 }
354 
355 template <class KEY, class VAL>
357  if (cursor == 0) return 0;
358 
359  asSMapNode<KEY, VAL> *node = cursor;
360 
361  //---------------------------------------------------
362  // Choose the node that will replace the erased one
363  asSMapNode<KEY, VAL> *remove;
364  if (node->left == 0 || node->right == 0)
365  remove = node;
366  else {
367  remove = node->right;
368  while (remove->left) remove = remove->left;
369  }
370 
371  //--------------------------------------------------
372  // Remove the node
373  asSMapNode<KEY, VAL> *child;
374  if (remove->left)
375  child = remove->left;
376  else
377  child = remove->right;
378 
379  if (child) child->parent = remove->parent;
380  if (remove->parent) {
381  if (remove == remove->parent->left)
382  remove->parent->left = child;
383  else
384  remove->parent->right = child;
385  } else
386  root = child;
387 
388  // If we remove a black node we must make sure the tree is balanced
389  if (ISBLACK(remove))
390  BalanceErase(child, remove->parent);
391 
392  //----------------------------------------
393  // Replace the erased node with the removed one
394  if (remove != node) {
395  if (node->parent) {
396  if (node->parent->left == node)
397  node->parent->left = remove;
398  else
399  node->parent->right = remove;
400  } else
401  root = remove;
402 
403  remove->isRed = node->isRed;
404  remove->parent = node->parent;
405 
406  remove->left = node->left;
407  if (remove->left) remove->left->parent = remove;
408  remove->right = node->right;
409  if (remove->right) remove->right->parent = remove;
410  }
411 
412  count--;
413 
414  return node;
415 }
416 
417 // Call method only if removed node was black
418 // child is the child of the removed node
419 template <class KEY, class VAL>
421  // If child is red
422  // Color child black
423  // Terminate
424 
425  // These tests assume brother is to the right.
426 
427  // 1. Brother is red
428  // Color parent red and brother black
429  // Rotate parent left
430  // Transforms to 2b
431  // 2a. Parent and brother is black, brother's children are black
432  // Color brother red
433  // Continue test with parent as child
434  // 2b. Parent is red, brother is black, brother's children are black
435  // Color parent black and brother red
436  // Terminate
437  // 3. Brother is black, and brother's left is red and brother's right is black
438  // Color brother red and brother's left black
439  // Rotate brother to right
440  // Transforms to 4.
441  // 4. Brother is black, brother's right is red
442  // Color brother's right black
443  // Color brother to color of parent
444  // Color parent black
445  // Rotate parent left
446  // Terminate
447 
448  while (child != root && ISBLACK(child)) {
449  if (child == parent->left) {
450  asSMapNode<KEY, VAL> *brother = parent->right;
451 
452  // Case 1
453  if (ISRED(brother)) {
454  brother->isRed = false;
455  parent->isRed = true;
456  RotateLeft(parent);
457  brother = parent->right;
458  }
459 
460  // Case 2
461  if (brother == 0) break;
462  if (ISBLACK(brother->left) && ISBLACK(brother->right)) {
463  // Case 2b
464  if (ISRED(parent)) {
465  parent->isRed = false;
466  brother->isRed = true;
467  break;
468  }
469 
470  brother->isRed = true;
471  child = parent;
472  parent = child->parent;
473  } else {
474  // Case 3
475  if (ISBLACK(brother->right)) {
476  brother->left->isRed = false;
477  brother->isRed = true;
478  RotateRight(brother);
479  brother = parent->right;
480  }
481 
482  // Case 4
483  brother->isRed = parent->isRed;
484  parent->isRed = false;
485  brother->right->isRed = false;
486  RotateLeft(parent);
487  break;
488  }
489  } else {
490  asSMapNode<KEY, VAL> *brother = parent->left;
491 
492  // Case 1
493  if (ISRED(brother)) {
494  brother->isRed = false;
495  parent->isRed = true;
496  RotateRight(parent);
497  brother = parent->left;
498  }
499 
500  // Case 2
501  if (brother == 0) break;
502  if (ISBLACK(brother->left) && ISBLACK(brother->right)) {
503  // Case 2b
504  if (ISRED(parent)) {
505  parent->isRed = false;
506  brother->isRed = true;
507  break;
508  }
509 
510  brother->isRed = true;
511  child = parent;
512  parent = child->parent;
513  } else {
514  // Case 3
515  if (ISBLACK(brother->left)) {
516  brother->right->isRed = false;
517  brother->isRed = true;
518  RotateLeft(brother);
519  brother = parent->left;
520  }
521 
522  // Case 4
523  brother->isRed = parent->isRed;
524  parent->isRed = false;
525  brother->left->isRed = false;
526  RotateRight(parent);
527  break;
528  }
529  }
530  }
531 
532  if (child)
533  child->isRed = false;
534 }
535 
536 template <class KEY, class VAL>
538  // P L //
539  // / \ / \ //
540  // L R => Ll P //
541  // / \ / \ //
542  // Ll Lr Lr R //
543 
544  if (node->left == 0) return -1;
545 
546  asSMapNode<KEY, VAL> *left = node->left;
547 
548  // Update parent
549  if (node->parent) {
550  asSMapNode<KEY, VAL> *parent = node->parent;
551  if (parent->left == node)
552  parent->left = left;
553  else
554  parent->right = left;
555 
556  left->parent = parent;
557  } else {
558  root = left;
559  left->parent = 0;
560  }
561 
562  // Move left's right child to node's left child
563  node->left = left->right;
564  if (node->left) node->left->parent = node;
565 
566  // Put node as left's right child
567  left->right = node;
568  node->parent = left;
569 
570  return 0;
571 }
572 
573 template <class KEY, class VAL>
575  // P R //
576  // / \ / \ //
577  // L R => P Rr //
578  // / \ / \ //
579  // Rl Rr L Rl //
580 
581  if (node->right == 0) return -1;
582 
583  asSMapNode<KEY, VAL> *right = node->right;
584 
585  // Update parent
586  if (node->parent) {
587  asSMapNode<KEY, VAL> *parent = node->parent;
588  if (parent->right == node)
589  parent->right = right;
590  else
591  parent->left = right;
592 
593  right->parent = parent;
594  } else {
595  root = right;
596  right->parent = 0;
597  }
598 
599  // Move right's left child to node's right child
600  node->right = right->left;
601  if (node->right) node->right->parent = node;
602 
603  // Put node as right's left child
604  right->left = node;
605  node->parent = right;
606 
607  return 0;
608 }
609 
610 template <class KEY, class VAL>
611 const VAL &asCMap<KEY, VAL>::GetValue(const asSMapNode<KEY, VAL> *cursor) const {
612  if (cursor == 0)
613  return dummy.value;
614 
615  return cursor->value;
616 }
617 
618 template <class KEY, class VAL>
620  if (cursor == 0)
621  return dummy.value;
622 
623  return cursor->value;
624 }
625 
626 template <class KEY, class VAL>
627 const KEY &asCMap<KEY, VAL>::GetKey(const asSMapNode<KEY, VAL> *cursor) const {
628  if (cursor == 0)
629  return dummy.key;
630 
631  return cursor->key;
632 }
633 
634 template <class KEY, class VAL>
636  *out = root;
637  if (root == 0) return false;
638 
639  while ((*out)->left)
640  *out = (*out)->left;
641 
642  return true;
643 }
644 
645 template <class KEY, class VAL>
647  *out = root;
648  if (root == 0) return false;
649 
650  while ((*out)->right)
651  *out = (*out)->right;
652 
653  return true;
654 }
655 
656 template <class KEY, class VAL>
658  if (cursor == 0) {
659  *out = 0;
660  return false;
661  }
662 
663  if (cursor->right == 0) {
664  // Move upwards until we find a parent node to the right
665  while (cursor->parent && cursor->parent->right == cursor)
666  cursor = cursor->parent;
667 
668  cursor = cursor->parent;
669  *out = cursor;
670  if (cursor == 0)
671  return false;
672 
673  return true;
674  }
675 
676  cursor = cursor->right;
677  while (cursor->left)
678  cursor = cursor->left;
679 
680  *out = cursor;
681  return true;
682 }
683 
684 template <class KEY, class VAL>
686  if (cursor == 0) {
687  *out = 0;
688  return false;
689  }
690 
691  if (cursor->left == 0) {
692  // Move upwards until we find a parent node to the left
693  while (cursor->parent && cursor->parent->left == cursor)
694  cursor = cursor->parent;
695 
696  cursor = cursor->parent;
697 
698  *out = cursor;
699  if (cursor == 0)
700  return false;
701 
702  return true;
703  }
704 
705  cursor = cursor->left;
706  while (cursor->right)
707  cursor = cursor->right;
708 
709  *out = cursor;
710  return true;
711 }
712 
713 
714 
715 
716 #endif
717 
Definition: as_map.h:44
Definition: as_map.h:42
It remove(It first, It last, const T &val)
Definition: algorithm.h:466