generic_binary_tree.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * Copyright (C) 2000,2001 Florian Sander
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #define GENERIC_BINARY_TREE 1
  19. #ifdef DYNAMIC_MEM_DEBUG
  20. #define bt_malloc(x) malloc(x)
  21. #define bt_free(x) free(x)
  22. #else
  23. #define bt_malloc nmalloc
  24. #define bt_free nfree
  25. #endif
  26. struct generic_binary_tree {
  27. void *root;
  28. int (*comparedata) (void *data1, void *data2);
  29. int (*expmemdata) (void *data);
  30. void (*freedata) (void *data);
  31. };
  32. struct generic_binary_tree_node {
  33. void *data;
  34. void *left;
  35. void *right;
  36. };
  37. static void btree_add(struct generic_binary_tree *, void *);
  38. //static int btree_expmem(struct generic_binary_tree *);
  39. static int btree_recursive_expmem(struct generic_binary_tree *, struct generic_binary_tree_node *);
  40. static void *btree_get(struct generic_binary_tree *, void *t);
  41. static void btree_freetree(struct generic_binary_tree *);
  42. static void btree_recursive_free(struct generic_binary_tree *,
  43. struct generic_binary_tree_node *);
  44. static void btree_getall(struct generic_binary_tree *, void (*) (void *));
  45. static void btree_recursive_getall(struct generic_binary_tree_node *,
  46. void (*) (void *));
  47. //static void btree_getall_expanded(struct generic_binary_tree *tree, void (*) (void *));
  48. static void btree_recursive_getall_expanded(struct generic_binary_tree_node *,
  49. void (*) (void *));
  50. static void btree_remove(struct generic_binary_tree *, void *);
  51. static void btree_add(struct generic_binary_tree *tree, void *data)
  52. {
  53. struct generic_binary_tree_node *node, *lastnode;
  54. int cmp, lastcmp;
  55. Assert(tree);
  56. Assert(data);
  57. cmp = lastcmp = 0;
  58. node = tree->root;
  59. lastnode = NULL;
  60. while (node) {
  61. cmp = tree->comparedata(node->data, data);
  62. if (!cmp) {
  63. // item is identical -> free old data and insert new
  64. tree->freedata(node->data);
  65. node->data = data;
  66. return;
  67. }
  68. lastnode = node;
  69. lastcmp = cmp;
  70. if (cmp < 0)
  71. node = node->left;
  72. else
  73. node = node->right;
  74. }
  75. node = bt_malloc(sizeof(struct generic_binary_tree_node));
  76. node->left = NULL;
  77. node->right = NULL;
  78. node->data = data;
  79. if (!lastnode)
  80. tree->root = node;
  81. else {
  82. Assert(lastcmp);
  83. if (lastcmp < 0) {
  84. Assert(!lastnode->left);
  85. lastnode->left = node;
  86. } else {
  87. Assert(!lastnode->right);
  88. lastnode->right = node;
  89. }
  90. }
  91. }
  92. /*
  93. static int btree_expmem(struct generic_binary_tree *tree)
  94. {
  95. int size = 0;
  96. Assert(tree);
  97. size += btree_recursive_expmem(tree, tree->root);
  98. return size;
  99. }
  100. */
  101. static int btree_recursive_expmem(struct generic_binary_tree *tree, struct generic_binary_tree_node *node)
  102. {
  103. int size = 0;
  104. if (!node)
  105. return 0;
  106. size += sizeof(struct generic_binary_tree_node);
  107. size += tree->expmemdata(node->data);
  108. size += btree_recursive_expmem(tree, node->left);
  109. size += btree_recursive_expmem(tree, node->right);
  110. return size;
  111. }
  112. static void *btree_get(struct generic_binary_tree *tree, void *what)
  113. {
  114. struct generic_binary_tree_node *node;
  115. int cmp;
  116. node = tree->root;
  117. while (node) {
  118. cmp = tree->comparedata(node->data, what);
  119. if (!cmp)
  120. return node->data;
  121. if (cmp < 0)
  122. node = node->left;
  123. else
  124. node = node->right;
  125. }
  126. return NULL;
  127. }
  128. static void btree_freetree(struct generic_binary_tree *tree)
  129. {
  130. btree_recursive_free(tree, tree->root);
  131. }
  132. static void btree_recursive_free(struct generic_binary_tree *tree,
  133. struct generic_binary_tree_node *node)
  134. {
  135. if (!node)
  136. return;
  137. btree_recursive_free(tree, node->left);
  138. btree_recursive_free(tree, node->right);
  139. tree->freedata(node->data);
  140. bt_free(node);
  141. }
  142. /* btree_getall():
  143. * calls the specified function for each item in the tree.
  144. * NOTE: getall() calls the proc _before_ it proceeds into recursion. This way,
  145. * one can savely store the tree into a file without mixing up its form.
  146. * But if you delete an item from the called prcedure, this function
  147. * WILL crash. Use btree_getall()_expanded instead.
  148. */
  149. static void btree_getall(struct generic_binary_tree *tree, void (*func) (void *))
  150. {
  151. Assert(tree);
  152. btree_recursive_getall(tree->root, func);
  153. }
  154. static void btree_recursive_getall(struct generic_binary_tree_node *node,
  155. void (*func) (void *))
  156. {
  157. if (!node)
  158. return;
  159. // first call the function, then proceed into recursion
  160. // this way, the tree keeps in form if its saved to a file, for example
  161. Assert(func);
  162. func(node->data);
  163. btree_recursive_getall(node->left, func);
  164. btree_recursive_getall(node->right, func);
  165. }
  166. /* btree_getall_expanded():
  167. * the same as btree_getall(), but calls the function after the greatest level of recursion
  168. * has been reached. The node-pointers won't be accessed anymore when the first function
  169. * gets called. You can savely use this to free items.
  170. */
  171. /*
  172. static void btree_getall_expanded(struct generic_binary_tree *tree, void (*func) (void *))
  173. {
  174. Assert(tree);
  175. btree_recursive_getall_expanded(tree->root, func);
  176. }
  177. */
  178. static void btree_recursive_getall_expanded(struct generic_binary_tree_node *node,
  179. void (*func) (void *))
  180. {
  181. if (!node)
  182. return;
  183. btree_recursive_getall_expanded(node->left, func);
  184. btree_recursive_getall_expanded(node->right, func);
  185. Assert(func);
  186. func(node->data);
  187. }
  188. static void btree_remove(struct generic_binary_tree *tree, void *data)
  189. {
  190. struct generic_binary_tree_node *node, *last, *largenode, *lastlarge;
  191. int ret, lastret;
  192. Assert(tree);
  193. Assert(data);
  194. last = NULL;
  195. lastret = 0;
  196. node = tree->root;
  197. while (node) {
  198. ret = tree->comparedata(node->data, data);
  199. if (ret == 0)
  200. break;
  201. last = node;
  202. lastret = ret;
  203. if (ret < 0)
  204. node = node->left;
  205. else
  206. node = node->right;
  207. }
  208. if (!node) // oops, item not found
  209. return;
  210. if (!node->left && !node->right) {
  211. // *freu* no sub-branches! We can easily delete this item.
  212. if (last) {
  213. if (lastret < 0)
  214. last->left = NULL;
  215. else
  216. last->right = NULL;
  217. } else
  218. tree->root = NULL;
  219. } else if (!node->left) {
  220. // also pretty easy. Just connect the child to the parent.
  221. if (last) {
  222. if (lastret < 0)
  223. last->left = node->right;
  224. else
  225. last->right = node->right;
  226. } else
  227. tree->root = node->right;
  228. } else if (!node->right) {
  229. // same as above, but mirrored
  230. if (last) {
  231. if (lastret < 0)
  232. last->left = node->left;
  233. else
  234. last->right = node->left;
  235. } else
  236. tree->root = node->left;
  237. } else {
  238. // aaargh... two sub-trees! The world is not fair... *sigh*
  239. // debug0("argl... worst case, two subtrees. :( Let's pray...");
  240. // now we take the largest item from the left subtree and replace the
  241. // doomed node with it.
  242. // since it is the largest val, the tree remains valid and doesn't
  243. // get deformed too much.
  244. // at first, we have to find this node and cut it from the tree
  245. largenode = node->left;
  246. lastlarge = NULL;
  247. while (largenode && largenode->right) {
  248. lastlarge = largenode;
  249. largenode = largenode->right;
  250. }
  251. // only set largenode->left to node->left if largenode exists.
  252. // otherwise node->left points to largenode, which would result
  253. // in a nice short-circuit
  254. // If it does not exist, just leave largenode->left as it is because we just
  255. // move largenode one level up, so it can keep its left subtree.
  256. if (lastlarge) {
  257. lastlarge->right = largenode->left;
  258. largenode->left = node->left;
  259. }
  260. // now connect node's subtrees to it
  261. largenode->right = node->right;
  262. // and finally replace node with largenode
  263. if (last) {
  264. if (lastret < 0)
  265. last->left = largenode;
  266. else
  267. last->right = largenode;
  268. } else
  269. tree->root = largenode;
  270. }
  271. // finally kill the node... we shouldn't need it anymore
  272. tree->freedata(node->data);
  273. bt_free(node);
  274. node = NULL;
  275. }
  276. #ifdef BTREE_WITHOPTIMIZE
  277. static void btree_optimize(struct generic_binary_tree *tree,
  278. struct generic_binary_tree_node *node,
  279. struct generic_binary_tree_node *last,
  280. int limit)
  281. {
  282. /* int leftdepth, rightdepth;
  283. if (!node)
  284. return;
  285. btree_optimize(tree, node->left, node, last, limit);
  286. btree_optimize(tree, node->right, node, last, limit);
  287. leftdepth = btree_depth(node->left);
  288. rightdepth = btree_depth(node->right);
  289. if ((leftdepth - rightdepth) > limit) {
  290. }
  291. */
  292. }
  293. #endif