avlmacro.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /* MACRO-CODED FAST FIXED AVL TREES IMPLEMENTATION IN C */
  2. /* COPYRIGHT (C) 1998 VALERY SHCHEDRIN */
  3. /* IT IS DISTRIBUTED UNDER GLPL (GNU GENERAL LIBRARY PUBLIC LICENSE) */
  4. /*
  5. * Manuel Novoa III Jan 2001
  6. *
  7. * Modified to decrease object size.
  8. * Tree balancing is now done in a fuction rather than inline.
  9. * Removed common code in balance by use of a goto.
  10. * Added macro Avl_Tree_no_replace since ptrs_replace was not used.
  11. * Prepended may symbols with "__" for possible conversion to extern.
  12. */
  13. #define __Avl_balance_proto(objname, pr, root) \
  14. static int __Avl_##objname##pr##balance(objname **root) \
  15. { \
  16. objname *p; \
  17. int ht_changed; \
  18. p = *root; \
  19. if (p->bal_##pr < -1) \
  20. { \
  21. if (p->l_##pr->bal_##pr == 1) \
  22. { \
  23. objname *pp; \
  24. pp=p->l_##pr; *root=p->l_##pr->r_##pr; p->l_##pr = (*root)->r_##pr; \
  25. (*root)->r_##pr = p; pp->r_##pr = (*root)->l_##pr; \
  26. p = *root; p->l_##pr = pp; \
  27. goto pr_common_ht_changed; \
  28. } \
  29. else \
  30. { \
  31. ht_changed = (p->l_##pr ->bal_##pr)?1:0; \
  32. *root = p->l_##pr ; \
  33. p->l_##pr = (*root)->r_##pr ; (*root)->r_##pr = p; \
  34. p->bal_##pr = - (++((*root)->bal_##pr )); \
  35. } \
  36. } \
  37. else if (p->bal_##pr > 1) \
  38. { \
  39. if (p->r_##pr->bal_##pr == -1) \
  40. { \
  41. objname *pp; \
  42. pp=p->r_##pr ; *root=p->r_##pr ->l_##pr ; p->r_##pr =(*root)->l_##pr ; \
  43. (*root)->l_##pr = p; pp->l_##pr = (*root)->r_##pr ; \
  44. p = *root; p->r_##pr = pp; \
  45. pr_common_ht_changed: \
  46. if (p->bal_##pr > 0) p->l_##pr ->bal_##pr = -p->bal_##pr ; \
  47. else p->l_##pr ->bal_##pr = 0; \
  48. if (p->bal_##pr < 0) p->r_##pr ->bal_##pr = -p->bal_##pr ; \
  49. else p->r_##pr ->bal_##pr = 0; \
  50. p->bal_##pr = 0; \
  51. ht_changed = 1; \
  52. } \
  53. else \
  54. { \
  55. ht_changed = (p->r_##pr ->bal_##pr)?1:0; \
  56. *root = p->r_##pr ; \
  57. p->r_##pr = (*root)->l_##pr ; (*root)->l_##pr = p; \
  58. p->bal_##pr = - (--((*root)->bal_##pr )); \
  59. } \
  60. } else ht_changed = 0; \
  61. return ht_changed; \
  62. }
  63. #define balance(objname, pr, root) \
  64. __Avl_##objname##pr##balance(root)
  65. #define __Avl_r_insert_proto(objname, pr, COMPARE) \
  66. static int __Avl_##objname##pr##_r_insert(objname **root) \
  67. { \
  68. int i; /* height increase */ \
  69. if (!*root) \
  70. { \
  71. *root = __Avl_##objname##pr##_new_node; \
  72. __Avl_##objname##pr##_new_node = NULL; \
  73. return 1; \
  74. } \
  75. COMPARE(i, __Avl_##objname##pr##_new_node, *root); \
  76. \
  77. if (i < 0) \
  78. { /* insert into the left subtree */ \
  79. i = -__Avl_##objname##pr##_r_insert(&((*root)->l_##pr)); \
  80. if (__Avl_##objname##pr##_new_node != NULL) return 0; /* already there */ \
  81. } \
  82. else if (i > 0) \
  83. { /* insert into the right subtree */ \
  84. i = __Avl_##objname##pr##_r_insert(&((*root)->r_##pr)); \
  85. if (__Avl_##objname##pr##_new_node != NULL) return 0; /* already there */ \
  86. } \
  87. else \
  88. { /* found */ \
  89. __Avl_##objname##pr##_new_node = *root; \
  90. return 0; \
  91. } \
  92. if (!i) return 0; \
  93. (*root)->bal_##pr += i; /* update balance factor */ \
  94. if ((*root)->bal_##pr) \
  95. { \
  96. return 1 - balance(objname,pr,root); \
  97. } \
  98. else return 0; \
  99. }
  100. #define __Avl_r_delete_proto(objname,pr,COMPARE) \
  101. static int __Avl_##objname##pr##_r_delete(objname **root) \
  102. { \
  103. int i; /* height decrease */ \
  104. \
  105. if (!*root) return 0; /* not found */ \
  106. \
  107. COMPARE(i, __Avl_##objname##pr##_new_node, *root); \
  108. \
  109. if (i < 0) \
  110. i = -__Avl_##objname##pr##_r_delete(&((*root)->l_##pr)); \
  111. else if (i > 0) \
  112. i = __Avl_##objname##pr##_r_delete(&((*root)->r_##pr)); \
  113. else \
  114. { \
  115. if (!(*root)->l_##pr) \
  116. { \
  117. *root = (*root)->r_##pr; \
  118. return 1; \
  119. } \
  120. else if (!(*root)->r_##pr) \
  121. { \
  122. *root = (*root)->l_##pr; \
  123. return 1; \
  124. } \
  125. else \
  126. { \
  127. i = __Avl_##objname##pr##_r_delfix(&((*root)->r_##pr)); \
  128. __Avl_##objname##pr##_new_node->l_##pr = (*root)->l_##pr; \
  129. __Avl_##objname##pr##_new_node->r_##pr = (*root)->r_##pr; \
  130. __Avl_##objname##pr##_new_node->bal_##pr = (*root)->bal_##pr; \
  131. *root = __Avl_##objname##pr##_new_node; \
  132. } \
  133. } \
  134. if (!i) return 0; \
  135. (*root)->bal_##pr -= i; \
  136. if ((*root)->bal_##pr) \
  137. { \
  138. return balance(objname,pr,root); \
  139. } \
  140. return 1; \
  141. }
  142. #define __Avl_r_delfix_proto(objname,pr) \
  143. static int __Avl_##objname##pr##_r_delfix(objname **root) \
  144. { \
  145. int i; /* height decrease */ \
  146. \
  147. if (!(*root)->l_##pr) \
  148. { \
  149. __Avl_##objname##pr##_new_node = *root; \
  150. *root = (*root)->r_##pr; \
  151. return 1; \
  152. } \
  153. i = -__Avl_##objname##pr##_r_delfix(&((*root)->l_##pr)); \
  154. if (!i) return 0; \
  155. (*root)->bal_##pr -= i; \
  156. if ((*root)->bal_##pr) \
  157. { \
  158. return balance(objname,pr,root); \
  159. } \
  160. return 1; \
  161. }
  162. #define __Avl_ins_proto(alias,objname,pr) \
  163. objname *__##alias##_ins(objname *data) \
  164. { \
  165. __Avl_##objname##pr##_new_node = data; \
  166. (data)->l_##pr = NULL; \
  167. (data)->r_##pr = NULL; \
  168. (data)->bal_##pr = 0; \
  169. __Avl_##objname##pr##_r_insert(&__Avl_##objname##pr##_tree); \
  170. if (__Avl_##objname##pr##_new_node) \
  171. return __Avl_##objname##pr##_new_node; \
  172. return NULL; \
  173. }
  174. #define __Avl_del_proto(alias,objname,pr) \
  175. void __##alias##_del(objname *data) \
  176. { \
  177. __Avl_##objname##pr##_new_node = data; \
  178. __Avl_##objname##pr##_r_delete(&__Avl_##objname##pr##_tree); \
  179. }
  180. #define __Avl_replace_proto(alias,objname,pr,COMPARE) \
  181. void __##alias##_replace(objname *data) \
  182. { \
  183. objname **p = &__Avl_##objname##pr##_tree; \
  184. int cmp; \
  185. while (*p) \
  186. { \
  187. COMPARE(cmp, data, *p); \
  188. if (cmp < 0) \
  189. p = &((*p)->l_##pr); \
  190. else if (cmp > 0) \
  191. p = &((*p)->r_##pr); \
  192. else \
  193. { \
  194. (data)->l_##pr = (*p)->l_##pr; \
  195. (data)->r_##pr = (*p)->r_##pr; \
  196. (data)->bal_##pr = (*p)->bal_##pr; \
  197. *p = data; \
  198. return; \
  199. } \
  200. } \
  201. }
  202. #define Avl_Root(objname,pr) __Avl_##objname##pr##_tree
  203. #define Avl_Tree_no_replace(alias,objname,pr,COMPARE) \
  204. objname *__Avl_##objname##pr##_tree = NULL; \
  205. static objname *__Avl_##objname##pr##_new_node; \
  206. __Avl_balance_proto(objname, pr, root) \
  207. __Avl_r_insert_proto(objname,pr,COMPARE) \
  208. __Avl_r_delfix_proto(objname,pr) \
  209. __Avl_r_delete_proto(objname,pr,COMPARE) \
  210. __Avl_ins_proto(alias,objname,pr) \
  211. __Avl_del_proto(alias,objname,pr)
  212. #define Avl_Tree(alias,objname,pr,COMPARE) \
  213. Avl_Tree_no_replace(alias,objname,pr,COMPARE) \
  214. __Avl_replace_proto(alias,objname,pr,COMPARE)