1 ////////////////////////////////////////////////////////////////////////////////
2 // $Id: tree.h,v 1.13 2006/11/18 03:12:35 dmouldin Exp $
4 // Visual Leak Detector - Red-black Tree Template
5 // Copyright (c) 2005-2006 Dan Moulding
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Lesser General Public License for more details.
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this library; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 // See COPYING.txt for the full terms of the GNU Lesser General Public License.
23 ////////////////////////////////////////////////////////////////////////////////
29 "This header should only be included by Visual Leak Detector when building it from source. \
30 Applications should never include this header."
33 #include "vldheap.h" // Provides internal new and delete operators.
35 #define TREE_DEFAULT_RESERVE 32 // By default, trees reserve enough space, in advance, for this many nodes.
37 ////////////////////////////////////////////////////////////////////////////////
39 // The Tree Template Class
41 // This data structure is the internal data structure behind the lightweight
42 // STL-like container classes. This is a red-black tree which provides for
43 // fast insert, find, and erase operations.
45 // The binary tree nodes are overlaid on top of larger chunks of allocated
46 // memory (called chunks) which are arranged in a simple linked list. This
47 // allows the tree to grow (add nodes) dynamically without incurring a heap
48 // hit each time a new node is added.
50 // The Tree class provides member functions which make it easily adaptable to
51 // an STL-like interface so that it can be used as the backend for STL-like
58 // This is a red-black tree.
64 // The node is the basic data structure which the tree is built from.
65 typedef struct node_s {
66 color_e color; // The node's color.
67 T key; // The node's value, by which nodes are sorted.
69 struct node_s *left; // For nodes in the tree, the node's left child.
70 struct node_s *next; // For nodes in the free list, the next node on the free list.
72 struct node_s *parent; // The node's parent.
73 struct node_s *right; // The node's right child.
76 // Reserve capacity for the tree is allocated in large chunks with room for
78 typedef struct chunk_s {
79 struct chunk_s *next; // Pointer to the next node in the chunk list.
80 node_t *nodes; // Pointer to an array (of variable size) where nodes are stored.
87 InitializeCriticalSection(&m_lock);
91 m_nil.parent = &m_nil;
93 m_reserve = TREE_DEFAULT_RESERVE;
99 // Copy constructor - The sole purpose of this constructor's existence is
100 // to ensure that trees are not being inadvertently copied.
101 Tree (const Tree& source)
103 assert(FALSE); // Do not make copies of trees!
112 // Free all the chunks in the chunk list.
113 EnterCriticalSection(&m_lock);
115 while (cur != NULL) {
118 delete [] temp->nodes;
121 LeaveCriticalSection(&m_lock);
122 DeleteCriticalSection(&m_lock);
125 // operator = - Assignment operator. For efficiency, we want to avoid ever
126 // making copies of Trees (only pointer passing or reference passing
127 // should be performed). The sole purpose of this assignment operator is
128 // to ensure that no copying is being done inadvertently.
130 Tree<T>& operator = (const Tree<T> &other)
132 // Don't make copies of Trees!
137 // begin - Obtains a pointer to the first node (the node with the smallest
138 // key value) in the tree.
142 // Returns a pointer to the first node in the tree.
144 typename Tree::node_t* begin () const
148 EnterCriticalSection(&m_lock);
149 if (m_root == &m_nil) {
150 LeaveCriticalSection(&m_lock);
155 while (cur->left != &m_nil) {
158 LeaveCriticalSection(&m_lock);
163 // erase - Erases the specified node from the tree. Note that this does
164 // not cause the key associated with the erased node to be freed. The
165 // caller is responsible for freeing any dynamically allocated memory
166 // associated with the key.
168 // - node (IN): Pointer to the node to erase from the tree.
174 VOID erase (typename Tree::node_t *node)
181 EnterCriticalSection(&m_lock);
183 if ((node->left == &m_nil) || (node->right == &m_nil)) {
184 // The node to be erased has less than two children. It can be directly
185 // removed from the tree.
189 // The node to be erased has two children. It can only be removed
190 // indirectly. The actual node will stay where it is, but it's contents
191 // will be replaced by it's in-order successor's contents. The successor
192 // node will then be erased. Find the successor.
193 erasure = node->right;
194 while (erasure->left != &m_nil) {
195 erasure = erasure->left;
199 // Select the child node which will replace the node to be erased.
200 if (erasure->left != &m_nil) {
201 child = erasure->left;
204 child = erasure->right;
207 // Replace the node to be erased with the selected child.
208 child->parent = erasure->parent;
209 if (child->parent == &m_nil) {
210 // The root of the tree is being erased. The child becomes root.
214 if (erasure == erasure->parent->left) {
215 erasure->parent->left = child;
218 erasure->parent->right = child;
222 if (erasure != node) {
223 // The node being erased from the tree is the successor of the actual
224 // node to be erased. Replace the contents of the node to be erased
225 // with the successor's contents.
226 node->key = erasure->key;
229 if (erasure->color == black) {
230 // The node being erased from the tree is black. Restructuring of the
231 // tree may be needed so that black-height is maintained.
233 while ((cur != m_root) && (cur->color == black)) {
234 if (cur == cur->parent->left) {
235 // Current node is a left child.
236 sibling = cur->parent->right;
237 if (sibling->color == red) {
238 // Sibling is red. Rotate sibling up and color it black.
239 sibling->color = black;
240 cur->parent->color = red;
241 _rotateleft(cur->parent);
242 sibling = cur->parent->right;
244 if ((sibling->left->color == black) && (sibling->right->color == black)) {
245 // Both of sibling's children are black. Color sibling red.
246 sibling->color = red;
250 // At least one of sibling's children is red.
251 if (sibling->right->color == black) {
252 sibling->left->color = black;
253 sibling->color = red;
254 _rotateright(sibling);
255 sibling = cur->parent->right;
257 sibling->color = cur->parent->color;
258 cur->parent->color = black;
259 sibling->right->color = black;
260 _rotateleft(cur->parent);
265 // Current node is a right child.
266 sibling = cur->parent->left;
267 if (sibling->color == red) {
268 // Sibling is red. Rotate sibling up and color it black.
269 sibling->color = black;
270 cur->parent->color = red;
271 _rotateright(cur->parent);
272 sibling = cur->parent->left;
274 if ((sibling->left->color == black) && (sibling->right->color == black)) {
275 // Both of sibling's children are black. Color sibling red.
276 sibling->color = red;
280 // At least one of sibling's children is red.
281 if (sibling->left->color == black) {
282 sibling->right->color = black;
283 sibling->color = red;
284 _rotateleft(sibling);
285 sibling = cur->parent->left;
287 sibling->color = cur->parent->color;
288 cur->parent->color = black;
289 sibling->left->color = black;
290 _rotateright(cur->parent);
298 // Put the erased node onto the free list.
299 erasure->next = m_freelist;
300 m_freelist = erasure;
302 LeaveCriticalSection(&m_lock);
305 // erase - Erases the specified key from the tree. Note that this does
306 // not cause the key associated with the erased node to be freed. The
307 // caller is responsible for freeing any dynamically allocated memory
308 // associated with the key.
310 // - key (IN): The key to erase from the tree. This value is treated as
311 // the key for sorting within the tree. It must therefore be of a type
312 // which supports the "<" operator.
318 VOID erase (const T &key)
322 // Find the node to erase.
323 EnterCriticalSection(&m_lock);
325 while (node != &m_nil) {
326 if (node->key < key) {
330 else if (key < node->key) {
337 LeaveCriticalSection(&m_lock);
341 LeaveCriticalSection(&m_lock);
343 // 'key' is not in the tree.
347 // find - Obtains a pointer to the node corresponding to the specified key.
349 // - key (IN): The value to search for in the tree. This value is treated
350 // as the key for sorting within the tree. It must therefore be of a
351 // type which supports the "<" operator.
355 // Returns a pointer to the node corresponding to the specified key. If
356 // the key is not in the tree, then "find" returns NULL.
358 typename Tree::node_t* find (const T &key) const
362 EnterCriticalSection(&m_lock);
364 while (cur != &m_nil) {
365 if (cur->key < key) {
369 else if (key < cur->key) {
375 LeaveCriticalSection(&m_lock);
379 LeaveCriticalSection(&m_lock);
381 // 'key' is not in the tree.
385 // insert - Inserts a new key into the tree.
387 // - key (IN): The key to insert into the tree. This value is treated as
388 // the key for sorting within the tree. It must therefore be of a type
389 // which supports the "<" operator.
393 // Returns a pointer to the node corresponding to the newly inserted
394 // key. If an attempt is made to insert a key which is already in the
395 // tree, then NULL is returned and the new key is not inserted.
397 typename Tree::node_t* insert (const T &key)
404 EnterCriticalSection(&m_lock);
406 // Find the location where the new node should be inserted..
409 while (cur != &m_nil) {
411 if (cur->key < key) {
415 else if (key < cur->key) {
420 // Keys in the tree must be unique.
421 LeaveCriticalSection(&m_lock);
426 // Obtain a new node from the free list.
427 if (m_freelist == NULL) {
428 // Allocate additional storage.
432 m_freelist = m_freelist->next;
434 // Initialize the new node and insert it.
438 node->parent = parent;
439 node->right = &m_nil;
440 if (parent == &m_nil) {
441 // The tree is empty. The new node becomes root.
445 if (parent->key < key) {
446 // New node is a right child.
447 parent->right = node;
450 // New node is a left child.
455 // Rebalance and/or adjust the tree, if necessary.
457 while (cur->parent->color == red) {
458 // Double-red violation. Rebalancing/adjustment needed.
459 if (cur->parent == cur->parent->parent->left) {
460 // Parent is the left child. Uncle is the right child.
461 uncle = cur->parent->parent->right;
462 if (uncle->color == red) {
463 // Uncle is red. Recolor.
464 cur->parent->parent->color = red;
465 cur->parent->color = black;
466 uncle->color = black;
467 cur = cur->parent->parent;
470 // Uncle is black. Restructure.
471 if (cur == cur->parent->right) {
475 cur->parent->color = black;
476 cur->parent->parent->color = red;
477 _rotateright(cur->parent->parent);
481 // Parent is the right child. Uncle is the left child.
482 uncle = cur->parent->parent->left;
483 if (uncle->color == red) {
484 // Uncle is red. Recolor.
485 cur->parent->parent->color = red;
486 cur->parent->color = black;
487 uncle->color = black;
488 cur = cur->parent->parent;
491 // Uncle is black. Restructure.
492 if (cur == cur->parent->left) {
496 cur->parent->color = black;
497 cur->parent->parent->color = red;
498 _rotateleft(cur->parent->parent);
503 // The root node is always colored black.
504 m_root->color = black;
506 LeaveCriticalSection(&m_lock);
511 // next - Obtains a pointer to the in-order successor of the specified
514 // - node (IN): Pointer to the node whose in-order successor to retrieve.
518 // Returns a pointer to the node's in-order successor. If the specified
519 // node corresponds to the largest value in the tree, then the specified
520 // node has no successor and "next" will return NULL.
522 typename Tree::node_t* next (typename Tree::node_t *node) const
530 EnterCriticalSection(&m_lock);
531 if (node->right != &m_nil) {
532 // 'node' has a right child. Successor is the far left node in
533 // the right subtree.
535 while (cur->left != &m_nil) {
538 LeaveCriticalSection(&m_lock);
541 else if (node->parent != &m_nil) {
542 // 'node' has no right child, but does have a parent.
543 if (node == node->parent->left) {
544 // 'node' is a left child; node's parent is successor.
545 LeaveCriticalSection(&m_lock);
549 // 'node' is a right child.
551 // Go up the tree until we find a parent to the right.
552 while (cur->parent != &m_nil) {
553 if (cur == cur->parent->right) {
558 LeaveCriticalSection(&m_lock);
563 // There is no parent greater than 'node'. 'node' is the
565 LeaveCriticalSection(&m_lock);
570 // 'node' is root and root is the maximum node.
571 LeaveCriticalSection(&m_lock);
576 // prev - Obtains a pointer to the in-order predecessor of the specified
579 // - node (IN): Pointer to the node whose in-order predecessor to retrieve.
583 // Returns a pointer to the node's in-order predecessor. If the specified
584 // node corresponds to the smallest value in the tree, then the specified
585 // node has no predecessor and "prev" will return NULL.
587 typename Tree::node_t* prev (typename Tree::node_t *node) const
595 EnterCriticalSection(&m_lock);
596 if (node->left != &m_nil) {
597 // 'node' has left child. Predecessor is the far right node in the
600 while (cur->right != &m_nil) {
603 LeaveCriticalSection(&m_lock);
606 else if (node->parent != & m_nil) {
607 // 'node' has no left child, but does have a parent.
608 if (node == node->parent->right) {
609 // 'node' is a right child; node's parent is predecessor.
610 LeaveCriticalSection(&m_lock);
614 // 'node is a left child.
616 // Go up the tree until we find a parent to the left.
617 while (cur->parent != &m_nil) {
618 if (cur == cur->parent->left) {
623 LeaveCriticalSection(&m_lock);
628 // There is no parent less than 'node'. 'node' is the minimum
630 LeaveCriticalSection(&m_lock);
635 // 'node' is root and root is the minimum node.
636 LeaveCriticalSection(&m_lock);
641 // reserve - Reserves storage for a number of nodes in advance and/or sets
642 // the number of nodes for which the tree will automatically reserve
643 // storage when the tree needs to "grow" to accomodate new values being
644 // inserted into the tree. If this function is not called to set the
645 // reserve size to a specific value, then a pre-determined default value
646 // will be used. If this function is called when the tree currently has
647 // no reserve storage, then in addition to setting the tree's reserve
648 // value, it will also cause the tree to immediately reserve the
649 // specified amount of storage.
651 // - count (IN): The number of individual nodes' worth of storage to
656 // Returns the previously defined reserve value.
658 UINT32 reserve (UINT32 count)
662 UINT32 oldreserve = m_reserve;
664 if (count != m_reserve) {
666 // Minimum reserve size is 1.
674 EnterCriticalSection(&m_lock);
675 if (m_freelist == NULL) {
676 // Allocate additional storage.
677 // Link a new chunk into the chunk list.
678 chunk = new Tree::chunk_t;
679 chunk->nodes = new Tree::node_s [m_reserve];
681 if (m_store == NULL) {
685 m_storetail->next = chunk;
689 // Link the individual nodes together to form a new free list.
690 for (index = 0; index < m_reserve - 1; index++) {
691 chunk->nodes[index].next = &chunk->nodes[index + 1];
693 chunk->nodes[index].next = NULL;
694 m_freelist = chunk->nodes;
696 LeaveCriticalSection(&m_lock);
702 // _rotateleft: Rotates a pair of nodes counter-clockwise so that the parent
703 // node becomes the left child and the right child becomes the parent.
705 // - parent (IN): Pointer to the parent to rotate about.
711 VOID _rotateleft (typename Tree::node_t *parent)
713 node_t *child = parent->right;
715 // Reassign the child's left subtree to the parent.
716 parent->right = child->left;
717 if (child->left != &m_nil) {
718 child->left->parent = parent;
721 // Reassign the child/parent relationship.
722 child->parent = parent->parent;
723 if (parent->parent == &m_nil) {
724 // The child becomes the new root node.
728 // Point the grandparent at the child.
729 if (parent == parent->parent->left) {
730 parent->parent->left = child;
733 parent->parent->right = child;
736 child->left = parent;
737 parent->parent = child;
740 // _rotateright - Rotates a pair of nodes clockwise so that the parent node
741 // becomes the right child and the left child becomes the parent.
743 // - parent (IN): Pointer to the parent to rotate about.
749 VOID _rotateright (typename Tree::node_t *parent)
751 node_t *child = parent->left;
753 // Reassign the child's right subtree to the parent.
754 parent->left = child->right;
755 if (child->right != &m_nil) {
756 child->right->parent = parent;
759 // Reassign the child/parent relationship.
760 child->parent = parent->parent;
761 if (parent->parent == &m_nil) {
762 // The child becomes the new root node.
766 // Point the grandparent at the child.
767 if (parent == parent->parent->left) {
768 parent->parent->left = child;
771 parent->parent->right = child;
774 child->right = parent;
775 parent->parent = child;
778 // Private data members.
779 node_t *m_freelist; // Pointer to the list of free nodes (reserve storage).
780 mutable CRITICAL_SECTION m_lock; // Protects the tree's integrity against concurrent accesses.
781 node_t m_nil; // The tree's nil node. All leaf nodes point to this.
782 UINT32 m_reserve; // The size (in nodes) of the chunks of reserve storage.
783 node_t *m_root; // Pointer to the tree's root node.
784 chunk_t *m_store; // Pointer to the start of the chunk list.
785 chunk_t *m_storetail; // Pointer to the end of the chunk list.