bitree.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #include "bitree.h"
  2. #include <mm/slab.h>
  3. #include <common/errno.h>
  4. #include <common/kfifo.h>
  5. #include <debug/bug.h>
  6. #define smaller(root, a, b) (root->cmp((a)->value, (b)->value) == -1)
  7. #define equal(root, a, b) (root->cmp((a)->value, (b)->value) == 0)
  8. #define greater(root, a, b) (root->cmp((a)->value, (b)->value) == 1)
  9. /**
  10. * @brief 创建二叉搜索树
  11. *
  12. * @param node 根节点
  13. * @param cmp 比较函数
  14. * @param release 用来释放结点的value的函数
  15. * @return struct bt_root_t* 树根结构体
  16. */
  17. struct bt_root_t *bt_create_tree(struct bt_node_t *node, int (*cmp)(void *a, void *b), int (*release)(void *value))
  18. {
  19. if (node == NULL || cmp == NULL)
  20. return -EINVAL;
  21. struct bt_root_t *root = (struct bt_root_t *)kmalloc(sizeof(struct bt_root_t), 0);
  22. memset((void *)root, 0, sizeof(struct bt_root_t));
  23. root->bt_node = node;
  24. root->cmp = cmp;
  25. root->release = release;
  26. root->size = (node == NULL) ? 0 : 1;
  27. return root;
  28. }
  29. /**
  30. * @brief 创建结点
  31. *
  32. * @param left 左子节点
  33. * @param right 右子节点
  34. * @param value 当前节点的值
  35. * @return struct bt_node_t*
  36. */
  37. struct bt_node_t *bt_create_node(struct bt_node_t *left, struct bt_node_t *right, struct bt_node_t *parent, void *value)
  38. {
  39. struct bt_node_t *node = (struct bt_node_t *)kmalloc(sizeof(struct bt_node_t), 0);
  40. FAIL_ON_TO(node == NULL, nomem);
  41. memset((void *)node, 0, sizeof(struct bt_node_t));
  42. node->left = left;
  43. node->right = right;
  44. node->value = value;
  45. node->parent = parent;
  46. return node;
  47. nomem:;
  48. return -ENOMEM;
  49. }
  50. /**
  51. * @brief 插入结点
  52. *
  53. * @param root 树根结点
  54. * @param value 待插入结点的值
  55. * @return int 返回码
  56. */
  57. int bt_insert(struct bt_root_t *root, void *value)
  58. {
  59. if (root == NULL)
  60. return -EINVAL;
  61. struct bt_node_t *this_node = root->bt_node;
  62. struct bt_node_t *last_node = NULL;
  63. struct bt_node_t *insert_node = bt_create_node(NULL, NULL, NULL, value);
  64. FAIL_ON_TO((uint64_t)insert_node == (uint64_t)(-ENOMEM), failed);
  65. while (this_node != NULL)
  66. {
  67. last_node = this_node;
  68. if (smaller(root, insert_node, this_node))
  69. this_node = this_node->left;
  70. else
  71. this_node = this_node->right;
  72. }
  73. insert_node->parent = last_node;
  74. if (unlikely(last_node == NULL))
  75. root->bt_node = insert_node;
  76. else
  77. {
  78. if (smaller(root, insert_node, last_node))
  79. last_node->left = insert_node;
  80. else
  81. last_node->right = insert_node;
  82. }
  83. ++root->size;
  84. return 0;
  85. failed:;
  86. return -ENOMEM;
  87. }
  88. /**
  89. * @brief 搜索值为value的结点
  90. *
  91. * @param value 值
  92. * @param ret_addr 返回的结点基地址
  93. * @return int 错误码
  94. */
  95. int bt_query(struct bt_root_t *root, void *value, uint64_t *ret_addr)
  96. {
  97. struct bt_node_t *this_node = root->bt_node;
  98. struct bt_node_t tmp_node = {0};
  99. tmp_node.value = value;
  100. // 如果返回地址为0
  101. if (ret_addr == NULL)
  102. return -EINVAL;
  103. while (this_node != NULL && !equal(root, this_node, &tmp_node))
  104. {
  105. if (smaller(root, &tmp_node, this_node))
  106. this_node = this_node->left;
  107. else
  108. this_node = this_node->right;
  109. }
  110. if (this_node != NULL && equal(root, this_node, &tmp_node))
  111. {
  112. *ret_addr = (uint64_t)this_node;
  113. return 0;
  114. }
  115. else
  116. {
  117. // 找不到则返回-1,且addr设为0
  118. *ret_addr = NULL;
  119. return -1;
  120. }
  121. }
  122. static struct bt_node_t *bt_get_minimum(struct bt_node_t *this_node)
  123. {
  124. while (this_node->left != NULL)
  125. this_node = this_node->left;
  126. return this_node;
  127. }
  128. /**
  129. * @brief 删除结点
  130. *
  131. * @param root 树根
  132. * @param value 待删除结点的值
  133. * @return int 返回码
  134. */
  135. int bt_delete(struct bt_root_t *root, void *value)
  136. {
  137. uint64_t tmp_addr;
  138. int retval;
  139. // 寻找待删除结点
  140. retval = bt_query(root, value, &tmp_addr);
  141. if (retval != 0 || tmp_addr == NULL)
  142. return retval;
  143. struct bt_node_t *this_node = (struct bt_node_t *)tmp_addr;
  144. struct bt_node_t *to_delete = NULL, *to_delete_son = NULL;
  145. if (this_node->left == NULL || this_node->right == NULL)
  146. to_delete = this_node;
  147. else
  148. {
  149. to_delete = bt_get_minimum(this_node->right);
  150. // 释放要被删除的值,并把下一个结点的值替换上来
  151. root->release(this_node->value);
  152. this_node->value = to_delete->value;
  153. }
  154. if (to_delete->left != NULL)
  155. to_delete_son = to_delete->left;
  156. else
  157. to_delete_son = to_delete->right;
  158. if (to_delete_son != NULL)
  159. to_delete_son->parent = to_delete->parent;
  160. if (to_delete->parent == NULL)
  161. root->bt_node = to_delete_son;
  162. else
  163. {
  164. if (to_delete->parent->left == to_delete)
  165. to_delete->parent->left = to_delete_son;
  166. else
  167. to_delete->parent->right = to_delete_son;
  168. }
  169. --root->size;
  170. // 释放最终要删除的结点的对象
  171. kfree(to_delete);
  172. }
  173. /**
  174. * @brief 释放整个二叉搜索树
  175. *
  176. * @param root 树的根节点
  177. * @return int 错误码
  178. */
  179. int bt_destroy_tree(struct bt_root_t *root)
  180. {
  181. // 新建一个kfifo缓冲区,将指向结点的指针存入fifo队列
  182. // 注:为了将指针指向的地址存入队列,我们需要对指针取地址
  183. struct kfifo_t fifo;
  184. kfifo_alloc(&fifo, ((root->size + 1) / 2) * sizeof(struct bt_node_t *), 0);
  185. kfifo_in(&fifo, (void *)&(root->bt_node), sizeof(struct bt_node_t *));
  186. // bfs
  187. while (!kfifo_empty(&fifo))
  188. {
  189. // 取出队列头部的结点指针
  190. struct bt_node_t *nd;
  191. uint64_t res;
  192. int count = kfifo_out(&fifo, &res, sizeof(uint64_t));
  193. nd = (struct bt_node_t *)res;
  194. // 将子节点加入队列
  195. if (nd->left != NULL)
  196. kfifo_in(&fifo, (void *)&(nd->left), sizeof(struct bt_node_t *));
  197. if (nd->right != NULL)
  198. kfifo_in(&fifo, (void *)&(nd->right), sizeof(struct bt_node_t *));
  199. // 销毁当前节点
  200. root->release(nd->value);
  201. kfree(nd);
  202. }
  203. kfifo_free_alloc(&fifo);
  204. return 0;
  205. }