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 /* FUNCTIONS ***************************************************************/
19 SwapSplayLinks(PRTL_SPLAY_LINKS LinkA
,
20 PRTL_SPLAY_LINKS LinkB
)
22 DPRINT1("UNIMPLEMENTED!\n");
30 RtlDelete(PRTL_SPLAY_LINKS Links
)
32 PRTL_SPLAY_LINKS N
, P
, C
, SP
;
35 /* Check if we have two children */
36 if ((RtlLeftChild(N
)) && (RtlRightChild(N
)))
38 /* Get the predecessor */
39 SP
= RtlSubtreePredecessor(N
);
41 /* Swap it with N, this will guarantee that N will have only a child */
42 SwapSplayLinks(SP
, N
);
45 /* Check if we have no children */
46 if (!(RtlLeftChild(N
)) && !(RtlRightChild(N
)))
48 /* If we are also the root, then the tree is gone */
49 if (RtlIsRoot(N
)) return NULL
;
54 /* Find out who is referencing us and delete the reference */
55 if (RtlIsLeftChild(N
))
57 /* N was a left child, so erase its parent's left child link */
58 RtlLeftChild(RtlParent(N
)) = NULL
;
62 /* N was a right child, so erase its parent's right child link */
63 RtlRightChild(RtlParent(N
)) = NULL
;
66 /* And finally splay the parent */
70 /* If we got here, we have a child (not two: we swapped above!) */
73 /* We have a left child, so get it */
78 /* We have a right child, get him instead */
82 /* Check if we are the root entry */
85 /* Our child is now root, return him */
90 /* Find out who is referencing us and link to our child instead */
91 if (RtlIsLeftChild(N
))
93 /* N was a left child, so set its parent's left child as our child */
94 RtlLeftChild(RtlParent(N
)) = C
;
98 /* N was a right child, so set its parent's right child as our child */
99 RtlRightChild(RtlParent(N
)) = C
;
102 /* Finally, inherit our parent and splay the parent */
103 C
->Parent
= N
->Parent
;
104 return RtlSplay(RtlParent(C
));
112 RtlDeleteNoSplay(PRTL_SPLAY_LINKS Links
,
113 PRTL_SPLAY_LINKS
*Root
)
123 RtlRealPredecessor(PRTL_SPLAY_LINKS Links
)
125 PRTL_SPLAY_LINKS Child
;
127 /* Get the left child */
128 Child
= RtlLeftChild(Links
);
131 /* Get right-most child */
132 while (RtlRightChild(Child
)) Child
= RtlRightChild(Child
);
136 /* We don't have a left child, keep looping until we find our parent */
138 while (RtlIsLeftChild(Child
)) Child
= RtlParent(Child
);
140 /* The parent should be a right child, return the real predecessor */
141 if (RtlIsRightChild(Child
)) return RtlParent(Child
);
143 /* The parent isn't a right child, so no real precessor for us */
152 RtlRealSuccessor(PRTL_SPLAY_LINKS Links
)
154 PRTL_SPLAY_LINKS Child
;
156 /* Get the right child */
157 Child
= RtlRightChild(Links
);
160 /* Get left-most child */
161 while (RtlLeftChild(Child
)) Child
= RtlLeftChild(Child
);
165 /* We don't have a right child, keep looping until we find our parent */
167 while (RtlIsRightChild(Child
)) Child
= RtlParent(Child
);
169 /* The parent should be a left child, return the real successor */
170 if (RtlIsLeftChild(Child
)) return RtlParent(Child
);
172 /* The parent isn't a right child, so no real successor for us */
181 RtlSplay(PRTL_SPLAY_LINKS Links
)
184 * Implementation Notes (http://en.wikipedia.org/wiki/Splay_tree):
186 * To do a splay, we carry out a sequence of rotations,
187 * each of which moves the target node N closer to the root.
189 * Each particular step depends on only two factors:
190 * - Whether N is the left or right child of its parent node, P,
191 * - Whether P is the left or right child of its parent, G (for grandparent node).
193 * Thus, there are four cases:
194 * - Case 1: N is the left child of P and P is the left child of G.
195 * In this case we perform a double right rotation, so that
196 * P becomes N's right child, and G becomes P's right child.
198 * - Case 2: N is the right child of P and P is the right child of G.
199 * In this case we perform a double left rotation, so that
200 * P becomes N's left child, and G becomes P's left child.
202 * - Case 3: N is the left child of P and P is the right child of G.
203 * In this case we perform a rotation so that
204 * G becomes N's left child, and P becomes N's right child.
206 * - Case 4: N is the right child of P and P is the left child of G.
207 * In this case we perform a rotation so that
208 * P becomes N's left child, and G becomes N's right child.
210 * Finally, if N doesn't have a grandparent node, we simply perform a
211 * left or right rotation to move it to the root.
213 * By performing a splay on the node of interest after every operation,
214 * we keep recently accessed nodes near the root and keep the tree
215 * roughly balanced, so that we achieve the desired amortized time bounds.
217 PRTL_SPLAY_LINKS N
, P
, G
;
219 /* N is the item we'll be playing with */
222 /* Let the algorithm run until N becomes the root entry */
223 while (!RtlIsRoot(N
))
225 /* Now get the parent and grand-parent */
229 /* Case 1 & 3: N is left child of P */
230 if (RtlIsLeftChild(N
))
232 /* Case 1: P is the left child of G */
233 if (RtlIsLeftChild(P
))
236 * N's right-child becomes P's left child and
237 * P's right-child becomes G's left child.
239 RtlLeftChild(P
) = RtlRightChild(N
);
240 RtlLeftChild(G
) = RtlRightChild(P
);
243 * If they exist, update their parent pointers too,
244 * since they've changed trees.
246 if (RtlLeftChild(P
)) RtlParent(RtlLeftChild(P
)) = P
;
247 if (RtlLeftChild(G
)) RtlParent(RtlLeftChild(G
)) = G
;
250 * Now we'll shove N all the way to the top.
251 * Check if G is the root first.
255 /* G doesn't have a parent, so N will become the root! */
260 /* G has a parent, so inherit it since we take G's place */
261 RtlParent(N
) = RtlParent(G
);
264 * Now find out who was referencing G and have it reference
265 * N instead, since we're taking G's place.
267 if (RtlIsLeftChild(G
))
270 * G was a left child, so change its parent's left
271 * child link to point to N now.
273 RtlLeftChild(RtlParent(G
)) = N
;
278 * G was a right child, so change its parent's right
279 * child link to point to N now.
281 RtlRightChild(RtlParent(G
)) = N
;
285 /* Now N is on top, so P has become its child. */
286 RtlRightChild(N
) = P
;
289 /* N is on top, P is its child, so G is grandchild. */
290 RtlRightChild(P
) = G
;
293 /* Case 3: P is the right child of G */
294 else if (RtlIsRightChild(P
))
297 * N's left-child becomes G's right child and
298 * N's right-child becomes P's left child.
300 RtlRightChild(G
) = RtlLeftChild(N
);
301 RtlLeftChild(P
) = RtlRightChild(N
);
304 * If they exist, update their parent pointers too,
305 * since they've changed trees.
307 if (RtlRightChild(G
)) RtlParent(RtlRightChild(G
)) = G
;
308 if (RtlLeftChild(P
)) RtlParent(RtlLeftChild(P
)) = P
;
311 * Now we'll shove N all the way to the top.
312 * Check if G is the root first.
316 /* G doesn't have a parent, so N will become the root! */
321 /* G has a parent, so inherit it since we take G's place */
322 RtlParent(N
) = RtlParent(G
);
325 * Now find out who was referencing G and have it reference
326 * N instead, since we're taking G's place.
328 if (RtlIsLeftChild(G
))
331 * G was a left child, so change its parent's left
332 * child link to point to N now.
334 RtlLeftChild(RtlParent(G
)) = N
;
339 * G was a right child, so change its parent's right
340 * child link to point to N now.
342 RtlRightChild(RtlParent(G
)) = N
;
346 /* Now N is on top, so G has become its left child. */
350 /* N is on top, G is its left child, so P is right child. */
351 RtlRightChild(N
) = P
;
354 /* "Finally" case: N doesn't have a grandparent => P is root */
357 /* P's left-child becomes N's right child */
358 RtlLeftChild(P
) = RtlRightChild(N
);
360 /* If it exists, update its parent pointer too */
361 if (RtlLeftChild(P
)) RtlParent(RtlLeftChild(P
)) = P
;
363 /* Now make N the root, no need to worry about references */
366 /* And make P its right child */
371 /* Case 2 & 4: N is right child of P */
374 /* Case 2: P is the right child of G */
375 if (RtlIsRightChild(P
))
378 * P's left-child becomes G's right child and
379 * N's left-child becomes P's right child.
381 RtlRightChild(G
) = RtlLeftChild(P
);
382 RtlRightChild(P
) = RtlLeftChild(N
);
385 * If they exist, update their parent pointers too,
386 * since they've changed trees.
388 if (RtlRightChild(G
)) RtlParent(RtlRightChild(G
)) = G
;
389 if (RtlRightChild(P
)) RtlParent(RtlRightChild(P
)) = P
;
392 * Now we'll shove N all the way to the top.
393 * Check if G is the root first.
397 /* G doesn't have a parent, so N will become the root! */
402 /* G has a parent, so inherit it since we take G's place */
403 RtlParent(N
) = RtlParent(G
);
406 * Now find out who was referencing G and have it reference
407 * N instead, since we're taking G's place.
409 if (RtlIsLeftChild(G
))
412 * G was a left child, so change its parent's left
413 * child link to point to N now.
415 RtlLeftChild(RtlParent(G
)) = N
;
420 * G was a right child, so change its parent's right
421 * child link to point to N now.
423 RtlRightChild(RtlParent(G
)) = N
;
427 /* Now N is on top, so P has become its child. */
431 /* N is on top, P is its child, so G is grandchild. */
435 /* Case 4: P is the left child of G */
436 else if (RtlIsLeftChild(P
))
439 * N's left-child becomes G's right child and
440 * N's right-child becomes P's left child.
442 RtlRightChild(P
) = RtlLeftChild(N
);
443 RtlLeftChild(G
) = RtlRightChild(N
);
446 * If they exist, update their parent pointers too,
447 * since they've changed trees.
449 if (RtlRightChild(P
)) RtlParent(RtlRightChild(P
)) = P
;
450 if (RtlLeftChild(G
)) RtlParent(RtlLeftChild(G
)) = G
;
453 * Now we'll shove N all the way to the top.
454 * Check if G is the root first.
458 /* G doesn't have a parent, so N will become the root! */
463 /* G has a parent, so inherit it since we take G's place */
464 RtlParent(N
) = RtlParent(G
);
467 * Now find out who was referencing G and have it reference
468 * N instead, since we're taking G's place.
470 if (RtlIsLeftChild(G
))
473 * G was a left child, so change its parent's left
474 * child link to point to N now.
476 RtlLeftChild(RtlParent(G
)) = N
;
481 * G was a right child, so change its parent's right
482 * child link to point to N now.
484 RtlRightChild(RtlParent(G
)) = N
;
488 /* Now N is on top, so P has become its left child. */
492 /* N is on top, P is its left child, so G is right child. */
493 RtlRightChild(N
) = G
;
496 /* "Finally" case: N doesn't have a grandparent => P is root */
499 /* P's right-child becomes N's left child */
500 RtlRightChild(P
) = RtlLeftChild(N
);
502 /* If it exists, update its parent pointer too */
503 if (RtlRightChild(P
)) RtlParent(RtlRightChild(P
)) = P
;
505 /* Now make N the root, no need to worry about references */
508 /* And make P its left child */
515 /* Return the root entry */
524 RtlSubtreePredecessor(IN PRTL_SPLAY_LINKS Links
)
526 PRTL_SPLAY_LINKS Child
;
528 /* Get the left child */
529 Child
= RtlLeftChild(Links
);
530 if (!Child
) return NULL
;
532 /* Get right-most child */
533 while (RtlRightChild(Child
)) Child
= RtlRightChild(Child
);
544 RtlSubtreeSuccessor(IN PRTL_SPLAY_LINKS Links
)
546 PRTL_SPLAY_LINKS Child
;
548 /* Get the right child */
549 Child
= RtlRightChild(Links
);
550 if (!Child
) return NULL
;
552 /* Get left-most child */
553 while (RtlLeftChild(Child
)) Child
= RtlLeftChild(Child
);