avlmacro.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. #define balance(objname, pr, root, ht_changed) \
  5. { \
  6. objname *p; \
  7. p = *root; \
  8. if (p->bal_##pr < -1) \
  9. { \
  10. if (p->l_##pr->bal_##pr == 1) \
  11. { \
  12. objname *pp; \
  13. pp=p->l_##pr; *root=p->l_##pr->r_##pr; p->l_##pr = (*root)->r_##pr; \
  14. (*root)->r_##pr = p; pp->r_##pr = (*root)->l_##pr; \
  15. p = *root; p->l_##pr = pp; \
  16. if (p->bal_##pr > 0) p->l_##pr ->bal_##pr = -p->bal_##pr ; \
  17. else p->l_##pr ->bal_##pr = 0; \
  18. if (p->bal_##pr < 0) p->r_##pr ->bal_##pr = -p->bal_##pr ; \
  19. else p->r_##pr ->bal_##pr = 0; \
  20. p->bal_##pr = 0; \
  21. ht_changed = 1; \
  22. } \
  23. else \
  24. { \
  25. ht_changed = (p->l_##pr ->bal_##pr)?1:0; \
  26. *root = p->l_##pr ; \
  27. p->l_##pr = (*root)->r_##pr ; (*root)->r_##pr = p; \
  28. p->bal_##pr = - (++((*root)->bal_##pr )); \
  29. } \
  30. } \
  31. else if (p->bal_##pr > 1) \
  32. { \
  33. if (p->r_##pr->bal_##pr == -1) \
  34. { \
  35. objname *pp; \
  36. pp=p->r_##pr ; *root=p->r_##pr ->l_##pr ; p->r_##pr =(*root)->l_##pr ; \
  37. (*root)->l_##pr = p; pp->l_##pr = (*root)->r_##pr ; \
  38. p = *root; p->r_##pr = pp; \
  39. if (p->bal_##pr > 0) p->l_##pr ->bal_##pr = -p->bal_##pr ; \
  40. else p->l_##pr ->bal_##pr = 0; \
  41. if (p->bal_##pr < 0) p->r_##pr ->bal_##pr = -p->bal_##pr ; \
  42. else p->r_##pr ->bal_##pr = 0; \
  43. p->bal_##pr = 0; \
  44. ht_changed = 1; \
  45. } \
  46. else \
  47. { \
  48. ht_changed = (p->r_##pr ->bal_##pr)?1:0; \
  49. *root = p->r_##pr ; \
  50. p->r_##pr = (*root)->l_##pr ; (*root)->l_##pr = p; \
  51. p->bal_##pr = - (--((*root)->bal_##pr )); \
  52. } \
  53. } else ht_changed = 0; \
  54. }
  55. #define Avl_r_insert_proto(objname, pr, COMPARE) \
  56. static int Avl_##objname##pr##_r_insert(objname **root) \
  57. { \
  58. int i; /* height increase */ \
  59. if (!*root) \
  60. { \
  61. *root = Avl_##objname##pr##_new_node; \
  62. Avl_##objname##pr##_new_node = NULL; \
  63. return 1; \
  64. } \
  65. COMPARE(i, Avl_##objname##pr##_new_node, *root); \
  66. \
  67. if (i < 0) \
  68. { /* insert into the left subtree */ \
  69. i = -Avl_##objname##pr##_r_insert(&((*root)->l_##pr)); \
  70. if (Avl_##objname##pr##_new_node != NULL) return 0; /* already there */ \
  71. } \
  72. else if (i > 0) \
  73. { /* insert into the right subtree */ \
  74. i = Avl_##objname##pr##_r_insert(&((*root)->r_##pr)); \
  75. if (Avl_##objname##pr##_new_node != NULL) return 0; /* already there */ \
  76. } \
  77. else \
  78. { /* found */ \
  79. Avl_##objname##pr##_new_node = *root; \
  80. return 0; \
  81. } \
  82. if (!i) return 0; \
  83. (*root)->bal_##pr += i; /* update balance factor */ \
  84. if ((*root)->bal_##pr) \
  85. { \
  86. balance(objname,pr,root,i); \
  87. return 1-i; \
  88. } \
  89. else return 0; \
  90. }
  91. #define Avl_r_delete_proto(objname,pr,COMPARE) \
  92. static int Avl_##objname##pr##_r_delete(objname **root) \
  93. { \
  94. int i; /* height decrease */ \
  95. \
  96. if (!*root) return 0; /* not found */ \
  97. \
  98. COMPARE(i, Avl_##objname##pr##_new_node, *root); \
  99. \
  100. if (i < 0) \
  101. i = -Avl_##objname##pr##_r_delete(&((*root)->l_##pr)); \
  102. else if (i > 0) \
  103. i = Avl_##objname##pr##_r_delete(&((*root)->r_##pr)); \
  104. else \
  105. { \
  106. if (!(*root)->l_##pr) \
  107. { \
  108. *root = (*root)->r_##pr; \
  109. return 1; \
  110. } \
  111. else if (!(*root)->r_##pr) \
  112. { \
  113. *root = (*root)->l_##pr; \
  114. return 1; \
  115. } \
  116. else \
  117. { \
  118. i = Avl_##objname##pr##_r_delfix(&((*root)->r_##pr)); \
  119. Avl_##objname##pr##_new_node->l_##pr = (*root)->l_##pr; \
  120. Avl_##objname##pr##_new_node->r_##pr = (*root)->r_##pr; \
  121. Avl_##objname##pr##_new_node->bal_##pr = (*root)->bal_##pr; \
  122. *root = Avl_##objname##pr##_new_node; \
  123. } \
  124. } \
  125. if (!i) return 0; \
  126. (*root)->bal_##pr -= i; \
  127. if ((*root)->bal_##pr) \
  128. { \
  129. balance(objname,pr,root,i); \
  130. return i; \
  131. } \
  132. return 1; \
  133. }
  134. #define Avl_r_delfix_proto(objname,pr) \
  135. static int Avl_##objname##pr##_r_delfix(objname **root) \
  136. { \
  137. int i; /* height decrease */ \
  138. \
  139. if (!(*root)->l_##pr) \
  140. { \
  141. Avl_##objname##pr##_new_node = *root; \
  142. *root = (*root)->r_##pr; \
  143. return 1; \
  144. } \
  145. i = -Avl_##objname##pr##_r_delfix(&((*root)->l_##pr)); \
  146. if (!i) return 0; \
  147. (*root)->bal_##pr -= i; \
  148. if ((*root)->bal_##pr) \
  149. { \
  150. balance(objname,pr,root,i); \
  151. return i; \
  152. } \
  153. return 1; \
  154. }
  155. #define Avl_ins_proto(alias,objname,pr) \
  156. static objname *##alias##_ins(objname *data) \
  157. { \
  158. Avl_##objname##pr##_new_node = data; \
  159. (data)->l_##pr = NULL; \
  160. (data)->r_##pr = NULL; \
  161. (data)->bal_##pr = 0; \
  162. Avl_##objname##pr##_r_insert(&Avl_##objname##pr##_tree); \
  163. if (Avl_##objname##pr##_new_node) \
  164. return Avl_##objname##pr##_new_node; \
  165. return NULL; \
  166. }
  167. #define Avl_del_proto(alias,objname,pr) \
  168. static void alias##_del(objname *data) \
  169. { \
  170. Avl_##objname##pr##_new_node = data; \
  171. Avl_##objname##pr##_r_delete(&Avl_##objname##pr##_tree); \
  172. }
  173. #define Avl_replace_proto(alias,objname,pr,COMPARE) \
  174. static void alias##_replace(objname *data) \
  175. { \
  176. objname **p = &Avl_##objname##pr##_tree; \
  177. int cmp; \
  178. while (*p) \
  179. { \
  180. COMPARE(cmp, data, *p); \
  181. if (cmp < 0) \
  182. p = &((*p)->l_##pr); \
  183. else if (cmp > 0) \
  184. p = &((*p)->r_##pr); \
  185. else \
  186. { \
  187. (data)->l_##pr = (*p)->l_##pr; \
  188. (data)->r_##pr = (*p)->r_##pr; \
  189. (data)->bal_##pr = (*p)->bal_##pr; \
  190. *p = data; \
  191. return; \
  192. } \
  193. } \
  194. }
  195. #define Avl_Root(objname,pr) Avl_##objname##pr##_tree
  196. #define Avl_Tree(alias,objname,pr,COMPARE) \
  197. static objname *Avl_##objname##pr##_tree = NULL; \
  198. static objname *Avl_##objname##pr##_new_node; \
  199. Avl_r_insert_proto(objname,pr,COMPARE) \
  200. Avl_r_delfix_proto(objname,pr) \
  201. Avl_r_delete_proto(objname,pr,COMPARE) \
  202. Avl_ins_proto(alias,objname,pr) \
  203. Avl_del_proto(alias,objname,pr) \
  204. Avl_replace_proto(alias,objname,pr,COMPARE)