avl.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. lchild->height = lrheight;
  47. axis->height = lrheight;
  48. lchild->parent = lrchild;
  49. axis->parent = lrchild;
  50. if (lchild->avl_right != NULL)
  51. lchild->avl_right->parent = lchild;
  52. if (axis->avl_left != NULL)
  53. axis->avl_left->parent = axis;
  54. *nodeplace = lrchild;
  55. }
  56. static inline void rotate_left(struct util_avl_struct *axis,
  57. struct util_avl_struct *rchild,
  58. struct util_avl_struct *rlchild,
  59. struct util_avl_struct **nodeplace,
  60. size_t rlheight)
  61. {
  62. axis->avl_right = rlchild;
  63. rchild->avl_right = axis;
  64. axis->height = rlheight + 1;
  65. rchild->height = axis->height + 1;
  66. rchild->parent = axis->parent;
  67. axis->parent = rchild;
  68. *nodeplace = rchild;
  69. if (rlchild != NULL)
  70. rlchild->parent = axis;
  71. }
  72. static inline void midmount_left(struct util_avl_struct *axis,
  73. struct util_avl_struct *rchild,
  74. struct util_avl_struct *rlchild,
  75. struct util_avl_struct **nodeplace,
  76. size_t rlheight)
  77. {
  78. rchild->avl_left = rlchild->avl_right;
  79. axis->avl_right = rlchild->avl_left;
  80. rlchild->avl_right = rchild;
  81. rlchild->avl_left = axis;
  82. rchild->height = rlheight;
  83. axis->height = rlheight;
  84. rchild->parent = rlchild;
  85. axis->parent = rlchild;
  86. if (rchild->avl_left != NULL)
  87. rchild->avl_left->parent = rchild;
  88. if (axis->avl_right != NULL)
  89. axis->avl_right->parent = axis;
  90. *nodeplace = rlchild;
  91. }
  92. /**
  93. * @brief avl insertion & delete conceptually contain 2 stage
  94. * 1. insertion/delete of reference
  95. * 2. rebalance
  96. */
  97. void util_avl_rebalance(struct util_avl_struct *node,
  98. struct util_avl_root *root)
  99. {
  100. if (!node)
  101. return;
  102. struct util_avl_struct *axis = node;
  103. struct util_avl_struct **nodeplace;
  104. do
  105. {
  106. struct util_avl_struct *lchild = axis->avl_left;
  107. struct util_avl_struct *rchild = axis->avl_right;
  108. nodeplace = node->parent ? NODE_PLACE(axis) : &root->root_node;
  109. int lheight = HEIGHT_OF(lchild);
  110. int rheight = HEIGHT_OF(rchild);
  111. if (rheight + 1 < lheight)
  112. {
  113. struct util_avl_struct *lrchild = lchild->avl_right;
  114. size_t lrheight = HEIGHT_OF(lrchild);
  115. if (HEIGHT_OF(lchild->avl_left) >= lrheight)
  116. {
  117. rotate_right(axis, lchild, lrchild, nodeplace, lrheight);
  118. }
  119. else
  120. {
  121. midmount_right(axis, lchild, lrchild, nodeplace, lrheight);
  122. }
  123. }
  124. else if (lheight + 1 < rheight)
  125. {
  126. struct util_avl_struct *rlchild = rchild->avl_left;
  127. size_t rlheight = HEIGHT_OF(rlchild);
  128. if (HEIGHT_OF(rchild->avl_right) >= rlheight)
  129. {
  130. rotate_left(axis, rchild, rlchild, nodeplace, rlheight);
  131. }
  132. else
  133. {
  134. midmount_left(axis, rchild, rlchild, nodeplace, rlheight);
  135. }
  136. }
  137. else
  138. {
  139. int height = lheight < rheight ? rheight : lheight;
  140. if (height == axis->height)
  141. break;
  142. axis->height = height;
  143. }
  144. } while (nodeplace != &root->root_node);
  145. }
  146. void util_avl_remove(struct util_avl_struct *node, struct util_avl_root *root)
  147. {
  148. struct util_avl_struct **nodeplace;
  149. if (root->root_node == NULL)
  150. return;
  151. if (node->parent != NULL)
  152. {
  153. nodeplace = NODE_PLACE(node);
  154. }
  155. else
  156. {
  157. nodeplace = &root->root_node;
  158. }
  159. /* deletion */
  160. if (node->avl_right == NULL)
  161. {
  162. *nodeplace = node->avl_left;
  163. if (node->avl_left != NULL)
  164. node->avl_left->parent = node->parent;
  165. node = node->parent;
  166. }
  167. else
  168. {
  169. struct util_avl_struct *rchild = node->avl_right;
  170. if (rchild->avl_left == NULL)
  171. {
  172. *nodeplace = rchild;
  173. rchild->avl_left = node->avl_left;
  174. if (rchild->avl_left != NULL)
  175. rchild->avl_left->parent = node->parent;
  176. rchild->parent = node->parent;
  177. node = rchild;
  178. }
  179. else
  180. {
  181. struct util_avl_struct *successor = rchild->avl_left;
  182. struct util_avl_struct *sparent = rchild;
  183. while (successor->avl_left != NULL)
  184. {
  185. sparent = successor;
  186. successor = successor->avl_left;
  187. }
  188. *nodeplace = successor;
  189. sparent->avl_left = successor->avl_right;
  190. successor->avl_left = node->avl_left;
  191. successor->avl_right = node->avl_right;
  192. if (successor->avl_left != NULL)
  193. successor->avl_left->parent = successor;
  194. successor->avl_right->parent = successor;
  195. if (sparent->avl_left != NULL)
  196. sparent->avl_left->parent = sparent;
  197. successor->parent = node->parent;
  198. node = sparent;
  199. }
  200. }
  201. /* rebalance */
  202. util_avl_rebalance(node, root);
  203. return;
  204. }