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.
 
 
 
 

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