Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1072 lines
26 KiB

  1. /*++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. Splay.cpp
  5. Abstract:
  6. Stolen from ntos\rtl\splay.c
  7. Copied here to avoid pulling in an obj from another project.
  8. --*/
  9. #include "ntsdp.hpp"
  10. #define SwapPointers(Type, Ptr1, Ptr2) { \
  11. Type _SWAP_POINTER_TEMP; \
  12. _SWAP_POINTER_TEMP = (Ptr1); \
  13. (Ptr1) = (Ptr2); \
  14. (Ptr2) = _SWAP_POINTER_TEMP; \
  15. }
  16. #define ParentsChildPointerAddress(Links) ( \
  17. RtlIsLeftChild(Links) ? \
  18. &(((Links)->Parent)->LeftChild) \
  19. : \
  20. &(((Links)->Parent)->RightChild) \
  21. )
  22. PRTL_SPLAY_LINKS
  23. pRtlSubtreePredecessor (
  24. IN PRTL_SPLAY_LINKS Links
  25. );
  26. VOID
  27. SwapSplayLinks (
  28. IN PRTL_SPLAY_LINKS Link1,
  29. IN PRTL_SPLAY_LINKS Link2
  30. );
  31. PRTL_SPLAY_LINKS
  32. pRtlSplay (
  33. IN PRTL_SPLAY_LINKS Links
  34. )
  35. /*++
  36. Routine Description:
  37. The Splay function takes as input a pointer to a splay link in a tree
  38. and splays the tree. Its function return value is a pointer to the
  39. root of the splayed tree.
  40. Arguments:
  41. Links - Supplies a pointer to a splay link in a tree.
  42. Return Value:
  43. PRTL_SPLAY_LINKS - returns a pointer to the root of the splayed tree.
  44. --*/
  45. {
  46. PRTL_SPLAY_LINKS L;
  47. PRTL_SPLAY_LINKS P;
  48. PRTL_SPLAY_LINKS G;
  49. //
  50. // while links is not the root we need to keep rotating it toward
  51. // the root
  52. //
  53. L = Links;
  54. while (!RtlIsRoot(L)) {
  55. P = RtlParent(L);
  56. G = RtlParent(P);
  57. if (RtlIsLeftChild(L)) {
  58. if (RtlIsRoot(P)) {
  59. /*
  60. we have the following case
  61. P L
  62. / \ / \
  63. L c ==> a P
  64. / \ / \
  65. a b b c
  66. */
  67. //
  68. // Connect P & b
  69. //
  70. P->LeftChild = L->RightChild;
  71. if (P->LeftChild != NULL) {P->LeftChild->Parent = P;}
  72. //
  73. // Connect L & P
  74. //
  75. L->RightChild = P;
  76. P->Parent = L;
  77. //
  78. // Make L the root
  79. //
  80. L->Parent = L;
  81. } else if (RtlIsLeftChild(P)) {
  82. /*
  83. we have the following case
  84. | |
  85. G L
  86. / \ / \
  87. P d ==> a P
  88. / \ / \
  89. L c b G
  90. / \ / \
  91. a b c d
  92. */
  93. //
  94. // Connect P & b
  95. //
  96. P->LeftChild = L->RightChild;
  97. if (P->LeftChild != NULL) {P->LeftChild->Parent = P;}
  98. //
  99. // Connect G & c
  100. //
  101. G->LeftChild = P->RightChild;
  102. if (G->LeftChild != NULL) {G->LeftChild->Parent = G;}
  103. //
  104. // Connect L & Great GrandParent
  105. //
  106. if (RtlIsRoot(G)) {
  107. L->Parent = L;
  108. } else {
  109. L->Parent = G->Parent;
  110. *(ParentsChildPointerAddress(G)) = L;
  111. }
  112. //
  113. // Connect L & P
  114. //
  115. L->RightChild = P;
  116. P->Parent = L;
  117. //
  118. // Connect P & G
  119. //
  120. P->RightChild = G;
  121. G->Parent = P;
  122. } else { // RtlIsRightChild(Parent)
  123. /*
  124. we have the following case
  125. | |
  126. G L
  127. / \ / \
  128. a P G P
  129. / \ / \ / \
  130. L d ==> a b c d
  131. / \
  132. b c
  133. */
  134. //
  135. // Connect G & b
  136. //
  137. G->RightChild = L->LeftChild;
  138. if (G->RightChild != NULL) {G->RightChild->Parent = G;}
  139. //
  140. // Connect P & c
  141. //
  142. P->LeftChild = L->RightChild;
  143. if (P->LeftChild != NULL) {P->LeftChild->Parent = P;}
  144. //
  145. // Connect L & Great GrandParent
  146. //
  147. if (RtlIsRoot(G)) {
  148. L->Parent = L;
  149. } else {
  150. L->Parent = G->Parent;
  151. *(ParentsChildPointerAddress(G)) = L;
  152. }
  153. //
  154. // Connect L & G
  155. //
  156. L->LeftChild = G;
  157. G->Parent = L;
  158. //
  159. // Connect L & P
  160. //
  161. L->RightChild = P;
  162. P->Parent = L;
  163. }
  164. } else { // RtlIsRightChild(L)
  165. if (RtlIsRoot(P)) {
  166. /*
  167. we have the following case
  168. P L
  169. / \ / \
  170. a L P c
  171. / \ / \
  172. b c ==> a b
  173. */
  174. //
  175. // Connect P & b
  176. //
  177. P->RightChild = L->LeftChild;
  178. if (P->RightChild != NULL) {P->RightChild->Parent = P;}
  179. //
  180. // Connect P & L
  181. //
  182. L->LeftChild = P;
  183. P->Parent = L;
  184. //
  185. // Make L the root
  186. //
  187. L->Parent = L;
  188. } else if (RtlIsRightChild(P)) {
  189. /*
  190. we have the following case
  191. | |
  192. G L
  193. / \ / \
  194. a P P d
  195. / \ / \
  196. b L G c
  197. / \ / \
  198. c d ==> a b
  199. */
  200. //
  201. // Connect G & b
  202. //
  203. G->RightChild = P->LeftChild;
  204. if (G->RightChild != NULL) {G->RightChild->Parent = G;}
  205. //
  206. // Connect P & c
  207. //
  208. P->RightChild = L->LeftChild;
  209. if (P->RightChild != NULL) {P->RightChild->Parent = P;}
  210. //
  211. // Connect L & Great GrandParent
  212. //
  213. if (RtlIsRoot(G)) {
  214. L->Parent = L;
  215. } else {
  216. L->Parent = G->Parent;
  217. *(ParentsChildPointerAddress(G)) = L;
  218. }
  219. //
  220. // Connect L & P
  221. //
  222. L->LeftChild = P;
  223. P->Parent = L;
  224. //
  225. // Connect P & G
  226. //
  227. P->LeftChild = G;
  228. G->Parent = P;
  229. } else { // RtlIsLeftChild(P)
  230. /*
  231. we have the following case
  232. | |
  233. G L
  234. / \ / \
  235. P d P G
  236. / \ / \ / \
  237. a L ==> a b c d
  238. / \
  239. b c
  240. */
  241. //
  242. // Connect P & b
  243. //
  244. P->RightChild = L->LeftChild;
  245. if (P->RightChild != NULL) {P->RightChild->Parent = P;}
  246. //
  247. // Connect G & c
  248. //
  249. G->LeftChild = L->RightChild;
  250. if (G->LeftChild != NULL) {G->LeftChild->Parent = G;}
  251. //
  252. // Connect L & Great GrandParent
  253. //
  254. if (RtlIsRoot(G)) {
  255. L->Parent = L;
  256. } else {
  257. L->Parent = G->Parent;
  258. *(ParentsChildPointerAddress(G)) = L;
  259. }
  260. //
  261. // Connect L & P
  262. //
  263. L->LeftChild = P;
  264. P->Parent = L;
  265. //
  266. // Connect L & G
  267. //
  268. L->RightChild = G;
  269. G->Parent = L;
  270. }
  271. }
  272. }
  273. return L;
  274. }
  275. PRTL_SPLAY_LINKS
  276. pRtlDelete (
  277. IN PRTL_SPLAY_LINKS Links
  278. )
  279. /*++
  280. Routine Description:
  281. The Delete function takes as input a pointer to a splay link in a tree
  282. and deletes that node from the tree. Its function return value is a
  283. pointer to the root of the tree. If the tree is now empty, the return
  284. value is NULL.
  285. Arguments:
  286. Links - Supplies a pointer to a splay link in a tree.
  287. Return Value:
  288. PRTL_SPLAY_LINKS - returns a pointer to the root of the tree.
  289. --*/
  290. {
  291. PRTL_SPLAY_LINKS Predecessor;
  292. PRTL_SPLAY_LINKS Parent;
  293. PRTL_SPLAY_LINKS Child;
  294. PRTL_SPLAY_LINKS *ParentChildPtr;
  295. //
  296. // First check to see if Links as two children. If it does then swap
  297. // Links with its subtree predecessor. Now we are guaranteed that Links
  298. // has at most one child.
  299. //
  300. if ((RtlLeftChild(Links) != NULL) && (RtlRightChild(Links) != NULL)) {
  301. //
  302. // get the predecessor, and swap their position in the tree
  303. //
  304. Predecessor = pRtlSubtreePredecessor(Links);
  305. SwapSplayLinks(Predecessor, Links);
  306. }
  307. //
  308. // If Links has no children then delete links by checking if it is
  309. // already the root or has a parent. If it is the root then the
  310. // tree is now empty, otherwise it set the appropriate parent's child
  311. // pointer (i.e., the one to links) to NULL, and splay the parent.
  312. //
  313. if ((RtlLeftChild(Links) == NULL) && (RtlRightChild(Links) == NULL)) {
  314. //
  315. // Links has no children, if it is the root then return NULL
  316. //
  317. if (RtlIsRoot(Links)) {
  318. return NULL;
  319. }
  320. //
  321. // Links as not children and is not the root, so to the parent's
  322. // child pointer to NULL and splay the parent.
  323. //
  324. Parent = RtlParent(Links);
  325. ParentChildPtr = ParentsChildPointerAddress(Links);
  326. *ParentChildPtr = NULL;
  327. return pRtlSplay(Parent);
  328. }
  329. //
  330. // otherwise Links has one child. If it is the root then make the child
  331. // the new root, otherwise link together the child and parent, and splay
  332. // the parent. But first remember who our child is.
  333. //
  334. if (RtlLeftChild(Links) != NULL) {
  335. Child = RtlLeftChild(Links);
  336. } else {
  337. Child = RtlRightChild(Links);
  338. }
  339. //
  340. // If links is the root then we make the child the root and return the
  341. // child.
  342. //
  343. if (RtlIsRoot(Links)) {
  344. Child->Parent = Child;
  345. return Child;
  346. }
  347. //
  348. // Links is not the root, so set link's parent child pointer to be
  349. // the child and the set child's parent to be link's parent, and splay
  350. // the parent.
  351. //
  352. ParentChildPtr = ParentsChildPointerAddress(Links);
  353. *ParentChildPtr = Child;
  354. Child->Parent = Links->Parent;
  355. return pRtlSplay(RtlParent(Child));
  356. }
  357. #if 0
  358. VOID
  359. RtlDeleteNoSplay (
  360. IN PRTL_SPLAY_LINKS Links,
  361. IN OUT PRTL_SPLAY_LINKS *Root
  362. )
  363. /*++
  364. Routine Description:
  365. The Delete function takes as input a pointer to a splay link in a tree,
  366. a pointer to the callers pointer to the tree and deletes that node from
  367. the tree. The caller's pointer is updated upon return. If the tree is
  368. now empty, the value is NULL.
  369. Unfortunately, the original RtlDelete() always splays and this is not
  370. always a desireable side-effect.
  371. Arguments:
  372. Links - Supplies a pointer to a splay link in a tree.
  373. Root - Pointer to the callers pointer to the root
  374. Return Value:
  375. None
  376. --*/
  377. {
  378. PRTL_SPLAY_LINKS Predecessor;
  379. PRTL_SPLAY_LINKS Parent;
  380. PRTL_SPLAY_LINKS Child;
  381. PRTL_SPLAY_LINKS *ParentChildPtr;
  382. //
  383. // First check to see if Links as two children. If it does then swap
  384. // Links with its subtree predecessor. Now we are guaranteed that Links
  385. // has at most one child.
  386. //
  387. if ((RtlLeftChild(Links) != NULL) && (RtlRightChild(Links) != NULL)) {
  388. //
  389. // get the predecessor, and swap their position in the tree
  390. //
  391. Predecessor = pRtlSubtreePredecessor(Links);
  392. if (RtlIsRoot(Links)) {
  393. //
  394. // If we're switching with the root of the tree, fix the
  395. // caller's root pointer
  396. //
  397. *Root = Predecessor;
  398. }
  399. SwapSplayLinks(Predecessor, Links);
  400. }
  401. //
  402. // If Links has no children then delete links by checking if it is
  403. // already the root or has a parent. If it is the root then the
  404. // tree is now empty, otherwise it set the appropriate parent's child
  405. // pointer (i.e., the one to links) to NULL.
  406. //
  407. if ((RtlLeftChild(Links) == NULL) && (RtlRightChild(Links) == NULL)) {
  408. //
  409. // Links has no children, if it is the root then set root to NULL
  410. //
  411. if (RtlIsRoot(Links)) {
  412. *Root = NULL;
  413. return;
  414. }
  415. //
  416. // Links as not children and is not the root, so to the parent's
  417. // child pointer to NULL.
  418. //
  419. ParentChildPtr = ParentsChildPointerAddress(Links);
  420. *ParentChildPtr = NULL;
  421. return;
  422. }
  423. //
  424. // otherwise Links has one child. If it is the root then make the child
  425. // the new root, otherwise link together the child and parent. But first
  426. // remember who our child is.
  427. //
  428. if (RtlLeftChild(Links) != NULL) {
  429. Child = RtlLeftChild(Links);
  430. } else {
  431. Child = RtlRightChild(Links);
  432. }
  433. //
  434. // If links is the root then we make the child the root and return the
  435. // child.
  436. //
  437. if (RtlIsRoot(Links)) {
  438. Child->Parent = Child;
  439. *Root = Child;
  440. return;
  441. }
  442. //
  443. // Links is not the root, so set link's parent child pointer to be
  444. // the child and the set child's parent to be link's parent.
  445. //
  446. ParentChildPtr = ParentsChildPointerAddress(Links);
  447. *ParentChildPtr = Child;
  448. Child->Parent = Links->Parent;
  449. return;
  450. }
  451. PRTL_SPLAY_LINKS
  452. RtlSubtreeSuccessor (
  453. IN PRTL_SPLAY_LINKS Links
  454. )
  455. /*++
  456. Routine Description:
  457. The SubtreeSuccessor function takes as input a pointer to a splay link
  458. in a tree and returns a pointer to the successor of the input node of
  459. the substree rooted at the input node. If there is not a successor, the
  460. return value is NULL.
  461. Arguments:
  462. Links - Supplies a pointer to a splay link in a tree.
  463. Return Value:
  464. PRTL_SPLAY_LINKS - returns a pointer to the successor in the subtree
  465. --*/
  466. {
  467. PRTL_SPLAY_LINKS Ptr;
  468. /*
  469. check to see if there is a right subtree to the input link
  470. if there is then the subtree successor is the left most node in
  471. the right subtree. That is find and return P in the following diagram
  472. Links
  473. \
  474. .
  475. .
  476. .
  477. /
  478. P
  479. \
  480. */
  481. if ((Ptr = RtlRightChild(Links)) != NULL) {
  482. while (RtlLeftChild(Ptr) != NULL) {
  483. Ptr = RtlLeftChild(Ptr);
  484. }
  485. return Ptr;
  486. }
  487. //
  488. // otherwise we are do not have a subtree successor so we simply return
  489. // NULL
  490. //
  491. return NULL;
  492. }
  493. #endif
  494. PRTL_SPLAY_LINKS
  495. pRtlSubtreePredecessor (
  496. IN PRTL_SPLAY_LINKS Links
  497. )
  498. /*++
  499. Routine Description:
  500. The SubtreePredecessor function takes as input a pointer to a splay link
  501. in a tree and returns a pointer to the predecessor of the input node of
  502. the substree rooted at the input node. If there is not a predecessor,
  503. the return value is NULL.
  504. Arguments:
  505. Links - Supplies a pointer to a splay link in a tree.
  506. Return Value:
  507. PRTL_SPLAY_LINKS - returns a pointer to the predecessor in the subtree
  508. --*/
  509. {
  510. PRTL_SPLAY_LINKS Ptr;
  511. //
  512. // check to see if there is a left subtree to the input link
  513. // if there is then the subtree predecessor is the right most node in
  514. // the left subtree. That is find and return P in the following diagram
  515. //
  516. // Links
  517. // /
  518. // .
  519. // .
  520. // .
  521. // P
  522. // /
  523. //
  524. if ((Ptr = RtlLeftChild(Links)) != NULL) {
  525. while (RtlRightChild(Ptr) != NULL) {
  526. Ptr = RtlRightChild(Ptr);
  527. }
  528. return Ptr;
  529. }
  530. //
  531. // otherwise we are do not have a subtree predecessor so we simply return
  532. // NULL
  533. //
  534. return NULL;
  535. }
  536. #if 0
  537. PRTL_SPLAY_LINKS
  538. RtlRealSuccessor (
  539. IN PRTL_SPLAY_LINKS Links
  540. )
  541. /*++
  542. Routine Description:
  543. The RealSuccessor function takes as input a pointer to a splay link
  544. in a tree and returns a pointer to the successor of the input node within
  545. the entire tree. If there is not a successor, the return value is NULL.
  546. Arguments:
  547. Links - Supplies a pointer to a splay link in a tree.
  548. Return Value:
  549. PRTL_SPLAY_LINKS - returns a pointer to the successor in the entire tree
  550. --*/
  551. {
  552. PRTL_SPLAY_LINKS Ptr;
  553. /*
  554. first check to see if there is a right subtree to the input link
  555. if there is then the real successor is the left most node in
  556. the right subtree. That is find and return P in the following diagram
  557. Links
  558. \
  559. .
  560. .
  561. .
  562. /
  563. P
  564. \
  565. */
  566. if ((Ptr = RtlRightChild(Links)) != NULL) {
  567. while (RtlLeftChild(Ptr) != NULL) {
  568. Ptr = RtlLeftChild(Ptr);
  569. }
  570. return Ptr;
  571. }
  572. /*
  573. we do not have a right child so check to see if have a parent and if
  574. so find the first ancestor that we are a left decendent of. That
  575. is find and return P in the following diagram
  576. P
  577. /
  578. .
  579. .
  580. .
  581. Links
  582. */
  583. Ptr = Links;
  584. while (RtlIsRightChild(Ptr)) {
  585. Ptr = RtlParent(Ptr);
  586. }
  587. if (RtlIsLeftChild(Ptr)) {
  588. return RtlParent(Ptr);
  589. }
  590. //
  591. // otherwise we are do not have a real successor so we simply return
  592. // NULL
  593. //
  594. return NULL;
  595. }
  596. PRTL_SPLAY_LINKS
  597. RtlRealPredecessor (
  598. IN PRTL_SPLAY_LINKS Links
  599. )
  600. /*++
  601. Routine Description:
  602. The RealPredecessor function takes as input a pointer to a splay link
  603. in a tree and returns a pointer to the predecessor of the input node
  604. within the entire tree. If there is not a predecessor, the return value
  605. is NULL.
  606. Arguments:
  607. Links - Supplies a pointer to a splay link in a tree.
  608. Return Value:
  609. PRTL_SPLAY_LINKS - returns a pointer to the predecessor in the entire tree
  610. --*/
  611. {
  612. PRTL_SPLAY_LINKS Ptr;
  613. /*
  614. first check to see if there is a left subtree to the input link
  615. if there is then the real predecessor is the right most node in
  616. the left subtree. That is find and return P in the following diagram
  617. Links
  618. /
  619. .
  620. .
  621. .
  622. P
  623. /
  624. */
  625. if ((Ptr = RtlLeftChild(Links)) != NULL) {
  626. while (RtlRightChild(Ptr) != NULL) {
  627. Ptr = RtlRightChild(Ptr);
  628. }
  629. return Ptr;
  630. }
  631. /*
  632. we do not have a left child so check to see if have a parent and if
  633. so find the first ancestor that we are a right decendent of. That
  634. is find and return P in the following diagram
  635. P
  636. \
  637. .
  638. .
  639. .
  640. Links
  641. */
  642. Ptr = Links;
  643. while (RtlIsLeftChild(Ptr)) {
  644. Ptr = RtlParent(Ptr);
  645. }
  646. if (RtlIsRightChild(Ptr)) {
  647. return RtlParent(Ptr);
  648. }
  649. //
  650. // otherwise we are do not have a real predecessor so we simply return
  651. // NULL
  652. //
  653. return NULL;
  654. }
  655. #endif
  656. VOID
  657. SwapSplayLinks (
  658. IN PRTL_SPLAY_LINKS Link1,
  659. IN PRTL_SPLAY_LINKS Link2
  660. )
  661. {
  662. PRTL_SPLAY_LINKS *Parent1ChildPtr;
  663. PRTL_SPLAY_LINKS *Parent2ChildPtr;
  664. /*
  665. We have the following situation
  666. Parent1 Parent2
  667. | |
  668. | |
  669. Link1 Link2
  670. / \ / \
  671. / \ / \
  672. LC1 RC1 LC2 RC2
  673. where one of the links can possibly be the root and one of the links
  674. can possibly be a direct child of the other. Without loss of
  675. generality we'll make link2 be the possible and root and link1 be
  676. the possible child.
  677. */
  678. if ((RtlIsRoot(Link1)) || (RtlParent(Link2) == Link1)) {
  679. SwapPointers(PRTL_SPLAY_LINKS, Link1, Link2);
  680. }
  681. //
  682. // The four cases we need to handle are
  683. //
  684. // 1. Link1 is not a child of link2 and link2 is not the root
  685. // 2. Link1 is not a child of link2 and link2 is the root
  686. // 3. Link1 is a child of link2 and link2 is not the root
  687. // 4. Link1 is a child of link2 and link2 is the root
  688. //
  689. //
  690. // Each case will be handled separately
  691. //
  692. if (RtlParent(Link1) != Link2) {
  693. if (!RtlIsRoot(Link2)) {
  694. //
  695. // Case 1 the initial steps are:
  696. //
  697. // 1. get both parent child pointers
  698. // 2. swap the parent child pointers
  699. // 3. swap the parent pointers
  700. //
  701. Parent1ChildPtr = ParentsChildPointerAddress(Link1);
  702. Parent2ChildPtr = ParentsChildPointerAddress(Link2);
  703. SwapPointers(PRTL_SPLAY_LINKS, *Parent1ChildPtr, *Parent2ChildPtr);
  704. SwapPointers(PRTL_SPLAY_LINKS, Link1->Parent, Link2->Parent);
  705. } else {
  706. //
  707. // Case 2 the initial steps are:
  708. //
  709. // 1. Set link1's parent child pointer to link2
  710. // 2. Set parent pointer of link2 to link1's parent
  711. // 3. Set parent pointer of link1 to be itself
  712. //
  713. Parent1ChildPtr = ParentsChildPointerAddress(Link1);
  714. *Parent1ChildPtr = Link2;
  715. Link2->Parent = Link1->Parent;
  716. Link1->Parent = Link1;
  717. }
  718. //
  719. // Case 1 and 2 common steps are:
  720. //
  721. // 1. swap the child pointers
  722. //
  723. SwapPointers(PRTL_SPLAY_LINKS, Link1->LeftChild, Link2->LeftChild);
  724. SwapPointers(PRTL_SPLAY_LINKS, Link1->RightChild, Link2->RightChild);
  725. } else { // RtlParent(Link1) == Link2
  726. if (!RtlIsRoot(Link2)) {
  727. //
  728. // Case 3 the initial steps are:
  729. //
  730. // 1. Set Link2's parent child pointer to link1
  731. // 2. Set Link1's parent pointer to parent of link2
  732. //
  733. Parent2ChildPtr = ParentsChildPointerAddress(Link2);
  734. *Parent2ChildPtr = Link1;
  735. Link1->Parent = Link2->Parent;
  736. } else {
  737. //
  738. // Case 4 the initial steps are:
  739. //
  740. // 1. Set Link1's parent pointer to be link1
  741. //
  742. Link1->Parent = Link1;
  743. }
  744. //
  745. // Case 3 and 4 common steps are:
  746. //
  747. // 1. Swap the child pointers
  748. // 2. if link1 was a left child (i.e., RtlLeftChild(Link1) == Link1)
  749. // then set left child of link1 to link2
  750. // else set right child of link1 to link2
  751. //
  752. SwapPointers(PRTL_SPLAY_LINKS, Link1->LeftChild, Link2->LeftChild);
  753. SwapPointers(PRTL_SPLAY_LINKS, Link1->RightChild, Link2->RightChild);
  754. if (Link1->LeftChild == Link1) {
  755. Link1->LeftChild = Link2;
  756. } else {
  757. Link1->RightChild = Link2;
  758. }
  759. }
  760. //
  761. // Case 1, 2, 3, 4 common (and final) steps are:
  762. //
  763. // 1. Fix the parent pointers of the left and right children
  764. //
  765. if (Link1->LeftChild != NULL) {Link1->LeftChild->Parent = Link1;}
  766. if (Link1->RightChild != NULL) {Link1->RightChild->Parent = Link1;}
  767. if (Link2->LeftChild != NULL) {Link2->LeftChild->Parent = Link2;}
  768. if (Link2->RightChild != NULL) {Link2->RightChild->Parent = Link2;}
  769. }