avl.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-10-12 Jesven first version
  9. * 2022-11-14 WangXiaoyao Optimize footprint and performance
  10. * Export as ADT for generic use case
  11. */
  12. #include <stddef.h>
  13. #include <stdint.h>
  14. #include "avl.h"
  15. #define HEIGHT_OF(node) ((node) ? (node)->height : 0)
  16. #define IS_RCHILD(node) (!((node) - ((node)->parent->avl_right)))
  17. #define IS_LCHILD(node) (!((node) - ((node)->parent->avl_left)))
  18. #define NODE_PLACE(node) \
  19. IS_LCHILD(node) ? &(node)->parent->avl_left : &(node)->parent->avl_right
  20. static inline void rotate_right(struct util_avl_struct *axis,
  21. struct util_avl_struct *lchild,
  22. struct util_avl_struct *lrchild,
  23. struct util_avl_struct **nodeplace,
  24. size_t lrheight)
  25. {
  26. axis->avl_left = lrchild;
  27. lchild->avl_right = axis;
  28. axis->height = lrheight + 1;
  29. lchild->height = axis->height + 1;
  30. lchild->parent = axis->parent;
  31. axis->parent = lchild;
  32. *nodeplace = lchild;
  33. if (lrchild != NULL)
  34. lrchild->parent = axis;
  35. }
  36. static inline void midmount_right(struct util_avl_struct *axis,
  37. struct util_avl_struct *lchild,
  38. struct util_avl_struct *lrchild,
  39. struct util_avl_struct **nodeplace,
  40. size_t lrheight)
  41. {
  42. lchild->avl_right = lrchild->avl_left;
  43. axis->avl_left = lrchild->avl_right;
  44. lrchild->avl_left = lchild;
  45. lrchild->avl_right = axis;
  46. lrchild->height = lchild->height;
  47. lchild->height = lrheight;
  48. axis->height = lrheight;
  49. lrchild->parent = axis->parent;
  50. lchild->parent = lrchild;
  51. axis->parent = lrchild;
  52. if (lchild->avl_right != NULL)
  53. lchild->avl_right->parent = lchild;
  54. if (axis->avl_left != NULL)
  55. axis->avl_left->parent = axis;
  56. *nodeplace = lrchild;
  57. }
  58. static inline void rotate_left(struct util_avl_struct *axis,
  59. struct util_avl_struct *rchild,
  60. struct util_avl_struct *rlchild,
  61. struct util_avl_struct **nodeplace,
  62. size_t rlheight)
  63. {
  64. axis->avl_right = rlchild;
  65. rchild->avl_left = axis;
  66. axis->height = rlheight + 1;
  67. rchild->height = axis->height + 1;
  68. rchild->parent = axis->parent;
  69. axis->parent = rchild;
  70. *nodeplace = rchild;
  71. if (rlchild != NULL)
  72. rlchild->parent = axis;
  73. }
  74. static inline void midmount_left(struct util_avl_struct *axis,
  75. struct util_avl_struct *rchild,
  76. struct util_avl_struct *rlchild,
  77. struct util_avl_struct **nodeplace,
  78. size_t rlheight)
  79. {
  80. rchild->avl_left = rlchild->avl_right;
  81. axis->avl_right = rlchild->avl_left;
  82. rlchild->avl_right = rchild;
  83. rlchild->avl_left = axis;
  84. rlchild->height = rchild->height;
  85. rchild->height = rlheight;
  86. axis->height = rlheight;
  87. rlchild->parent = axis->parent;
  88. rchild->parent = rlchild;
  89. axis->parent = rlchild;
  90. if (rchild->avl_left != NULL)
  91. rchild->avl_left->parent = rchild;
  92. if (axis->avl_right != NULL)
  93. axis->avl_right->parent = axis;
  94. *nodeplace = rlchild;
  95. }
  96. /**
  97. * @brief avl insertion & delete conceptually contain 2 stage
  98. * 1. insertion/delete of reference
  99. * 2. rebalance
  100. */
  101. void util_avl_rebalance(struct util_avl_struct *node,
  102. struct util_avl_root *root)
  103. {
  104. if (!node)
  105. return;
  106. struct util_avl_struct *axis = node;
  107. struct util_avl_struct **nodeplace;
  108. do
  109. {
  110. struct util_avl_struct *lchild = axis->avl_left;
  111. struct util_avl_struct *rchild = axis->avl_right;
  112. nodeplace = axis->parent ? NODE_PLACE(axis) : &root->root_node;
  113. int lheight = HEIGHT_OF(lchild);
  114. int rheight = HEIGHT_OF(rchild);
  115. if (rheight + 1 < lheight)
  116. {
  117. struct util_avl_struct *lrchild = lchild->avl_right;
  118. size_t lrheight = HEIGHT_OF(lrchild);
  119. if (HEIGHT_OF(lchild->avl_left) >= lrheight)
  120. {
  121. rotate_right(axis, lchild, lrchild, nodeplace, lrheight);
  122. axis = lchild->parent;
  123. }
  124. else
  125. {
  126. midmount_right(axis, lchild, lrchild, nodeplace, lrheight);
  127. axis = lrchild->parent;
  128. }
  129. }
  130. else if (lheight + 1 < rheight)
  131. {
  132. struct util_avl_struct *rlchild = rchild->avl_left;
  133. size_t rlheight = HEIGHT_OF(rlchild);
  134. if (HEIGHT_OF(rchild->avl_right) >= rlheight)
  135. {
  136. rotate_left(axis, rchild, rlchild, nodeplace, rlheight);
  137. axis = rchild->parent;
  138. }
  139. else
  140. {
  141. midmount_left(axis, rchild, rlchild, nodeplace, rlheight);
  142. axis = rlchild->parent;
  143. }
  144. }
  145. else
  146. {
  147. int height = (lheight < rheight ? rheight : lheight) + 1;
  148. if (height == axis->height)
  149. break;
  150. axis->height = height;
  151. axis = axis->parent;
  152. }
  153. } while (axis);
  154. }
  155. void util_avl_remove(struct util_avl_struct *node, struct util_avl_root *root)
  156. {
  157. struct util_avl_struct **nodeplace;
  158. if (root->root_node == NULL)
  159. return;
  160. if (node->parent != NULL)
  161. {
  162. nodeplace = NODE_PLACE(node);
  163. }
  164. else
  165. {
  166. nodeplace = &root->root_node;
  167. }
  168. /* deletion */
  169. if (node->avl_right == NULL)
  170. {
  171. *nodeplace = node->avl_left;
  172. if (node->avl_left != NULL)
  173. node->avl_left->parent = node->parent;
  174. node = node->parent;
  175. }
  176. else
  177. {
  178. struct util_avl_struct *rchild = node->avl_right;
  179. if (rchild->avl_left == NULL)
  180. {
  181. *nodeplace = rchild;
  182. rchild->avl_left = node->avl_left;
  183. if (rchild->avl_left != NULL)
  184. rchild->avl_left->parent = rchild;
  185. rchild->parent = node->parent;
  186. util_avl_rebalance(rchild, root);
  187. node = rchild->parent;
  188. }
  189. else
  190. {
  191. struct util_avl_struct *successor = rchild->avl_left;
  192. struct util_avl_struct *sparent = rchild;
  193. while (successor->avl_left != NULL)
  194. {
  195. sparent = successor;
  196. successor = successor->avl_left;
  197. }
  198. *nodeplace = successor;
  199. sparent->avl_left = successor->avl_right;
  200. successor->avl_left = node->avl_left;
  201. successor->avl_right = node->avl_right;
  202. if (successor->avl_left != NULL)
  203. successor->avl_left->parent = successor;
  204. successor->avl_right->parent = successor;
  205. if (sparent->avl_left != NULL)
  206. sparent->avl_left->parent = sparent;
  207. successor->parent = node->parent;
  208. util_avl_rebalance(sparent, root);
  209. node = successor;
  210. }
  211. }
  212. /* rebalance */
  213. util_avl_rebalance(node, root);
  214. return;
  215. }