Source code of Windows XP (NT5)
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.

1074 lines
25 KiB

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