2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: Splay-Tree implementation
5 * FILE: lib/rtl/splaytree.c
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES *****************************************************************/
16 //#define VERIFY_SWAP_SPLAY_LINKS
18 /* FUNCTIONS ***************************************************************/
22 FixupChildLinks(PRTL_SPLAY_LINKS Links
, BOOLEAN Root
, BOOLEAN LeftChild
)
24 if (RtlLeftChild(Links
))
26 RtlInsertAsLeftChild(Links
, RtlLeftChild(Links
));
29 if (RtlRightChild(Links
))
31 RtlInsertAsRightChild(Links
, RtlRightChild(Links
));
38 RtlInsertAsLeftChild(RtlParent(Links
), Links
);
42 RtlInsertAsRightChild(RtlParent(Links
), Links
);
56 Q S Q.P Q.L Q.R S.P S.L S.R
57 A C S.P S.L S.R Q.P Q.L Q.R
58 B A S S.L S.R Q.P Q Q.R
59 B C S S.L S.R Q.P Q.L Q
60 D A S.P S.L S.R S Q.L Q.R
64 When Q is the immediate parent of S,
65 Set Q's parent to S, and the proper child ptr of S to Q
73 SwapSplayLinks(PRTL_SPLAY_LINKS LinkA
,
74 PRTL_SPLAY_LINKS LinkB
)
76 if (RtlParent(LinkA
) == LinkB
|| RtlIsRoot(LinkB
))
78 PRTL_SPLAY_LINKS Tmp
= LinkA
;
84 RTL_SPLAY_LINKS Ta
= *LinkA
, Tb
= *LinkB
;
85 BOOLEAN RootA
= RtlIsRoot(LinkA
),
86 LeftA
= RtlIsLeftChild(LinkA
),
87 LeftB
= RtlIsLeftChild(LinkB
);
89 *LinkB
= Ta
; *LinkA
= Tb
;
91 // A was parent of B is a special case: A->Parent is now B
92 if (RtlParent(&Tb
) == LinkA
)
98 RtlInsertAsLeftChild(RtlParent(&Ta
), LinkB
);
102 RtlInsertAsRightChild(RtlParent(&Ta
), LinkB
);
108 RtlInsertAsLeftChild(LinkB
, LinkA
);
112 RtlInsertAsRightChild(LinkB
, LinkA
);
116 FixupChildLinks(LinkA
, FALSE
, LeftB
);
117 FixupChildLinks(LinkB
, RootA
, LeftA
);
119 // A was root is a special case: B->Parent is now B
121 RtlParent(LinkB
) = LinkB
;
123 #ifdef VERIFY_SWAP_SPLAY_LINKS
124 // Verify the distinct cases of node swap
127 if (RtlParent(&Tb
) == LinkA
)
129 // LinkA = D, LinkB = B
130 // D B S S.L S.R S Q Q.R
131 ASSERT(RtlParent(LinkA
) == LinkB
);
132 ASSERT(RtlLeftChild(LinkA
) == RtlLeftChild(&Tb
));
133 ASSERT(RtlRightChild(LinkA
) == RtlRightChild(&Tb
));
134 ASSERT(RtlParent(LinkB
) == LinkB
);
135 ASSERT(RtlLeftChild(LinkB
) == (LeftB
? LinkA
: RtlLeftChild(&Ta
)));
136 ASSERT(RtlRightChild(LinkB
) == (LeftB
? RtlRightChild(&Ta
) : LinkA
));
140 // LinkA = D, LinkB = A
141 // D A S.P S.L S.R S Q.L Q.R
142 ASSERT(RtlParent(LinkA
) == RtlParent(&Tb
));
143 ASSERT(RtlLeftChild(LinkA
) == RtlLeftChild(&Tb
));
144 ASSERT(RtlRightChild(LinkA
) == RtlRightChild(&Tb
));
145 ASSERT(RtlParent(LinkB
) == LinkB
);
146 ASSERT(RtlLeftChild(LinkB
) == RtlLeftChild(&Ta
));
147 ASSERT(RtlRightChild(LinkB
) == RtlRightChild(&Ta
));
152 if (RtlParent(&Tb
) == LinkA
)
154 // LinkA = B, LinkB = A
155 // B A S S.L S.R Q.P Q Q.R
156 ASSERT(RtlParent(LinkA
) == LinkB
);
157 ASSERT(RtlLeftChild(LinkA
) == RtlLeftChild(&Tb
));
158 ASSERT(RtlRightChild(LinkA
) == RtlRightChild(&Tb
));
159 ASSERT(RtlParent(LinkB
) == RtlParent(&Ta
));
160 ASSERT(RtlLeftChild(LinkB
) == (LeftB
? LinkA
: RtlLeftChild(&Ta
)));
161 ASSERT(RtlRightChild(LinkB
) == (LeftB
? RtlRightChild(&Ta
) : LinkA
));
165 // LinkA = A, LinkB = C
166 // A C S.P S.L S.R Q.P Q.L Q.R
167 ASSERT(!memcmp(LinkA
, &Tb
, sizeof(Tb
)));
168 ASSERT(!memcmp(LinkB
, &Ta
, sizeof(Ta
)));
180 RtlDelete(PRTL_SPLAY_LINKS Links
)
182 PRTL_SPLAY_LINKS N
, P
, C
, SP
;
185 /* Check if we have two children */
186 if (RtlLeftChild(N
) && RtlRightChild(N
))
188 /* Get the predecessor */
189 SP
= RtlSubtreePredecessor(N
);
191 /* Swap it with N, this will guarantee that N will only have a child */
192 SwapSplayLinks(SP
, N
);
195 /* Check if we have no children */
196 if (!RtlLeftChild(N
) && !RtlRightChild(N
))
198 /* If we are also the root, then the tree is gone */
199 if (RtlIsRoot(N
)) return NULL
;
204 /* Find out who is referencing us and delete the reference */
205 if (RtlIsLeftChild(N
))
207 /* N was a left child, so erase its parent's left child link */
208 RtlLeftChild(P
) = NULL
;
212 /* N was a right child, so erase its parent's right child link */
213 RtlRightChild(P
) = NULL
;
216 /* And finally splay the parent */
220 /* If we got here, we have a child (not two: we swapped above!) */
223 /* We have a left child, so get it */
228 /* We have a right child, get it instead */
229 C
= RtlRightChild(N
);
232 /* Check if we are the root entry */
235 /* Our child is now root, return it */
243 /* Find out who is referencing us and link to our child instead */
244 if (RtlIsLeftChild(N
))
246 /* N was a left child, so set its parent's left child as our child */
251 /* N was a right child, so set its parent's right child as our child */
252 RtlRightChild(P
) = C
;
255 /* Finally, inherit our parent and splay the parent */
265 RtlDeleteNoSplay(PRTL_SPLAY_LINKS Links
,
266 PRTL_SPLAY_LINKS
*Root
)
268 PRTL_SPLAY_LINKS N
, P
, C
, SP
;
271 /* Check if we have two children */
272 if (RtlLeftChild(N
) && RtlRightChild(N
))
274 /* Get the predecessor */
275 SP
= RtlSubtreePredecessor(N
);
277 /* If we are the root, the new root will be our predecessor after swapping */
278 if (RtlIsRoot(N
)) *Root
= SP
;
280 /* Swap the predecessor with N, this will guarantee that N will only have a child */
281 SwapSplayLinks(SP
, N
);
284 /* Check if we have no children */
285 if (!RtlLeftChild(N
) && !RtlRightChild(N
))
287 /* If we are also the root, then the tree is gone */
297 /* Find out who is referencing us and delete the reference */
298 if (RtlIsLeftChild(N
))
300 /* N was a left child, so erase its parent's left child link */
301 RtlLeftChild(P
) = NULL
;
305 /* N was a right child, so erase its parent's right child link */
306 RtlRightChild(P
) = NULL
;
313 /* If we got here, we have a child (not two: we swapped above!) */
316 /* We have a left child, so get it */
321 /* We have a right child, get it instead */
322 C
= RtlRightChild(N
);
325 /* Check if we are the root entry */
328 /* Our child is now root, return it */
337 /* Find out who is referencing us and link to our child instead */
338 if (RtlIsLeftChild(N
))
340 /* N was a left child, so set its parent's left child as our child */
345 /* N was a right child, so set its parent's right child as our child */
346 RtlRightChild(P
) = C
;
349 /* Finally, inherit our parent and we are done */
359 RtlRealPredecessor(PRTL_SPLAY_LINKS Links
)
361 PRTL_SPLAY_LINKS Child
;
363 /* Get the left child */
364 Child
= RtlLeftChild(Links
);
367 /* Get right-most child */
368 while (RtlRightChild(Child
)) Child
= RtlRightChild(Child
);
372 /* We don't have a left child, keep looping until we find our parent */
374 while (RtlIsLeftChild(Child
)) Child
= RtlParent(Child
);
376 /* The parent should be a right child, return the real predecessor */
377 if (RtlIsRightChild(Child
)) return RtlParent(Child
);
379 /* The parent isn't a right child, so no real precessor for us */
388 RtlRealSuccessor(PRTL_SPLAY_LINKS Links
)
390 PRTL_SPLAY_LINKS Child
;
392 /* Get the right child */
393 Child
= RtlRightChild(Links
);
396 /* Get left-most child */
397 while (RtlLeftChild(Child
)) Child
= RtlLeftChild(Child
);
401 /* We don't have a right child, keep looping until we find our parent */
403 while (RtlIsRightChild(Child
)) Child
= RtlParent(Child
);
405 /* The parent should be a left child, return the real successor */
406 if (RtlIsLeftChild(Child
)) return RtlParent(Child
);
408 /* The parent isn't a right child, so no real successor for us */
417 RtlSplay(PRTL_SPLAY_LINKS Links
)
420 * Implementation Notes (http://en.wikipedia.org/wiki/Splay_tree):
422 * To do a splay, we carry out a sequence of rotations,
423 * each of which moves the target node N closer to the root.
425 * Each particular step depends on only two factors:
426 * - Whether N is the left or right child of its parent node, P,
427 * - Whether P is the left or right child of its parent, G (for grandparent node).
429 * Thus, there are four cases:
430 * - Case 1: N is the left child of P and P is the left child of G.
431 * In this case we perform a double right rotation, so that
432 * P becomes N's right child, and G becomes P's right child.
434 * - Case 2: N is the right child of P and P is the right child of G.
435 * In this case we perform a double left rotation, so that
436 * P becomes N's left child, and G becomes P's left child.
438 * - Case 3: N is the left child of P and P is the right child of G.
439 * In this case we perform a rotation so that
440 * G becomes N's left child, and P becomes N's right child.
442 * - Case 4: N is the right child of P and P is the left child of G.
443 * In this case we perform a rotation so that
444 * P becomes N's left child, and G becomes N's right child.
446 * Finally, if N doesn't have a grandparent node, we simply perform a
447 * left or right rotation to move it to the root.
449 * By performing a splay on the node of interest after every operation,
450 * we keep recently accessed nodes near the root and keep the tree
451 * roughly balanced, so that we achieve the desired amortized time bounds.
453 PRTL_SPLAY_LINKS N
, P
, G
;
455 /* N is the item we'll be playing with */
458 /* Let the algorithm run until N becomes the root entry */
459 while (!RtlIsRoot(N
))
461 /* Now get the parent and grand-parent */
465 /* Case 1 & 3: N is left child of P */
466 if (RtlIsLeftChild(N
))
468 /* Case 1: P is the left child of G */
469 if (RtlIsLeftChild(P
))
472 * N's right-child becomes P's left child and
473 * P's right-child becomes G's left child.
475 RtlLeftChild(P
) = RtlRightChild(N
);
476 RtlLeftChild(G
) = RtlRightChild(P
);
479 * If they exist, update their parent pointers too,
480 * since they've changed trees.
482 if (RtlLeftChild(P
)) RtlParent(RtlLeftChild(P
)) = P
;
483 if (RtlLeftChild(G
)) RtlParent(RtlLeftChild(G
)) = G
;
486 * Now we'll shove N all the way to the top.
487 * Check if G is the root first.
491 /* G doesn't have a parent, so N will become the root! */
496 /* G has a parent, so inherit it since we take G's place */
497 RtlParent(N
) = RtlParent(G
);
500 * Now find out who was referencing G and have it reference
501 * N instead, since we're taking G's place.
503 if (RtlIsLeftChild(G
))
506 * G was a left child, so change its parent's left
507 * child link to point to N now.
509 RtlLeftChild(RtlParent(G
)) = N
;
514 * G was a right child, so change its parent's right
515 * child link to point to N now.
517 RtlRightChild(RtlParent(G
)) = N
;
521 /* Now N is on top, so P has become its child. */
522 RtlRightChild(N
) = P
;
525 /* N is on top, P is its child, so G is grandchild. */
526 RtlRightChild(P
) = G
;
529 /* Case 3: P is the right child of G */
530 else if (RtlIsRightChild(P
))
533 * N's left-child becomes G's right child and
534 * N's right-child becomes P's left child.
536 RtlRightChild(G
) = RtlLeftChild(N
);
537 RtlLeftChild(P
) = RtlRightChild(N
);
540 * If they exist, update their parent pointers too,
541 * since they've changed trees.
543 if (RtlRightChild(G
)) RtlParent(RtlRightChild(G
)) = G
;
544 if (RtlLeftChild(P
)) RtlParent(RtlLeftChild(P
)) = P
;
547 * Now we'll shove N all the way to the top.
548 * Check if G is the root first.
552 /* G doesn't have a parent, so N will become the root! */
557 /* G has a parent, so inherit it since we take G's place */
558 RtlParent(N
) = RtlParent(G
);
561 * Now find out who was referencing G and have it reference
562 * N instead, since we're taking G's place.
564 if (RtlIsLeftChild(G
))
567 * G was a left child, so change its parent's left
568 * child link to point to N now.
570 RtlLeftChild(RtlParent(G
)) = N
;
575 * G was a right child, so change its parent's right
576 * child link to point to N now.
578 RtlRightChild(RtlParent(G
)) = N
;
582 /* Now N is on top, so G has become its left child. */
586 /* N is on top, G is its left child, so P is right child. */
587 RtlRightChild(N
) = P
;
590 /* "Finally" case: N doesn't have a grandparent => P is root */
593 /* P's left-child becomes N's right child */
594 RtlLeftChild(P
) = RtlRightChild(N
);
596 /* If it exists, update its parent pointer too */
597 if (RtlLeftChild(P
)) RtlParent(RtlLeftChild(P
)) = P
;
599 /* Now make N the root, no need to worry about references */
602 /* And make P its right child */
607 /* Case 2 & 4: N is right child of P */
610 /* Case 2: P is the right child of G */
611 if (RtlIsRightChild(P
))
614 * P's left-child becomes G's right child and
615 * N's left-child becomes P's right child.
617 RtlRightChild(G
) = RtlLeftChild(P
);
618 RtlRightChild(P
) = RtlLeftChild(N
);
621 * If they exist, update their parent pointers too,
622 * since they've changed trees.
624 if (RtlRightChild(G
)) RtlParent(RtlRightChild(G
)) = G
;
625 if (RtlRightChild(P
)) RtlParent(RtlRightChild(P
)) = P
;
628 * Now we'll shove N all the way to the top.
629 * Check if G is the root first.
633 /* G doesn't have a parent, so N will become the root! */
638 /* G has a parent, so inherit it since we take G's place */
639 RtlParent(N
) = RtlParent(G
);
642 * Now find out who was referencing G and have it reference
643 * N instead, since we're taking G's place.
645 if (RtlIsLeftChild(G
))
648 * G was a left child, so change its parent's left
649 * child link to point to N now.
651 RtlLeftChild(RtlParent(G
)) = N
;
656 * G was a right child, so change its parent's right
657 * child link to point to N now.
659 RtlRightChild(RtlParent(G
)) = N
;
663 /* Now N is on top, so P has become its child. */
667 /* N is on top, P is its child, so G is grandchild. */
671 /* Case 4: P is the left child of G */
672 else if (RtlIsLeftChild(P
))
675 * N's left-child becomes G's right child and
676 * N's right-child becomes P's left child.
678 RtlRightChild(P
) = RtlLeftChild(N
);
679 RtlLeftChild(G
) = RtlRightChild(N
);
682 * If they exist, update their parent pointers too,
683 * since they've changed trees.
685 if (RtlRightChild(P
)) RtlParent(RtlRightChild(P
)) = P
;
686 if (RtlLeftChild(G
)) RtlParent(RtlLeftChild(G
)) = G
;
689 * Now we'll shove N all the way to the top.
690 * Check if G is the root first.
694 /* G doesn't have a parent, so N will become the root! */
699 /* G has a parent, so inherit it since we take G's place */
700 RtlParent(N
) = RtlParent(G
);
703 * Now find out who was referencing G and have it reference
704 * N instead, since we're taking G's place.
706 if (RtlIsLeftChild(G
))
709 * G was a left child, so change its parent's left
710 * child link to point to N now.
712 RtlLeftChild(RtlParent(G
)) = N
;
717 * G was a right child, so change its parent's right
718 * child link to point to N now.
720 RtlRightChild(RtlParent(G
)) = N
;
724 /* Now N is on top, so P has become its left child. */
728 /* N is on top, P is its left child, so G is right child. */
729 RtlRightChild(N
) = G
;
732 /* "Finally" case: N doesn't have a grandparent => P is root */
735 /* P's right-child becomes N's left child */
736 RtlRightChild(P
) = RtlLeftChild(N
);
738 /* If it exists, update its parent pointer too */
739 if (RtlRightChild(P
)) RtlParent(RtlRightChild(P
)) = P
;
741 /* Now make N the root, no need to worry about references */
744 /* And make P its left child */
751 /* Return the root entry */
752 ASSERT(RtlIsRoot(N
));
761 RtlSubtreePredecessor(IN PRTL_SPLAY_LINKS Links
)
763 PRTL_SPLAY_LINKS Child
;
765 /* Get the left child */
766 Child
= RtlLeftChild(Links
);
767 if (!Child
) return NULL
;
769 /* Get right-most child */
770 while (RtlRightChild(Child
)) Child
= RtlRightChild(Child
);
781 RtlSubtreeSuccessor(IN PRTL_SPLAY_LINKS Links
)
783 PRTL_SPLAY_LINKS Child
;
785 /* Get the right child */
786 Child
= RtlRightChild(Links
);
787 if (!Child
) return NULL
;
789 /* Get left-most child */
790 while (RtlLeftChild(Child
)) Child
= RtlLeftChild(Child
);