09btree/btree.c
#include <stdio.h> #include "btree.h" #include "queue.h" static void bnode_init(struct btree_info *info, struct bnode_info *bnode) { bnode->parent = NULL; bnode->lchild = NULL; bnode->rchild = NULL; } static void btree_add(struct btree_info *info, struct bnode_info *bnode, int (*cmp)(struct bnode_info *, struct bnode_info *)) { bnode_init(info, bnode); struct bnode_info *cur = info->root; struct bnode_info **pparent = &info->root; while (*pparent) { if (cmp(bnode, cur) < 0) { pparent = &cur->lchild; } else { pparent = &cur->rchild; } if (*pparent) { cur = *pparent; } } *pparent = bnode; bnode->parent = cur; }
09btree/Makefile
SRCS := btree.c SUBDIR := $(BUILT_IN): $(SRCS:.c=.o) $(SUBDIR) $(LD) $(LDFLAGS) -r -o $@ $(SRCS:.c=.o) $(SUBDIR:=/$(BUILT_IN)) $(SUBDIR): $(MAKE) -C $@ $(SRCS:.c=.o): $(CC) $(CFLAGS) -c $< $(DEP): $(SRCS) $(CC) $(CFLAGS) -MM $(SRCS) >$@ sed -i "s/: / $@: /g" $@ sinclude $(DEP) .PHONY: clean $(SUBDIR) clean: for dir in $(SUBDIR); do \ $(MAKE) -C $$dir clean; \ done $(RM) $(SRCS:.c=.o) $(BUILT_IN) $(DEP)
09btree/include/btree.h
struct bnode_info { struct bnode_info *parent; struct bnode_info *lchild; struct bnode_info *rchild; }; struct btree_info { struct bnode_info *root; void (*bnode_init)(struct btree_info *, struct bnode_info *); void (*add)(struct btree_info *, struct bnode_info *bnode, int (*cmp)(struct bnode_info *, struct bnode_info *)); void (*preorder)(struct btree_info *, void (*)(struct btree_info *, struct bnode_info *)); void (*inorder)(struct btree_info *, void (*)(struct btree_info *, struct bnode_info *)); void (*postorder)(struct btree_info *, void (*)(struct btree_info *, struct bnode_info *)); void (*levelorder)(struct btree_info *, void (*)(struct btree_info *, struct bnode_info *)); void (*reverse)(struct btree_info *); void (*del)(struct btree_info *, struct bnode_info *, void (*)(struct btree_info *, struct bnode_info *));
struct bnode_info *(*search)(struct btree_info *, struct bnode_info *key, int (*cmp)(struct bnode_info *, struct bnode_info *)); }; void btree_init(struct btree_info *); void btree_destroy(struct btree_info *, void (*)(struct btree_info *, struct bnode_info *)); #define offsetof(type, member) \ ( (size_t)(&((type*)0)->member) ) #define container_of(ptr, type, member) \ ({const typeof(((type*)0)->member) *__mptr = ptr; \ (type *)((char*)ptr - offsetof(type, member));})
09btree/include/list.h
struct node_info { struct node_info *prev; struct node_info *next; char priv[]; }; struct list_info { struct node_info *head; void (*add)(struct list_info *, const void *data_entry, size_t data_size); void (*add_tail)(struct list_info *, const void *data_entry, size_t data_size); void (*del)(struct list_info *, struct node_info *, size_t data_size); }; #define list_for_each(cur, head) \ for (cur = (head)->next; \ (cur) != (head); \ cur = (cur)->next) #define list_for_each_safe(cur, tmp, head) \ for (cur = (head)->next, tmp = (cur)->next; \ (cur) != (head); \ cur = tmp, tmp = (tmp)->next) #define ENTRY(node, type) ((type*)(node->priv)) void list_init(struct list_info*); void list_destroy(struct list_info*);
09btree/include/queue.h
#include "list.h" struct queue_info { struct list_info list; void (*push)(struct queue_info *, const void *data_entry, size_t data_size); int (*pop)(struct queue_info *, void *data_entry, size_t data_size); int (*top)(struct queue_info *, void *data_entry, size_t data_size); int (*isempty)(struct queue_info *); }; void queue_init(struct queue_info *); void queue_destroy(struct queue_info *); ~
09btree/main/test.c
#include <stdio.h> #include <stdlib.h> #include "btree.h" struct node_info { ssize_t data; struct bnode_info bnode; }; static int cmp(struct bnode_info *a, struct bnode_info *b) { struct node_info *pa = container_of(a, struct node_info, bnode); struct node_info *pb = container_of(b, struct node_info, bnode); return pa->data - pb->data; } static void print_node(struct btree_info *info, struct bnode_info *bnode) { struct node_info *ptr = container_of(bnode, struct node_info, bnode); printf("%ld ", ptr->data); } static void m_free(struct btree_info *info, struct bnode_info *bnode) { info->bnode_init(info, bnode); free(container_of(bnode, struct node_info, bnode)); }
int main() { struct btree_info btree; btree_init(&btree); struct node_info *cur = NULL; ssize_t s[] = {10, 15, 2, 6, 7, 3, 8, 5, 2, 0, -2, 6}; size_t i = 0; for (i = 0; i < sizeof(s) / sizeof(ssize_t); ++i) { cur = (struct node_info *)malloc(sizeof(struct node_info)); cur->data = s[i]; btree.add(&btree, &cur->bnode, cmp); } struct node_info key = {6}; struct bnode_info *search_ret = NULL;
printf("del node %ld\n", key.data); if (search_ret = btree.search(&btree, &key.bnode, cmp)) { btree.del(&btree, search_ret, m_free); } printf("preorder\n"); btree.preorder(&btree, print_node); printf("\n"); printf("inorder\n"); btree.inorder(&btree, print_node); printf("\n"); printf("postorder\n"); btree.postorder(&btree, print_node); printf("\n"); printf("levelorder\n"); btree.levelorder(&btree, print_node); printf("\n"); btree_destroy(&btree, m_free); return 0; }
09btree/main/Makefile
SRCS := test.c SUBDIR := $(BUILT_IN): $(SRCS:.c=.o) $(SUBDIR) $(LD) $(LDFLAGS) -r -o $@ $(SRCS:.c=.o) $(SUBDIR:=/$(BUILT_IN)) $(SUBDIR): $(MAKE) -C $@ $(SRCS:.c=.o): $(CC) $(CFLAGS) -c $< $(DEP): $(SRCS) $(CC) $(CFLAGS) -MM $(SRCS) >$@ sed -i "s/: / $@: /g" $@ sinclude $(DEP) .PHONY: clean $(SUBDIR) clean: for dir in $(SUBDIR); do \ $(MAKE) -C $$dir clean; \ done $(RM) $(SRCS:.c=.o) $(BUILT_IN) $(DEP)
09btree/queue/list.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "list.h" static void __list_add(struct node_info *prev, struct node_info *next, const void *data_entry, size_t data_size) { struct node_info *node = (struct node_info *)malloc(sizeof(struct node_info) + data_size); memcpy(node->priv, data_entry, data_size); node->prev = prev; node->next = next; prev->next = node; next->prev = node; }
static void list_add(struct list_info *info, const void *data_entry, size_t data_size) { __list_add(info->head, info->head->next, data_entry, data_size); } static void list_add_tail(struct list_info *info, const void *data_entry, size_t data_size) { __list_add(info->head->prev, info->head, data_entry, data_size); }
static void list_del(struct list_info *info, struct node_info *node, size_t data_size) { node->prev->next = node->next; node->next->prev = node->prev; node->prev = node; node->next = node; if (data_size) { memset(node->priv, 0, data_size); } free(node); } void list_init(struct list_info *info) { info->head = (struct node_info *)malloc(sizeof(struct node_info)); info->head->prev = info->head; info->head->next = info->head; info->add = list_add; info->add_tail = list_add_tail; info->del = list_del; } void list_destroy(struct list_info *info) { struct node_info *cur = info->head->next; for (; cur != info->head; cur = info->head->next) { list_del(info, cur, 0); } free(info->head); }
09btree/queue/queue.c
#include <stdio.h> #include <string.h> #include "queue.h" static void queue_push(struct queue_info *info, const void *data_entry, size_t data_size) { info->list.add_tail(&info->list, data_entry, data_size); } static int queue_isempty(struct queue_info *info) { return info->list.head->next == info->list.head; } static int queue_top(struct queue_info *info, void *data_entry, size_t data_size) { if (queue_isempty(info)) { return -1; } if (data_entry) { memcpy(data_entry, info->list.head->next->priv, data_size); } return 0; }
static int queue_pop(struct queue_info *info, void *data_entry, size_t data_size) { if (queue_top(info, data_entry, data_size) < 0) { return -1; } //?..绗.?涓..?..? info->list.del(&info->list, info->list.head->next, data_size); return 0; } void queue_init(struct queue_info *info) { list_init(&info->list); info->push = queue_push; info->pop = queue_pop; info->top = queue_top; info->isempty = queue_isempty; } void queue_destroy(struct queue_info *info) { list_destroy(&info->list); }
09btree/queue/Makefile
SRCS := list.c queue.c SUBDIR := $(BUILT_IN): $(SRCS:.c=.o) $(SUBDIR) $(LD) $(LDFLAGS) -r -o $@ $(SRCS:.c=.o) $(SUBDIR:=/$(BUILT_IN)) $(SUBDIR): $(MAKE) -C $@ $(SRCS:.c=.o): $(CC) $(CFLAGS) -c $< $(DEP): $(SRCS) $(CC) $(CFLAGS) -MM $(SRCS) >$@ sed -i "s/: / $@: /g" $@ sinclude $(DEP) .PHONY: clean $(SUBDIR) clean: for dir in $(SUBDIR); do \ $(MAKE) -C $$dir clean; \ done $(RM) $(SRCS:.c=.o) $(BUILT_IN) $(DEP)