A Python parser for MediaWiki wikicode https://mwparserfromhell.readthedocs.io/
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.
 
 
 
 

790 lines
23 KiB

  1. /*
  2. * avl_tree.c - intrusive, nonrecursive AVL tree data structure (self-balancing
  3. * binary search tree), implementation file
  4. *
  5. * Written in 2014-2016 by Eric Biggers <ebiggers3@gmail.com>
  6. *
  7. * To the extent possible under law, the author(s) have dedicated all copyright
  8. * and related and neighboring rights to this software to the public domain
  9. * worldwide via the Creative Commons Zero 1.0 Universal Public Domain
  10. * Dedication (the "CC0").
  11. *
  12. * This software is distributed in the hope that it will be useful, but WITHOUT
  13. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  14. * FOR A PARTICULAR PURPOSE. See the CC0 for more details.
  15. *
  16. * You should have received a copy of the CC0 along with this software; if not
  17. * see <http://creativecommons.org/publicdomain/zero/1.0/>.
  18. */
  19. #include "avl_tree.h"
  20. /* Returns the left child (sign < 0) or the right child (sign > 0) of the
  21. * specified AVL tree node.
  22. * Note: for all calls of this, 'sign' is constant at compilation time,
  23. * so the compiler can remove the conditional. */
  24. static AVL_INLINE struct avl_tree_node *
  25. avl_get_child(const struct avl_tree_node *parent, int sign)
  26. {
  27. if (sign < 0)
  28. return parent->left;
  29. else
  30. return parent->right;
  31. }
  32. static AVL_INLINE struct avl_tree_node *
  33. avl_tree_first_or_last_in_order(const struct avl_tree_node *root, int sign)
  34. {
  35. const struct avl_tree_node *first = root;
  36. if (first)
  37. while (avl_get_child(first, +sign))
  38. first = avl_get_child(first, +sign);
  39. return (struct avl_tree_node *)first;
  40. }
  41. /* Starts an in-order traversal of the tree: returns the least-valued node, or
  42. * NULL if the tree is empty. */
  43. struct avl_tree_node *
  44. avl_tree_first_in_order(const struct avl_tree_node *root)
  45. {
  46. return avl_tree_first_or_last_in_order(root, -1);
  47. }
  48. /* Starts a *reverse* in-order traversal of the tree: returns the
  49. * greatest-valued node, or NULL if the tree is empty. */
  50. struct avl_tree_node *
  51. avl_tree_last_in_order(const struct avl_tree_node *root)
  52. {
  53. return avl_tree_first_or_last_in_order(root, 1);
  54. }
  55. static AVL_INLINE struct avl_tree_node *
  56. avl_tree_next_or_prev_in_order(const struct avl_tree_node *node, int sign)
  57. {
  58. const struct avl_tree_node *next;
  59. if (avl_get_child(node, +sign))
  60. for (next = avl_get_child(node, +sign);
  61. avl_get_child(next, -sign);
  62. next = avl_get_child(next, -sign))
  63. ;
  64. else
  65. for (next = avl_get_parent(node);
  66. next && node == avl_get_child(next, +sign);
  67. node = next, next = avl_get_parent(next))
  68. ;
  69. return (struct avl_tree_node *)next;
  70. }
  71. /* Continues an in-order traversal of the tree: returns the next-greatest-valued
  72. * node, or NULL if there is none. */
  73. struct avl_tree_node *
  74. avl_tree_next_in_order(const struct avl_tree_node *node)
  75. {
  76. return avl_tree_next_or_prev_in_order(node, 1);
  77. }
  78. /* Continues a *reverse* in-order traversal of the tree: returns the
  79. * previous-greatest-valued node, or NULL if there is none. */
  80. struct avl_tree_node *
  81. avl_tree_prev_in_order(const struct avl_tree_node *node)
  82. {
  83. return avl_tree_next_or_prev_in_order(node, -1);
  84. }
  85. /* Starts a postorder traversal of the tree. */
  86. struct avl_tree_node *
  87. avl_tree_first_in_postorder(const struct avl_tree_node *root)
  88. {
  89. const struct avl_tree_node *first = root;
  90. if (first)
  91. while (first->left || first->right)
  92. first = first->left ? first->left : first->right;
  93. return (struct avl_tree_node *)first;
  94. }
  95. /* Continues a postorder traversal of the tree. @prev will not be deferenced as
  96. * it's allowed that its memory has been freed; @prev_parent must be its saved
  97. * parent node. Returns NULL if there are no more nodes (i.e. @prev was the
  98. * root of the tree). */
  99. struct avl_tree_node *
  100. avl_tree_next_in_postorder(const struct avl_tree_node *prev,
  101. const struct avl_tree_node *prev_parent)
  102. {
  103. const struct avl_tree_node *next = prev_parent;
  104. if (next && prev == next->left && next->right)
  105. for (next = next->right;
  106. next->left || next->right;
  107. next = next->left ? next->left : next->right)
  108. ;
  109. return (struct avl_tree_node *)next;
  110. }
  111. /* Sets the left child (sign < 0) or the right child (sign > 0) of the
  112. * specified AVL tree node.
  113. * Note: for all calls of this, 'sign' is constant at compilation time,
  114. * so the compiler can remove the conditional. */
  115. static AVL_INLINE void
  116. avl_set_child(struct avl_tree_node *parent, int sign,
  117. struct avl_tree_node *child)
  118. {
  119. if (sign < 0)
  120. parent->left = child;
  121. else
  122. parent->right = child;
  123. }
  124. /* Sets the parent and balance factor of the specified AVL tree node. */
  125. static AVL_INLINE void
  126. avl_set_parent_balance(struct avl_tree_node *node, struct avl_tree_node *parent,
  127. int balance_factor)
  128. {
  129. node->parent_balance = (uintptr_t)parent | (balance_factor + 1);
  130. }
  131. /* Sets the parent of the specified AVL tree node. */
  132. static AVL_INLINE void
  133. avl_set_parent(struct avl_tree_node *node, struct avl_tree_node *parent)
  134. {
  135. node->parent_balance = (uintptr_t)parent | (node->parent_balance & 3);
  136. }
  137. /* Returns the balance factor of the specified AVL tree node --- that is, the
  138. * height of its right subtree minus the height of its left subtree. */
  139. static AVL_INLINE int
  140. avl_get_balance_factor(const struct avl_tree_node *node)
  141. {
  142. return (int)(node->parent_balance & 3) - 1;
  143. }
  144. /* Adds @amount to the balance factor of the specified AVL tree node.
  145. * The caller must ensure this still results in a valid balance factor
  146. * (-1, 0, or 1). */
  147. static AVL_INLINE void
  148. avl_adjust_balance_factor(struct avl_tree_node *node, int amount)
  149. {
  150. node->parent_balance += amount;
  151. }
  152. static AVL_INLINE void
  153. avl_replace_child(struct avl_tree_node **root_ptr,
  154. struct avl_tree_node *parent,
  155. struct avl_tree_node *old_child,
  156. struct avl_tree_node *new_child)
  157. {
  158. if (parent) {
  159. if (old_child == parent->left)
  160. parent->left = new_child;
  161. else
  162. parent->right = new_child;
  163. } else {
  164. *root_ptr = new_child;
  165. }
  166. }
  167. /*
  168. * Template for performing a single rotation ---
  169. *
  170. * sign > 0: Rotate clockwise (right) rooted at A:
  171. *
  172. * P? P?
  173. * | |
  174. * A B
  175. * / \ / \
  176. * B C? => D? A
  177. * / \ / \
  178. * D? E? E? C?
  179. *
  180. * (nodes marked with ? may not exist)
  181. *
  182. * sign < 0: Rotate counterclockwise (left) rooted at A:
  183. *
  184. * P? P?
  185. * | |
  186. * A B
  187. * / \ / \
  188. * C? B => A D?
  189. * / \ / \
  190. * E? D? C? E?
  191. *
  192. * This updates pointers but not balance factors!
  193. */
  194. static AVL_INLINE void
  195. avl_rotate(struct avl_tree_node ** const root_ptr,
  196. struct avl_tree_node * const A, const int sign)
  197. {
  198. struct avl_tree_node * const B = avl_get_child(A, -sign);
  199. struct avl_tree_node * const E = avl_get_child(B, +sign);
  200. struct avl_tree_node * const P = avl_get_parent(A);
  201. avl_set_child(A, -sign, E);
  202. avl_set_parent(A, B);
  203. avl_set_child(B, +sign, A);
  204. avl_set_parent(B, P);
  205. if (E)
  206. avl_set_parent(E, A);
  207. avl_replace_child(root_ptr, P, A, B);
  208. }
  209. /*
  210. * Template for performing a double rotation ---
  211. *
  212. * sign > 0: Rotate counterclockwise (left) rooted at B, then
  213. * clockwise (right) rooted at A:
  214. *
  215. * P? P? P?
  216. * | | |
  217. * A A E
  218. * / \ / \ / \
  219. * B C? => E C? => B A
  220. * / \ / \ / \ / \
  221. * D? E B G? D? F?G? C?
  222. * / \ / \
  223. * F? G? D? F?
  224. *
  225. * (nodes marked with ? may not exist)
  226. *
  227. * sign < 0: Rotate clockwise (right) rooted at B, then
  228. * counterclockwise (left) rooted at A:
  229. *
  230. * P? P? P?
  231. * | | |
  232. * A A E
  233. * / \ / \ / \
  234. * C? B => C? E => A B
  235. * / \ / \ / \ / \
  236. * E D? G? B C? G?F? D?
  237. * / \ / \
  238. * G? F? F? D?
  239. *
  240. * Returns a pointer to E and updates balance factors. Except for those
  241. * two things, this function is equivalent to:
  242. * avl_rotate(root_ptr, B, -sign);
  243. * avl_rotate(root_ptr, A, +sign);
  244. *
  245. * See comment in avl_handle_subtree_growth() for explanation of balance
  246. * factor updates.
  247. */
  248. static AVL_INLINE struct avl_tree_node *
  249. avl_do_double_rotate(struct avl_tree_node ** const root_ptr,
  250. struct avl_tree_node * const B,
  251. struct avl_tree_node * const A, const int sign)
  252. {
  253. struct avl_tree_node * const E = avl_get_child(B, +sign);
  254. struct avl_tree_node * const F = avl_get_child(E, -sign);
  255. struct avl_tree_node * const G = avl_get_child(E, +sign);
  256. struct avl_tree_node * const P = avl_get_parent(A);
  257. const int e = avl_get_balance_factor(E);
  258. avl_set_child(A, -sign, G);
  259. avl_set_parent_balance(A, E, ((sign * e >= 0) ? 0 : -e));
  260. avl_set_child(B, +sign, F);
  261. avl_set_parent_balance(B, E, ((sign * e <= 0) ? 0 : -e));
  262. avl_set_child(E, +sign, A);
  263. avl_set_child(E, -sign, B);
  264. avl_set_parent_balance(E, P, 0);
  265. if (G)
  266. avl_set_parent(G, A);
  267. if (F)
  268. avl_set_parent(F, B);
  269. avl_replace_child(root_ptr, P, A, E);
  270. return E;
  271. }
  272. /*
  273. * This function handles the growth of a subtree due to an insertion.
  274. *
  275. * @root_ptr
  276. * Location of the tree's root pointer.
  277. *
  278. * @node
  279. * A subtree that has increased in height by 1 due to an insertion.
  280. *
  281. * @parent
  282. * Parent of @node; must not be NULL.
  283. *
  284. * @sign
  285. * -1 if @node is the left child of @parent;
  286. * +1 if @node is the right child of @parent.
  287. *
  288. * This function will adjust @parent's balance factor, then do a (single
  289. * or double) rotation if necessary. The return value will be %true if
  290. * the full AVL tree is now adequately balanced, or %false if the subtree
  291. * rooted at @parent is now adequately balanced but has increased in
  292. * height by 1, so the caller should continue up the tree.
  293. *
  294. * Note that if %false is returned, no rotation will have been done.
  295. * Indeed, a single node insertion cannot require that more than one
  296. * (single or double) rotation be done.
  297. */
  298. static AVL_INLINE bool
  299. avl_handle_subtree_growth(struct avl_tree_node ** const root_ptr,
  300. struct avl_tree_node * const node,
  301. struct avl_tree_node * const parent,
  302. const int sign)
  303. {
  304. int old_balance_factor, new_balance_factor;
  305. old_balance_factor = avl_get_balance_factor(parent);
  306. if (old_balance_factor == 0) {
  307. avl_adjust_balance_factor(parent, sign);
  308. /* @parent is still sufficiently balanced (-1 or +1
  309. * balance factor), but must have increased in height.
  310. * Continue up the tree. */
  311. return false;
  312. }
  313. new_balance_factor = old_balance_factor + sign;
  314. if (new_balance_factor == 0) {
  315. avl_adjust_balance_factor(parent, sign);
  316. /* @parent is now perfectly balanced (0 balance factor).
  317. * It cannot have increased in height, so there is
  318. * nothing more to do. */
  319. return true;
  320. }
  321. /* @parent is too left-heavy (new_balance_factor == -2) or
  322. * too right-heavy (new_balance_factor == +2). */
  323. /* Test whether @node is left-heavy (-1 balance factor) or
  324. * right-heavy (+1 balance factor).
  325. * Note that it cannot be perfectly balanced (0 balance factor)
  326. * because here we are under the invariant that @node has
  327. * increased in height due to the insertion. */
  328. if (sign * avl_get_balance_factor(node) > 0) {
  329. /* @node (B below) is heavy in the same direction @parent
  330. * (A below) is heavy.
  331. *
  332. * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  333. * The comment, diagram, and equations below assume sign < 0.
  334. * The other case is symmetric!
  335. * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  336. *
  337. * Do a clockwise rotation rooted at @parent (A below):
  338. *
  339. * A B
  340. * / \ / \
  341. * B C? => D A
  342. * / \ / \ / \
  343. * D E? F? G?E? C?
  344. * / \
  345. * F? G?
  346. *
  347. * Before the rotation:
  348. * balance(A) = -2
  349. * balance(B) = -1
  350. * Let x = height(C). Then:
  351. * height(B) = x + 2
  352. * height(D) = x + 1
  353. * height(E) = x
  354. * max(height(F), height(G)) = x.
  355. *
  356. * After the rotation:
  357. * height(D) = max(height(F), height(G)) + 1
  358. * = x + 1
  359. * height(A) = max(height(E), height(C)) + 1
  360. * = max(x, x) + 1 = x + 1
  361. * balance(B) = 0
  362. * balance(A) = 0
  363. */
  364. avl_rotate(root_ptr, parent, -sign);
  365. /* Equivalent to setting @parent's balance factor to 0. */
  366. avl_adjust_balance_factor(parent, -sign); /* A */
  367. /* Equivalent to setting @node's balance factor to 0. */
  368. avl_adjust_balance_factor(node, -sign); /* B */
  369. } else {
  370. /* @node (B below) is heavy in the direction opposite
  371. * from the direction @parent (A below) is heavy.
  372. *
  373. * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  374. * The comment, diagram, and equations below assume sign < 0.
  375. * The other case is symmetric!
  376. * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  377. *
  378. * Do a counterblockwise rotation rooted at @node (B below),
  379. * then a clockwise rotation rooted at @parent (A below):
  380. *
  381. * A A E
  382. * / \ / \ / \
  383. * B C? => E C? => B A
  384. * / \ / \ / \ / \
  385. * D? E B G? D? F?G? C?
  386. * / \ / \
  387. * F? G? D? F?
  388. *
  389. * Before the rotation:
  390. * balance(A) = -2
  391. * balance(B) = +1
  392. * Let x = height(C). Then:
  393. * height(B) = x + 2
  394. * height(E) = x + 1
  395. * height(D) = x
  396. * max(height(F), height(G)) = x
  397. *
  398. * After both rotations:
  399. * height(A) = max(height(G), height(C)) + 1
  400. * = x + 1
  401. * balance(A) = balance(E{orig}) >= 0 ? 0 : -balance(E{orig})
  402. * height(B) = max(height(D), height(F)) + 1
  403. * = x + 1
  404. * balance(B) = balance(E{orig} <= 0) ? 0 : -balance(E{orig})
  405. *
  406. * height(E) = x + 2
  407. * balance(E) = 0
  408. */
  409. avl_do_double_rotate(root_ptr, node, parent, -sign);
  410. }
  411. /* Height after rotation is unchanged; nothing more to do. */
  412. return true;
  413. }
  414. /* Rebalance the tree after insertion of the specified node. */
  415. void
  416. avl_tree_rebalance_after_insert(struct avl_tree_node **root_ptr,
  417. struct avl_tree_node *inserted)
  418. {
  419. struct avl_tree_node *node, *parent;
  420. bool done;
  421. inserted->left = NULL;
  422. inserted->right = NULL;
  423. node = inserted;
  424. /* Adjust balance factor of new node's parent.
  425. * No rotation will need to be done at this level. */
  426. parent = avl_get_parent(node);
  427. if (!parent)
  428. return;
  429. if (node == parent->left)
  430. avl_adjust_balance_factor(parent, -1);
  431. else
  432. avl_adjust_balance_factor(parent, +1);
  433. if (avl_get_balance_factor(parent) == 0)
  434. /* @parent did not change in height. Nothing more to do. */
  435. return;
  436. /* The subtree rooted at @parent increased in height by 1. */
  437. do {
  438. /* Adjust balance factor of next ancestor. */
  439. node = parent;
  440. parent = avl_get_parent(node);
  441. if (!parent)
  442. return;
  443. /* The subtree rooted at @node has increased in height by 1. */
  444. if (node == parent->left)
  445. done = avl_handle_subtree_growth(root_ptr, node,
  446. parent, -1);
  447. else
  448. done = avl_handle_subtree_growth(root_ptr, node,
  449. parent, +1);
  450. } while (!done);
  451. }
  452. /*
  453. * This function handles the shrinkage of a subtree due to a deletion.
  454. *
  455. * @root_ptr
  456. * Location of the tree's root pointer.
  457. *
  458. * @parent
  459. * A node in the tree, exactly one of whose subtrees has decreased
  460. * in height by 1 due to a deletion. (This includes the case where
  461. * one of the child pointers has become NULL, since we can consider
  462. * the "NULL" subtree to have a height of 0.)
  463. *
  464. * @sign
  465. * +1 if the left subtree of @parent has decreased in height by 1;
  466. * -1 if the right subtree of @parent has decreased in height by 1.
  467. *
  468. * @left_deleted_ret
  469. * If the return value is not NULL, this will be set to %true if the
  470. * left subtree of the returned node has decreased in height by 1,
  471. * or %false if the right subtree of the returned node has decreased
  472. * in height by 1.
  473. *
  474. * This function will adjust @parent's balance factor, then do a (single
  475. * or double) rotation if necessary. The return value will be NULL if
  476. * the full AVL tree is now adequately balanced, or a pointer to the
  477. * parent of @parent if @parent is now adequately balanced but has
  478. * decreased in height by 1. Also in the latter case, *left_deleted_ret
  479. * will be set.
  480. */
  481. static AVL_INLINE struct avl_tree_node *
  482. avl_handle_subtree_shrink(struct avl_tree_node ** const root_ptr,
  483. struct avl_tree_node *parent,
  484. const int sign,
  485. bool * const left_deleted_ret)
  486. {
  487. struct avl_tree_node *node;
  488. int old_balance_factor, new_balance_factor;
  489. old_balance_factor = avl_get_balance_factor(parent);
  490. if (old_balance_factor == 0) {
  491. /* Prior to the deletion, the subtree rooted at
  492. * @parent was perfectly balanced. It's now
  493. * unbalanced by 1, but that's okay and its height
  494. * hasn't changed. Nothing more to do. */
  495. avl_adjust_balance_factor(parent, sign);
  496. return NULL;
  497. }
  498. new_balance_factor = old_balance_factor + sign;
  499. if (new_balance_factor == 0) {
  500. /* The subtree rooted at @parent is now perfectly
  501. * balanced, whereas before the deletion it was
  502. * unbalanced by 1. Its height must have decreased
  503. * by 1. No rotation is needed at this location,
  504. * but continue up the tree. */
  505. avl_adjust_balance_factor(parent, sign);
  506. node = parent;
  507. } else {
  508. /* @parent is too left-heavy (new_balance_factor == -2) or
  509. * too right-heavy (new_balance_factor == +2). */
  510. node = avl_get_child(parent, sign);
  511. /* The rotations below are similar to those done during
  512. * insertion (see avl_handle_subtree_growth()), so full
  513. * comments are not provided. The only new case is the
  514. * one where @node has a balance factor of 0, and that is
  515. * commented. */
  516. if (sign * avl_get_balance_factor(node) >= 0) {
  517. avl_rotate(root_ptr, parent, -sign);
  518. if (avl_get_balance_factor(node) == 0) {
  519. /*
  520. * @node (B below) is perfectly balanced.
  521. *
  522. * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  523. * The comment, diagram, and equations
  524. * below assume sign < 0. The other case
  525. * is symmetric!
  526. * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  527. *
  528. * Do a clockwise rotation rooted at
  529. * @parent (A below):
  530. *
  531. * A B
  532. * / \ / \
  533. * B C? => D A
  534. * / \ / \ / \
  535. * D E F? G?E C?
  536. * / \
  537. * F? G?
  538. *
  539. * Before the rotation:
  540. * balance(A) = -2
  541. * balance(B) = 0
  542. * Let x = height(C). Then:
  543. * height(B) = x + 2
  544. * height(D) = x + 1
  545. * height(E) = x + 1
  546. * max(height(F), height(G)) = x.
  547. *
  548. * After the rotation:
  549. * height(D) = max(height(F), height(G)) + 1
  550. * = x + 1
  551. * height(A) = max(height(E), height(C)) + 1
  552. * = max(x + 1, x) + 1 = x + 2
  553. * balance(A) = -1
  554. * balance(B) = +1
  555. */
  556. /* A: -2 => -1 (sign < 0)
  557. * or +2 => +1 (sign > 0)
  558. * No change needed --- that's the same as
  559. * old_balance_factor. */
  560. /* B: 0 => +1 (sign < 0)
  561. * or 0 => -1 (sign > 0) */
  562. avl_adjust_balance_factor(node, -sign);
  563. /* Height is unchanged; nothing more to do. */
  564. return NULL;
  565. } else {
  566. avl_adjust_balance_factor(parent, -sign);
  567. avl_adjust_balance_factor(node, -sign);
  568. }
  569. } else {
  570. node = avl_do_double_rotate(root_ptr, node,
  571. parent, -sign);
  572. }
  573. }
  574. parent = avl_get_parent(node);
  575. if (parent)
  576. *left_deleted_ret = (node == parent->left);
  577. return parent;
  578. }
  579. /* Swaps node X, which must have 2 children, with its in-order successor, then
  580. * unlinks node X. Returns the parent of X just before unlinking, without its
  581. * balance factor having been updated to account for the unlink. */
  582. static AVL_INLINE struct avl_tree_node *
  583. avl_tree_swap_with_successor(struct avl_tree_node **root_ptr,
  584. struct avl_tree_node *X,
  585. bool *left_deleted_ret)
  586. {
  587. struct avl_tree_node *Y, *ret;
  588. Y = X->right;
  589. if (!Y->left) {
  590. /*
  591. * P? P? P?
  592. * | | |
  593. * X Y Y
  594. * / \ / \ / \
  595. * A Y => A X => A B?
  596. * / \ / \
  597. * (0) B? (0) B?
  598. *
  599. * [ X unlinked, Y returned ]
  600. */
  601. ret = Y;
  602. *left_deleted_ret = false;
  603. } else {
  604. struct avl_tree_node *Q;
  605. do {
  606. Q = Y;
  607. Y = Y->left;
  608. } while (Y->left);
  609. /*
  610. * P? P? P?
  611. * | | |
  612. * X Y Y
  613. * / \ / \ / \
  614. * A ... => A ... => A ...
  615. * | | |
  616. * Q Q Q
  617. * / / /
  618. * Y X B?
  619. * / \ / \
  620. * (0) B? (0) B?
  621. *
  622. *
  623. * [ X unlinked, Q returned ]
  624. */
  625. Q->left = Y->right;
  626. if (Q->left)
  627. avl_set_parent(Q->left, Q);
  628. Y->right = X->right;
  629. avl_set_parent(X->right, Y);
  630. ret = Q;
  631. *left_deleted_ret = true;
  632. }
  633. Y->left = X->left;
  634. avl_set_parent(X->left, Y);
  635. Y->parent_balance = X->parent_balance;
  636. avl_replace_child(root_ptr, avl_get_parent(X), X, Y);
  637. return ret;
  638. }
  639. /*
  640. * Removes an item from the specified AVL tree.
  641. *
  642. * @root_ptr
  643. * Location of the AVL tree's root pointer. Indirection is needed
  644. * because the root node may change if the tree needed to be rebalanced
  645. * because of the deletion or if @node was the root node.
  646. *
  647. * @node
  648. * Pointer to the `struct avl_tree_node' embedded in the item to
  649. * remove from the tree.
  650. *
  651. * Note: This function *only* removes the node and rebalances the tree.
  652. * It does not free any memory, nor does it do the equivalent of
  653. * avl_tree_node_set_unlinked().
  654. */
  655. void
  656. avl_tree_remove(struct avl_tree_node **root_ptr, struct avl_tree_node *node)
  657. {
  658. struct avl_tree_node *parent;
  659. bool left_deleted = false;
  660. if (node->left && node->right) {
  661. /* @node is fully internal, with two children. Swap it
  662. * with its in-order successor (which must exist in the
  663. * right subtree of @node and can have, at most, a right
  664. * child), then unlink @node. */
  665. parent = avl_tree_swap_with_successor(root_ptr, node,
  666. &left_deleted);
  667. /* @parent is now the parent of what was @node's in-order
  668. * successor. It cannot be NULL, since @node itself was
  669. * an ancestor of its in-order successor.
  670. * @left_deleted has been set to %true if @node's
  671. * in-order successor was the left child of @parent,
  672. * otherwise %false. */
  673. } else {
  674. struct avl_tree_node *child;
  675. /* @node is missing at least one child. Unlink it. Set
  676. * @parent to @node's parent, and set @left_deleted to
  677. * reflect which child of @parent @node was. Or, if
  678. * @node was the root node, simply update the root node
  679. * and return. */
  680. child = node->left ? node->left : node->right;
  681. parent = avl_get_parent(node);
  682. if (parent) {
  683. if (node == parent->left) {
  684. parent->left = child;
  685. left_deleted = true;
  686. } else {
  687. parent->right = child;
  688. left_deleted = false;
  689. }
  690. if (child)
  691. avl_set_parent(child, parent);
  692. } else {
  693. if (child)
  694. avl_set_parent(child, parent);
  695. *root_ptr = child;
  696. return;
  697. }
  698. }
  699. /* Rebalance the tree. */
  700. do {
  701. if (left_deleted)
  702. parent = avl_handle_subtree_shrink(root_ptr, parent,
  703. +1, &left_deleted);
  704. else
  705. parent = avl_handle_subtree_shrink(root_ptr, parent,
  706. -1, &left_deleted);
  707. } while (parent);
  708. }