CppCommon  1.0.4.1
C++ Common Library
bintree_rb.inl
Go to the documentation of this file.
1 
9 namespace CppCommon {
10 
11 template <typename T, typename TCompare>
12 template <class InputIterator>
13 inline BinTreeRB<T, TCompare>::BinTreeRB(InputIterator first, InputIterator last, const TCompare& compare) noexcept
14  : _compare(compare)
15 {
16  for (auto it = first; it != last; ++it)
17  insert(*it);
18 }
19 
20 template <typename T, typename TCompare>
21 inline T* BinTreeRB<T, TCompare>::lowest() noexcept
22 {
23  return (T*)InternalLowest();
24 }
25 
26 template <typename T, typename TCompare>
27 inline const T* BinTreeRB<T, TCompare>::lowest() const noexcept
28 {
29  return InternalLowest();
30 }
31 
32 template <typename T, typename TCompare>
33 inline const T* BinTreeRB<T, TCompare>::InternalLowest() const noexcept
34 {
35  const T* result = _root;
36  if (result != nullptr)
37  while (result->left != nullptr)
38  result = result->left;
39  return result;
40 }
41 
42 template <typename T, typename TCompare>
43 inline T* BinTreeRB<T, TCompare>::highest() noexcept
44 {
45  return (T*)InternalHighest();
46 }
47 
48 template <typename T, typename TCompare>
49 inline const T* BinTreeRB<T, TCompare>::highest() const noexcept
50 {
51  return InternalHighest();
52 }
53 
54 template <typename T, typename TCompare>
55 inline const T* BinTreeRB<T, TCompare>::InternalHighest() const noexcept
56 {
57  const T* result = _root;
58  if (result != nullptr)
59  while (result->right != nullptr)
60  result = result->right;
61  return result;
62 }
63 
64 template <typename T, typename TCompare>
66 {
67  return iterator(this, lowest());
68 }
69 
70 template <typename T, typename TCompare>
72 {
73  return const_iterator(this, lowest());
74 }
75 
76 template <typename T, typename TCompare>
78 {
79  return const_iterator(this, lowest());
80 }
81 
82 template <typename T, typename TCompare>
84 {
85  return iterator(this, nullptr);
86 }
87 
88 template <typename T, typename TCompare>
90 {
91  return const_iterator(this, nullptr);
92 }
93 
94 template <typename T, typename TCompare>
96 {
97  return const_iterator(this, nullptr);
98 }
99 
100 template <typename T, typename TCompare>
102 {
103  return reverse_iterator(this, highest());
104 }
105 
106 template <typename T, typename TCompare>
108 {
109  return const_reverse_iterator(this, highest());
110 }
111 
112 template <typename T, typename TCompare>
114 {
115  return const_reverse_iterator(this, highest());
116 }
117 
118 template <typename T, typename TCompare>
120 {
121  return reverse_iterator(this, nullptr);
122 }
123 
124 template <typename T, typename TCompare>
126 {
127  return const_reverse_iterator(this, nullptr);
128 }
129 
130 template <typename T, typename TCompare>
132 {
133  return const_reverse_iterator(this, nullptr);
134 }
135 
136 template <typename T, typename TCompare>
137 inline typename BinTreeRB<T, TCompare>::iterator BinTreeRB<T, TCompare>::find(const T& item) noexcept
138 {
139  return iterator(this, (T*)InternalFind(item));
140 }
141 
142 template <typename T, typename TCompare>
143 inline typename BinTreeRB<T, TCompare>::const_iterator BinTreeRB<T, TCompare>::find(const T& item) const noexcept
144 {
145  return const_iterator(this, InternalFind(item));
146 }
147 
148 template <typename T, typename TCompare>
149 inline const T* BinTreeRB<T, TCompare>::InternalFind(const T& item) const noexcept
150 {
151  // Perform the binary tree search from the root node
152  const T* current = _root;
153 
154  while (current != nullptr)
155  {
156  // Move to the left subtree
157  if (compare(item, *current))
158  {
159  current = current->left;
160  continue;
161  }
162 
163  // Move to the right subtree
164  if (compare(*current, item))
165  {
166  current = current->right;
167  continue;
168  }
169 
170  // Found result node
171  return current;
172  }
173 
174  // Nothing was found...
175  return nullptr;
176 }
177 
178 template <typename T, typename TCompare>
180 {
181  return iterator(this, (T*)InternalLowerBound(item));
182 }
183 
184 template <typename T, typename TCompare>
186 {
187  return const_iterator(this, InternalLowerBound(item));
188 }
189 
190 template <typename T, typename TCompare>
191 inline const T* BinTreeRB<T, TCompare>::InternalLowerBound(const T& item) const noexcept
192 {
193  // Perform the binary tree search from the root node
194  const T* current = _root;
195  const T* previous = nullptr;
196 
197  while (current != nullptr)
198  {
199  // Move to the left subtree
200  if (compare(item, *current))
201  {
202  previous = current;
203  current = current->left;
204  continue;
205  }
206 
207  // Move to the right subtree
208  if (compare(*current, item))
209  {
210  current = current->right;
211  continue;
212  }
213 
214  // Found result node
215  return current;
216  }
217 
218  // Return the previous lower bound node if any met
219  return previous;
220 }
221 
222 template <typename T, typename TCompare>
224 {
225  return iterator(this, (T*)InternalUpperBound(item));
226 }
227 
228 template <typename T, typename TCompare>
230 {
231  return const_iterator(this, InternalUpperBound(item));
232 }
233 
234 template <typename T, typename TCompare>
235 inline const T* BinTreeRB<T, TCompare>::InternalUpperBound(const T& item) const noexcept
236 {
237  // Perform the binary tree search from the root node
238  const T* current = _root;
239  const T* previous = nullptr;
240 
241  while (current != nullptr)
242  {
243  // Move to the left subtree
244  if (compare(item, *current))
245  {
246  previous = current;
247  current = current->left;
248  continue;
249  }
250 
251  // Move to the right subtree
252  current = current->right;
253  }
254 
255  // Return the previous upper bound node if any met
256  return previous;
257 }
258 
259 template <typename T, typename TCompare>
260 inline std::pair<typename BinTreeRB<T, TCompare>::iterator, bool> BinTreeRB<T, TCompare>::insert(T& item) noexcept
261 {
262  return insert(const_iterator(this, _root), item);
263 }
264 
265 template <typename T, typename TCompare>
266 inline std::pair<typename BinTreeRB<T, TCompare>::iterator, bool> BinTreeRB<T, TCompare>::insert(const const_iterator& position, T& item) noexcept
267 {
268  // Perform the binary tree insert from the given node
269  T* current = (T*)position.operator->();
270 
271  while (current != nullptr)
272  {
273  // Move to the left subtree
274  if (compare(item, *current))
275  {
276  if (current->left != nullptr)
277  {
278  current = current->left;
279  continue;
280  }
281  else
282  {
283  // Link a new item to the left leaf
284  current->left = &item;
285  break;
286  }
287  }
288 
289  // Move to the right subtree
290  if (compare(*current, item))
291  {
292  if (current->right != nullptr)
293  {
294  current = current->right;
295  continue;
296  }
297  else
298  {
299  // Link a new item to the right leaf
300  current->right = &item;
301  break;
302  }
303  }
304 
305  // Found duplicate node
306  return std::make_pair(iterator(this, current), false);
307  }
308 
309  item.parent = current;
310  item.left = nullptr;
311  item.right = nullptr;
312  if (_root == nullptr)
313  _root = &item;
314  ++_size;
315 
316  // Balance the binary tree
317  T* node = &item;
318  // Set red color for new red-black balanced binary tree node
319  node->rb = true;
320  // Check red-black properties
321  while ((node->parent != nullptr) && node->parent->rb)
322  {
323  // We have a violation...
324  if (node->parent == node->parent->parent->left)
325  {
326  T* uncle = node->parent->parent->right;
327  if ((uncle != nullptr) && uncle->rb)
328  {
329  // Uncle is red
330  node->parent->rb = false;
331  uncle->rb = false;
332  node->parent->parent->rb = true;
333  node = node->parent->parent;
334  }
335  else
336  {
337  // Uncle is back
338  if (node == node->parent->right)
339  {
340  // Make node a left child
341  node = node->parent;
342  RotateLeft(node);
343  }
344 
345  // Recolor and rotate
346  node->parent->rb = false;
347  node->parent->parent->rb = true;
348  RotateRight(node->parent->parent);
349  }
350  }
351  else
352  {
353  // Mirror image of above code...
354  T* uncle = node->parent->parent->left;
355  if ((uncle != nullptr) && uncle->rb)
356  {
357  // Uncle is red
358  node->parent->rb = false;
359  uncle->rb = false;
360  node->parent->parent->rb = true;
361  node = node->parent->parent;
362  }
363  else
364  {
365  // Uncle is black
366  if (node == node->parent->left)
367  {
368  node = node->parent;
369  RotateRight(node);
370  }
371 
372  // Recolor and rotate
373  node->parent->rb = false;
374  node->parent->parent->rb = true;
375  RotateLeft(node->parent->parent);
376  }
377  }
378  }
379  _root->rb = false;
380 
381  return std::make_pair(iterator(this, &item), true);
382 }
383 
384 template <typename T, typename TCompare>
385 inline T* BinTreeRB<T, TCompare>::erase(const T& item) noexcept
386 {
387  return erase(find(item)).operator->();
388 }
389 
390 template <typename T, typename TCompare>
392 {
393  T* result = ((iterator&)it).operator->();
394  if (result == nullptr)
395  return end();
396 
397  T* x;
398  T* y;
399  T* node = result;
400 
401  if ((node->left == nullptr) || (node->right == nullptr))
402  {
403  // y has a nullptr node as a child
404  y = node;
405  }
406  else
407  {
408  // Find tree successor with a nullptr node as a child
409  y = node->right;
410  while (y->left != nullptr)
411  y = y->left;
412  }
413 
414  // Swap two nodes
415  if (y != node)
416  {
417  if (node->parent == nullptr)
418  _root = y;
419  Swap(node, y);
420  }
421 
422  // x is y's only child
423  if (y->left != nullptr)
424  x = y->left;
425  else
426  x = y->right;
427 
428  // Remove y from the parent chain
429  if (x != nullptr)
430  x->parent = y->parent;
431  if (y->parent != nullptr)
432  {
433  if (y == y->parent->left)
434  y->parent->left = x;
435  else
436  y->parent->right = x;
437  }
438  else
439  _root = x;
440 
441  // Unlink given node
442  if (!y->rb)
443  Unlink(x, y->parent);
444 
445  result->parent = nullptr;
446  result->left = nullptr;
447  result->right = nullptr;
448  --_size;
449  return iterator(this, result);
450 }
451 
452 template <typename T, typename TCompare>
453 inline void BinTreeRB<T, TCompare>::RotateLeft(T* node)
454 {
455  T* current = node->right;
456 
457  // Establish node->right link
458  node->right = current->left;
459  if (current->left != nullptr)
460  current->left->parent = node;
461 
462  // Establish current->parent link
463  current->parent = node->parent;
464  if (node->parent != nullptr)
465  {
466  if (node == node->parent->left)
467  node->parent->left = current;
468  else
469  node->parent->right = current;
470  }
471  else
472  _root = current;
473 
474  // Link node and current
475  current->left = node;
476  node->parent = current;
477 }
478 
479 template <typename T, typename TCompare>
480 inline void BinTreeRB<T, TCompare>::RotateRight(T* node)
481 {
482  T* current = node->left;
483 
484  // Establish node->right link
485  node->left = current->right;
486  if (current->right != nullptr)
487  current->right->parent = node;
488 
489  // Establish current->parent link
490  current->parent = node->parent;
491  if (node->parent != nullptr)
492  {
493  if (node == node->parent->right)
494  node->parent->right = current;
495  else
496  node->parent->left = current;
497  }
498  else
499  _root = current;
500 
501  // Link node and current
502  current->right = node;
503  node->parent = current;
504 }
505 
506 template <typename T, typename TCompare>
507 inline void BinTreeRB<T, TCompare>::Unlink(T* node, T* parent)
508 {
509  T* w;
510 
511  while ((parent != nullptr) && ((node == nullptr) || !node->rb))
512  {
513  if (node == parent->left)
514  {
515  w = parent->right;
516  if ((w != nullptr) && w->rb)
517  {
518  w->rb = false;
519  parent->rb = true;
520  RotateLeft(parent);
521  w = parent->right;
522  }
523  if (w == nullptr)
524  break;
525  if (((w->left == nullptr) || !w->left->rb) && ((w->right == nullptr) || !w->right->rb))
526  {
527  w->rb = true;
528  node = parent;
529  parent = parent->parent;
530  }
531  else
532  {
533  if ((w->right == nullptr) || !w->right->rb)
534  {
535  w->left->rb = false;
536  w->rb = true;
537  RotateRight(w);
538  w = parent->right;
539  }
540 
541  // Copy red-black color information
542  if (parent->rb)
543  w->rb = true;
544  else
545  w->rb = false;
546  parent->rb = false;
547  w->right->rb = false;
548  RotateLeft(parent);
549  node = _root;
550  parent = nullptr;
551  }
552  }
553  else
554  {
555  w = parent->left;
556  if ((w != nullptr) && w->rb)
557  {
558  w->rb = false;
559  parent->rb = true;
560  RotateRight(parent);
561  w = parent->left;
562  }
563  if (w == nullptr)
564  break;
565  if (((w->left == nullptr) || !w->left->rb) && ((w->right == nullptr) || !w->right->rb))
566  {
567  w->rb = true;
568  node = parent;
569  parent = parent->parent;
570  }
571  else
572  {
573  if ((w->left == nullptr) || !w->left->rb)
574  {
575  w->right->rb = false;
576  w->rb = true;
577  RotateLeft(w);
578  w = parent->left;
579  }
580 
581  // Copy red-black color information
582  if (parent->rb)
583  w->rb = true;
584  else
585  w->rb = false;
586  parent->rb = false;
587  w->left->rb = false;
588  RotateRight(parent);
589  node = _root;
590  parent = nullptr;
591  }
592  }
593  }
594 
595  if (node != nullptr)
596  node->rb = false;
597 }
598 
599 template <typename T, typename TCompare>
600 inline void BinTreeRB<T, TCompare>::Swap(T*& node1, T*& node2)
601 {
602  T* first_parent = node1->parent;
603  T* first_left = node1->left;
604  T* first_right = node1->right;
605  T* second_parent = node2->parent;
606  T* second_left = node2->left;
607  T* second_right = node2->right;
608  bool first_is_left = ((first_parent != nullptr) && (first_parent->left == node1));
609  bool second_is_left = ((second_parent != nullptr) && (second_parent->left == node2));
610 
611  // Update first node links
612  if (first_parent != nullptr)
613  {
614  if (first_is_left)
615  first_parent->left = node2;
616  else
617  first_parent->right = node2;
618  }
619  if (first_left != nullptr)
620  first_left->parent = node2;
621  if (first_right != nullptr)
622  first_right->parent = node2;
623 
624  // Update second node links
625  if (second_parent != nullptr)
626  {
627  if (second_is_left)
628  second_parent->left = node1;
629  else
630  second_parent->right = node1;
631  }
632  if (second_left != nullptr)
633  second_left->parent = node1;
634  if (second_right != nullptr)
635  second_right->parent = node1;
636 
637  // Swap node links
638  std::swap(node1->parent, node2->parent);
639  std::swap(node1->left, node2->left);
640  std::swap(node1->right, node2->right);
641  std::swap(node1->balance, node2->balance);
642 
643  // Swap nodes
644  std::swap(node1, node2);
645 }
646 
647 template <typename T, typename TCompare>
648 inline void BinTreeRB<T, TCompare>::clear() noexcept
649 {
650  _size = 0;
651  _root = nullptr;
652 }
653 
654 template <typename T, typename TCompare>
655 inline void BinTreeRB<T, TCompare>::swap(BinTreeRB& bintree) noexcept
656 {
657  using std::swap;
658  swap(_compare, bintree._compare);
659  swap(_size, bintree._size);
660  swap(_root, bintree._root);
661 }
662 
663 template <typename T, typename TCompare>
664 inline void swap(BinTreeRB<T, TCompare>& bintree1, BinTreeRB<T, TCompare>& bintree2) noexcept
665 {
666  bintree1.swap(bintree2);
667 }
668 
669 } // namespace CppCommon
Intrusive binary tree constant iterator.
Definition: bintree.h:335
Intrusive binary tree constant reverse iterator.
Definition: bintree.h:448
Intrusive binary tree iterator.
Definition: bintree.h:279
Intrusive balanced Red-Black binary tree container.
Definition: bintree_rb.h:202
T * highest() noexcept
Get the highest binary tree item.
Definition: bintree_rb.inl:43
const_iterator cend() const noexcept
Definition: bintree_rb.inl:95
const_reverse_iterator crbegin() const noexcept
Definition: bintree_rb.inl:113
BinTreeRB(const TCompare &compare=TCompare()) noexcept
Definition: bintree_rb.h:229
iterator begin() noexcept
Get the begin binary tree iterator.
Definition: bintree_rb.inl:65
reverse_iterator rbegin() noexcept
Get the reverse begin binary tree iterator.
Definition: bintree_rb.inl:101
T * erase(const T &item) noexcept
Erase the given item from the binary tree.
Definition: bintree_rb.inl:385
void clear() noexcept
Clear the binary tree.
Definition: bintree_rb.inl:648
iterator upper_bound(const T &item) noexcept
Find the iterator which points to the first item that greater than the given item in the binary tree ...
Definition: bintree_rb.inl:223
reverse_iterator rend() noexcept
Get the reverse end binary tree iterator.
Definition: bintree_rb.inl:119
iterator end() noexcept
Get the end binary tree iterator.
Definition: bintree_rb.inl:83
T * lowest() noexcept
Get the lowest binary tree item.
Definition: bintree_rb.inl:21
void swap(BinTreeRB &bintree) noexcept
Swap two instances.
Definition: bintree_rb.inl:655
const_reverse_iterator crend() const noexcept
Definition: bintree_rb.inl:131
std::pair< iterator, bool > insert(T &item) noexcept
Insert a new item into the binary tree.
Definition: bintree_rb.inl:260
iterator lower_bound(const T &item) noexcept
Find the iterator which points to the first item that not less than the given item in the binary tree...
Definition: bintree_rb.inl:179
const_iterator cbegin() const noexcept
Definition: bintree_rb.inl:77
iterator find(const T &item) noexcept
Find the iterator which points to the first equal item in the binary tree or return end iterator.
Definition: bintree_rb.inl:137
Intrusive binary tree reverse iterator.
Definition: bintree.h:392
C++ Common project definitions.
Definition: token_bucket.h:15
void swap(BinTreeRB< T, TCompare > &bintree1, BinTreeRB< T, TCompare > &bintree2) noexcept
Definition: bintree_rb.inl:664
void swap(FileCache &cache1, FileCache &cache2) noexcept
Definition: filecache.inl:23