|
|
@@ -0,0 +1,194 @@
|
|
|
+#include <ds/bitree.h>
|
|
|
+#include <ds/err.h>
|
|
|
+
|
|
|
+extern func_malloc ds_malloc;
|
|
|
+extern func_free ds_free;
|
|
|
+
|
|
|
+ds_bitree_t* ds_bitree_init(func_each destroyer)
|
|
|
+{
|
|
|
+ ds_bitree_t* tree = (ds_bitree_t*)ds_malloc(sizeof(ds_bitree_t));
|
|
|
+ if (!tree) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ tree->size = 0;
|
|
|
+ tree->root = NULL;
|
|
|
+ tree->destroyer = destroyer;
|
|
|
+ tree->comparer = NULL;
|
|
|
+ return tree;
|
|
|
+}
|
|
|
+
|
|
|
+void ds_bitree_destroy(ds_bitree_t* tree)
|
|
|
+{
|
|
|
+ ds_bitree_rm_left(tree, NULL);
|
|
|
+
|
|
|
+ ds_free(tree);
|
|
|
+ tree = NULL;
|
|
|
+}
|
|
|
+
|
|
|
+int ds_bitree_ins_left(ds_bitree_t* tree, ds_bitree_node_t* node, ds_data_t data)
|
|
|
+{
|
|
|
+ ds_bitree_node_t * new_node, **pos;
|
|
|
+ if (!node) {
|
|
|
+ if (ds_bitree_size(tree) > 0) {
|
|
|
+ return DS_ERR_PARAMS;
|
|
|
+ }
|
|
|
+ pos = &(tree->root);
|
|
|
+ } else {
|
|
|
+ if (ds_bitree_left(node)) {
|
|
|
+ return DS_ERR_TARGET_EXISTS;
|
|
|
+ }
|
|
|
+ pos = &(node->left);
|
|
|
+ }
|
|
|
+ if((new_node = (ds_bitree_node_t*)ds_malloc(sizeof(ds_bitree_node_t))) == NULL) {
|
|
|
+ return DS_ERR_MEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ new_node->data = data;
|
|
|
+ new_node->left = NULL;
|
|
|
+ new_node->right = NULL;
|
|
|
+
|
|
|
+ *pos = new_node;
|
|
|
+ tree->size++;
|
|
|
+
|
|
|
+ return DS_ERR_OK;
|
|
|
+}
|
|
|
+
|
|
|
+int ds_bitree_ins_right(ds_bitree_t* tree, ds_bitree_node_t* node, ds_data_t data)
|
|
|
+{
|
|
|
+ ds_bitree_node_t * new_node, **pos;
|
|
|
+ if (!node) {
|
|
|
+ if (ds_bitree_size(tree) > 0) {
|
|
|
+ return DS_ERR_PARAMS;
|
|
|
+ }
|
|
|
+ pos = &tree->root;
|
|
|
+ } else {
|
|
|
+ if (ds_bitree_right(node)) {
|
|
|
+ return DS_ERR_TARGET_EXISTS;
|
|
|
+ }
|
|
|
+ pos = &(node->right);
|
|
|
+ }
|
|
|
+ if((new_node = (ds_bitree_node_t*)ds_malloc(sizeof(ds_bitree_node_t))) == NULL) {
|
|
|
+ return DS_ERR_MEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ new_node->data = data;
|
|
|
+ new_node->left = NULL;
|
|
|
+ new_node->right = NULL;
|
|
|
+
|
|
|
+ *pos = new_node;
|
|
|
+ tree->size++;
|
|
|
+
|
|
|
+ return DS_ERR_OK;
|
|
|
+}
|
|
|
+
|
|
|
+int ds_bitree_rm_left(ds_bitree_t* tree, ds_bitree_node_t* node)
|
|
|
+{
|
|
|
+ ds_bitree_node_t ** pos;
|
|
|
+ if (ds_bitree_size(tree) <= 0) {
|
|
|
+ return DS_ERR_EMPTY;
|
|
|
+ }
|
|
|
+ if (!node) {
|
|
|
+ pos = &(tree->root);
|
|
|
+ } else {
|
|
|
+ pos = &(node->left);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (*pos) {
|
|
|
+ ds_bitree_rm_left(tree, *pos);
|
|
|
+ ds_bitree_rm_right(tree, *pos);
|
|
|
+
|
|
|
+ if(tree->destroyer) {
|
|
|
+ tree->destroyer((*pos)->data);
|
|
|
+ }
|
|
|
+
|
|
|
+ ds_free(*pos);
|
|
|
+ *pos = NULL;
|
|
|
+
|
|
|
+ tree->size--;
|
|
|
+ }
|
|
|
+ return DS_ERR_OK;
|
|
|
+}
|
|
|
+
|
|
|
+int ds_bitree_rm_right(ds_bitree_t* tree, ds_bitree_node_t* node)
|
|
|
+{
|
|
|
+ ds_bitree_node_t**pos;
|
|
|
+ if (ds_bitree_size(tree) <= 0){
|
|
|
+ return DS_ERR_EMPTY;
|
|
|
+ }
|
|
|
+ if(!node) {
|
|
|
+ pos = &(tree->root);
|
|
|
+ } else {
|
|
|
+ pos = &(node->right);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (*pos) {
|
|
|
+ ds_bitree_rm_left(tree, *pos);
|
|
|
+ ds_bitree_rm_right(tree, *pos);
|
|
|
+
|
|
|
+ if(tree->destroyer){
|
|
|
+ tree->destroyer((*pos)->data);
|
|
|
+ }
|
|
|
+
|
|
|
+ ds_free(*pos);
|
|
|
+ *pos = NULL;
|
|
|
+
|
|
|
+ tree->size--;
|
|
|
+ }
|
|
|
+ return DS_ERR_OK;
|
|
|
+}
|
|
|
+
|
|
|
+ds_bitree_t* ds_bitree_merge(ds_bitree_t*left, ds_bitree_t*right, ds_data_t data)
|
|
|
+{
|
|
|
+ ds_bitree_t *new_tree = ds_bitree_init(left->destroyer);
|
|
|
+ if(!new_tree) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ int err;
|
|
|
+ if((err = ds_bitree_ins_left(new_tree, NULL, data)) != DS_ERR_OK) {
|
|
|
+ ds_bitree_destroy(new_tree);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ ds_bitree_root(new_tree)->left = ds_bitree_root(left);
|
|
|
+ ds_bitree_root(new_tree)->right = ds_bitree_root(right);
|
|
|
+
|
|
|
+ new_tree->size = new_tree->size + left->size + right->size;
|
|
|
+
|
|
|
+ ds_free(left);
|
|
|
+ ds_free(right);
|
|
|
+
|
|
|
+ return new_tree;
|
|
|
+}
|
|
|
+
|
|
|
+void ds_bitree_preorder(ds_bitree_node_t* node, func_each each)
|
|
|
+{
|
|
|
+ if(node){
|
|
|
+ if(each){
|
|
|
+ each(node);
|
|
|
+ }
|
|
|
+ ds_bitree_preorder(node->left, each);
|
|
|
+ ds_bitree_preorder(node->right, each);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void ds_bitree_inorder(ds_bitree_node_t* node, func_each each)
|
|
|
+{
|
|
|
+ if(node) {
|
|
|
+ ds_bitree_inorder(node->left, each);
|
|
|
+ if(each){
|
|
|
+ each(node);
|
|
|
+ }
|
|
|
+ ds_bitree_inorder(node->right, each);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void ds_bitree_postorder(ds_bitree_node_t* node, func_each each)
|
|
|
+{
|
|
|
+ if(node) {
|
|
|
+ ds_bitree_postorder(node->left, each);
|
|
|
+ ds_bitree_postorder(node->right, each);
|
|
|
+ if(each){
|
|
|
+ each(node);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|