From 40380603039ba9ee18aacb7d2a15a791e47a6aca Mon Sep 17 00:00:00 2001 From: doowoong Date: Sun, 27 Mar 2016 09:05:50 +0900 Subject: [PATCH] API clean up - change API name into unified naming convention ( pkg_moduleFUNC /w cammel case ) - revising heavily recursive into less or no recursive for practical use - generic base class(like) is integrated to lists / trees implementation --- Makefile | 16 +- cdsl.h | 8 +- include/cdsl_bstree.h | 27 +- include/cdsl_heap.h | 21 +- include/cdsl_nrbtree.h | 67 +++ include/cdsl_spltree.h | 38 +- include/test/cdsl_bstree_test.h | 7 + include/test/cdsl_hash_test.h | 7 +- include/test/cdsl_list_test.h | 9 + include/test/cdsl_nrbtree_test.h | 22 + include/test/cdsl_rbtree_test.h | 9 + include/test/cdsl_slist_test.h | 9 +- include/test/cdsl_spltree_test.h | 8 + main.c | 7 + source/base_tree.c | 46 +- source/cdsl_bstree.c | 65 +-- source/cdsl_heap.c | 28 +- source/cdsl_nrbtree.c | 784 +++++++++++++++++++++++++++++++ source/cdsl_rbtree.c | 18 +- source/cdsl_spltree.c | 78 +-- source/recipe.mk | 3 +- source/test/cdsl_bstree_test.c | 36 +- source/test/cdsl_heap_test.c | 25 +- source/test/cdsl_nrbtree_test.c | 65 +++ source/test/cdsl_rbtree_test.c | 2 +- source/test/cdsl_slist_test.c | 7 +- source/test/cdsl_spltree_test.c | 8 +- source/test/recipe.mk | 3 +- 28 files changed, 1169 insertions(+), 254 deletions(-) create mode 100644 include/cdsl_nrbtree.h create mode 100644 include/test/cdsl_nrbtree_test.h create mode 100644 source/cdsl_nrbtree.c create mode 100644 source/test/cdsl_nrbtree_test.c diff --git a/Makefile b/Makefile index ece0c5f..2616f8a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -## makefile for cdsl +# makefile for cdsl CC=clang-3.6 @@ -8,7 +8,7 @@ PYTHON=python PIP=pip MKDIR=mkdir -DBG_CFLAG = -O0 -g3 -fmessage-length=0 +DBG_CFLAG = -O0 -g3 -fmessage-length=0 -D__DBG REL_CFLAG = -O2 -g0 -fmessage-length=0 DYNAMIC_FLAG = -fPIC @@ -21,6 +21,7 @@ TOOL_DIR=$(PROJECT_ROOT_DIR)/tools CONFIG_PY=$(TOOL_DIR)/jconfigpy/jconfigpy.py TEST_TARGET=cdsl +DEV_TEST_TARGET=cdsl_dev DBG_STATIC_TARGET=libcdsld.a DBG_DYNAMIC_TARGET=libcdsld.so @@ -45,7 +46,7 @@ REL_CACHE_DIR=Release SILENT+= $(REL_STATIC_TARGET) $(REL_DYNAMIC_TARGET) $(DBG_OBJS) SILENT+= $(DBG_STATIC_TARGET) $(DBG_DYNAMIC_TARGET) $(REL_OBJS) SILENT+= $(DBG_SH_OBJS) $(REL_SH_OBJS) -SILENT+= $(TEST_TARGET) $(REL_CACHE_DIR)/main.o +SILENT+= $(TEST_TARGET) $(REL_CACHE_DIR)/main.o $(DEV_TEST_TARGET) $(DBG_CACHE_DIR)/main.do .SILENT : $(SILENT) clean @@ -58,7 +59,7 @@ debug : $(DBG_CACHE_DIR) $(DBG_STATIC_TARGET) $(DBG_DYNAMIC_TARGET) release : $(REL_CACHE_DIR) $(REL_STATIC_TARGET) $(REL_DYNAMIC_TARGET) -test : $(REL_CACHE_DIR) $(TEST_TARGET) +test : $(REL_CACHE_DIR) $(DBG_CACHE_DIR) $(TEST_TARGET) $(DEV_TEST_TARGET) config : $(CONFIG_PY) $(PYTHON) $(CONFIG_PY) -c -i config.json @@ -89,6 +90,11 @@ $(TEST_TARGET) : $(REL_CACHE_DIR)/main.o $(REL_OBJS) @echo 'Building unit-test executable... $@' $(CC) -o $@ $(REL_CFLAG) $< $(REL_OBJS) + +$(DEV_TEST_TARGET) : $(DBG_CACHE_DIR)/main.do $(DBG_OBJS) + @echo 'Building unit-test executable... $@' + $(CC) -o $@ $(DBG_CFLAG) $< $(DBG_OBJS) + $(DBG_CACHE_DIR)/%.do : %.c @echo 'compile...$@' $(CC) -c -o $@ $(DBG_CFLAG) $< $(INCS) @@ -110,7 +116,7 @@ PHONY += clean clean : rm -rf $(DBG_CACHE_DIR) $(DBG_STATIC_TARGET) $(DBG_DYNAMIC_TARGET)\ $(REL_CACHE_DIR) $(REL_STATIC_TARGET) $(REL_DYNAMIC_TARGET)\ - $(TEST_TARGET) $(REL_SH_OBJS) $(DBG_SH_OBJS) + $(TEST_TARGET) $(REL_SH_OBJS) $(DBG_SH_OBJS) $(DEV_TEST_TARGET) .PHONY = $(PHONY) diff --git a/cdsl.h b/cdsl.h index 0ddeea0..78fe1a8 100644 --- a/cdsl.h +++ b/cdsl.h @@ -20,12 +20,10 @@ extern "C" { #define TEST_SIZE 5000 #endif -#define VERBOSE_LOG - -#ifdef VERBOSE_LOG -#define log(...) printf(__VA_ARGS__) +#ifdef __DBG +#define __dev_log(...) printf(__VA_ARGS__) #else -#define log(...) +#define __dev_log(...) #endif #define container_of(ptr, type, elem) ((type*) ((size_t) ptr - offsetof(type, elem))) diff --git a/include/cdsl_bstree.h b/include/cdsl_bstree.h index 6028192..9feae2c 100644 --- a/include/cdsl_bstree.h +++ b/include/cdsl_bstree.h @@ -16,8 +16,13 @@ extern "C"{ #endif -typedef struct bs_treenode bs_treeNode_t; -typedef struct bs_treeroot bs_treeRoot_t; +typedef struct bs_treenode bstreeNode_t; +typedef struct bs_treeroot bstreeRoot_t; + +#define cdsl_bstreeMaxDepth(root) tree_max_depth((base_treeRoot_t*) root) +#define cdsl_bstreeTraverse(root, cb, order) tree_traverse((base_treeRoot_t*) root, (base_tree_callback_t) cb, order) +#define cdsl_bstreeSize(root) tree_size((base_treeRoot_t*) root) +#define cdsl_bstreePrint(root, print) tree_print((base_treeRoot_t*) root, print) #define ORDER_INC (int) 0 #define ORDER_DEC (int) 1 @@ -29,7 +34,7 @@ typedef int (*bs_tree_callback_t) (int order,void*); struct bs_treenode { union { struct { - bs_treeNode_t *left, *right; + bstreeNode_t *left, *right; }; base_treeNode_t node; }; @@ -38,21 +43,17 @@ struct bs_treenode { struct bs_treeroot { union { - bs_treeNode_t* entry; + bstreeNode_t* entry; base_treeRoot_t root; }; }; -extern void bstree_root_init(bs_treeRoot_t* rootp); -extern void bstree_node_init(bs_treeNode_t* node,int key); -extern bs_treeNode_t* bstree_insert(bs_treeRoot_t* rootp,bs_treeNode_t* item); -extern bs_treeNode_t* bstree_lookup(bs_treeRoot_t* rootp,int key); -extern bs_treeNode_t* bstree_delete(bs_treeRoot_t* rootp,int key); -extern void bstree_traverse(bs_treeRoot_t* rootp,base_tree_callback_t cb,int order); -extern int bstree_size(bs_treeRoot_t* rootp); -extern void bstree_print(bs_treeRoot_t* rootp,cdsl_generic_printer_t prt); -extern int bstree_max_depth(bs_treeRoot_t* rootp); +extern void cdsl_bstreeRootInit(bstreeRoot_t* rootp); +extern void cdsl_bstreeNodeInit(bstreeNode_t* node,int key); +extern bstreeNode_t* cdsl_bstreeInsert(bstreeRoot_t* rootp,bstreeNode_t* item); +extern bstreeNode_t* cdsl_bstreeLookup(bstreeRoot_t* rootp,int key); +extern bstreeNode_t* cdsl_bstreeDelete(bstreeRoot_t* rootp,int key); #if defined(__cplusplus) diff --git a/include/cdsl_heap.h b/include/cdsl_heap.h index 7c08d7f..1e4e35d 100644 --- a/include/cdsl_heap.h +++ b/include/cdsl_heap.h @@ -15,8 +15,10 @@ extern "C" { #endif - - +#define cdsl_heapMaxDepth(root) tree_max_depth((base_treeRoot_t*) root) +#define cdsl_heapTraverse(root, cb, order) tree_traverse((base_treeRoot_t*) root, (base_tree_callback_t) cb, order) +#define cdsl_heapSize(root) tree_size((base_treeRoot_t*) root) +#define cdsl_heapPrint(root, print) tree_print((base_treeRoot_t*) root, print) typedef struct heap_node heapNode_t; typedef struct heap_root heapRoot_t; @@ -28,7 +30,7 @@ struct heap_node { struct { heapNode_t* left, *right; }; - base_treeNode_t _node; + base_treeNode_t node; }; uint32_t key; }; @@ -36,19 +38,16 @@ struct heap_node { struct heap_root { union { heapNode_t* entry; - base_treeRoot_t _root; + base_treeRoot_t root; }; int dir; heapType_t type; }; -extern void heap_root_init(heapRoot_t* rootp,heapType_t type); -extern void heap_node_init(heapNode_t* node,int key); -extern int heap_enqueue(heapRoot_t* rootp,heapNode_t* item); -extern heapNode_t* heap_deqeue(heapRoot_t* rootp); -extern void heap_print(heapRoot_t* rootp,cdsl_generic_printer_t print); -extern int heap_size(heapRoot_t* rootp); -extern int heap_max_depth(heapRoot_t* rootp); +extern void cdsl_heapRootInit(heapRoot_t* rootp,heapType_t type); +extern void cdsl_heapNodeInit(heapNode_t* node,int key); +extern int cdsl_heapEnqueue(heapRoot_t* rootp,heapNode_t* item); +extern heapNode_t* cdsl_heapDeqeue(heapRoot_t* rootp); #if defined(__cplusplus) } diff --git a/include/cdsl_nrbtree.h b/include/cdsl_nrbtree.h new file mode 100644 index 0000000..5392b04 --- /dev/null +++ b/include/cdsl_nrbtree.h @@ -0,0 +1,67 @@ +/* + * cdsl_nrbtree.h + * + * Created on: Mar 24, 2016 + * Author: innocentevil + */ + +#ifndef INCLUDE_CDSL_NRBTREE_H_ +#define INCLUDE_CDSL_NRBTREE_H_ + +#include "base_tree.h" +#include "cdsl.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifndef rb_key_t +#define rb_key_t uint32_t +#endif + +#define cdsl_nrbtreeMaxDepth(root) tree_max_depth((base_treeRoot_t*) root) +#define cdsl_nrbtreeTraverse(root, cb, order) tree_traverse((base_treeRoot_t*) root, (base_tree_callback_t) cb, order) +#define cdsl_nrbtreeSize(root) tree_size((base_treeRoot_t*) root) +#define cdsl_nrbtreePrint(root, print) tree_print((base_treeRoot_t*) root, print) + +typedef struct cdsl_nrbtree nrbtreeNode_t; +typedef struct cdsl_nrbroot { + union { + struct base_tree_root base_root; + nrbtreeNode_t* entry; + }; +}nrbtreeRoot_t; + +struct cdsl_nrbtree { + union { + struct base_tree_node base_node; + struct { + nrbtreeNode_t* left; + nrbtreeNode_t* right; + }; + + }; + rb_key_t key; +}; + + + +extern void cdsl_nrbtreeRootInit(nrbtreeRoot_t* rootp); +extern void cdsl_nrbtreeNodeInit(nrbtreeNode_t* node, rb_key_t key); +extern nrbtreeNode_t* cdsl_nrbtreeInsert(nrbtreeRoot_t* rootp,nrbtreeNode_t* item); +extern nrbtreeNode_t* cdsl_nrbtreeLookup(nrbtreeRoot_t* rootp,rb_key_t key); +extern nrbtreeNode_t* cdsl_nrbtreeDelete(nrbtreeRoot_t* rootp,rb_key_t key); + +#ifdef __DBG +extern void cdsl_nrbtreePrint_dev(nrbtreeRoot_t* root); +#else +#define cdsl_nrbtreePrint_dev(root) +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* INCLUDE_CDSL_NRBTREE_H_ */ diff --git a/include/cdsl_spltree.h b/include/cdsl_spltree.h index f598586..1582fe3 100644 --- a/include/cdsl_spltree.h +++ b/include/cdsl_spltree.h @@ -8,26 +8,46 @@ #ifndef CDSL_SPLTREE_H_ #define CDSL_SPLTREE_H_ +#include "base_tree.h" + #if defined(__cplusplus) extern "C" { #endif +#define cdsl_spltreeMaxDepth(root) tree_max_depth((base_treeRoot_t*) root) +#define cdsl_traverse(root, cb, order) tree_traverse((base_treeRoot_t*) root, (base_tree_callback_t) cb, order) +#define cdsl_spltreeSize(root) tree_size((base_treeRoot_t*) root) +#define cdsl_spltreePrint(root, print) tree_print((base_treeRoot_t*) root, print) + typedef struct spltree_node spltreeNode_t; +typedef struct spltree_root spltreeRoot_t; + +struct spltree_root { + union { + base_treeRoot_t root_base; + spltreeNode_t* entry; + }; +}; + struct spltree_node { - spltreeNode_t* left,*right; + union { + base_treeNode_t node_base; + struct { + spltreeNode_t* left,*right; + }; + }; int key; }; + +extern void cdsl_spltreeRootInit(spltreeRoot_t* root); extern void cdsl_spltreeNodeInit(spltreeNode_t* node,int key); -extern void cdsl_spltreeInsert(spltreeNode_t** root,spltreeNode_t* item); -extern spltreeNode_t* cdsl_spltreeLookup(spltreeNode_t** root,int key,BOOL splay); -extern spltreeNode_t* cdsl_spltreeLookupLargest(spltreeNode_t** root,BOOL splay); -extern spltreeNode_t* cdsl_spltreeLookupSmallest(spltreeNode_t** root,BOOL splay); -extern spltreeNode_t* cdsl_spltreeDelete(spltreeNode_t** root,int key); -extern int cdsl_spltreeSize(spltreeNode_t** root); -extern int cdsl_spltreeMaxDepth(spltreeNode_t** root); -extern void cdsl_spltreePrint(spltreeNode_t** root); +extern void cdsl_spltreeInsert(spltreeRoot_t* root,spltreeNode_t* item); +extern spltreeNode_t* cdsl_spltreeLookup(spltreeRoot_t* root,int key,BOOL splay); +extern spltreeNode_t* cdsl_spltreeLookupLargest(spltreeRoot_t* root,BOOL splay); +extern spltreeNode_t* cdsl_spltreeLookupSmallest(spltreeRoot_t* root,BOOL splay); +extern spltreeNode_t* cdsl_spltreeDelete(spltreeRoot_t* root,int key); diff --git a/include/test/cdsl_bstree_test.h b/include/test/cdsl_bstree_test.h index 7e1afba..9f471b4 100644 --- a/include/test/cdsl_bstree_test.h +++ b/include/test/cdsl_bstree_test.h @@ -10,7 +10,14 @@ #include "cdsl.h" +#ifdef __cplusplus +extern "C" { +#endif + extern BOOL cdsl_bstreeDoTest(void); +#ifdef __cplusplus +} +#endif #endif /* CDSL_BSTREE_TEST_H_ */ diff --git a/include/test/cdsl_hash_test.h b/include/test/cdsl_hash_test.h index e0f56b9..fdb81c2 100644 --- a/include/test/cdsl_hash_test.h +++ b/include/test/cdsl_hash_test.h @@ -10,10 +10,15 @@ #include "cdsl.h" +#ifdef __cplusplus +extern "C" { +#endif extern BOOL cdsl_hashDoTest(void); - +#ifdef __cplusplus +} +#endif #endif /* CDSL_HASH_TEST_H_ */ diff --git a/include/test/cdsl_list_test.h b/include/test/cdsl_list_test.h index 43c5c1b..af04d5b 100644 --- a/include/test/cdsl_list_test.h +++ b/include/test/cdsl_list_test.h @@ -8,7 +8,16 @@ #ifndef CDSL_LIST_TEST_H_ #define CDSL_LIST_TEST_H_ +#include "cdsl.h" + +#ifdef __cplusplus +extern "C" { +#endif + extern BOOL cdsl_listDoTest(void); +#ifdef __cplusplus +} +#endif #endif /* CDSL_LIST_TEST_H_ */ diff --git a/include/test/cdsl_nrbtree_test.h b/include/test/cdsl_nrbtree_test.h new file mode 100644 index 0000000..96e7d10 --- /dev/null +++ b/include/test/cdsl_nrbtree_test.h @@ -0,0 +1,22 @@ +/* + * cdsl_nrbtree_test.h + * + * Created on: Mar 26, 2016 + * Author: innocentevil + */ + +#ifndef INCLUDE_TEST_CDSL_NRBTREE_TEST_H_ +#define INCLUDE_TEST_CDSL_NRBTREE_TEST_H_ +#include "cdsl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern BOOL cdsl_nrbtreeDoTest(void); + +#ifdef __cplusplus +} +#endif + +#endif /* INCLUDE_TEST_CDSL_NRBTREE_TEST_H_ */ diff --git a/include/test/cdsl_rbtree_test.h b/include/test/cdsl_rbtree_test.h index dcb46ca..22fda1b 100644 --- a/include/test/cdsl_rbtree_test.h +++ b/include/test/cdsl_rbtree_test.h @@ -8,7 +8,16 @@ #ifndef CDSL_RBTREE_TEST_H_ #define CDSL_RBTREE_TEST_H_ +#include "cdsl.h" + +#ifdef __cplusplus +extern "C" { +#endif + extern BOOL cdsl_rbtreeDoTest(void); +#ifdef __cplusplus +} +#endif #endif /* CDSL_RBTREE_TEST_H_ */ diff --git a/include/test/cdsl_slist_test.h b/include/test/cdsl_slist_test.h index c8da9fa..b4eb7d6 100644 --- a/include/test/cdsl_slist_test.h +++ b/include/test/cdsl_slist_test.h @@ -9,11 +9,14 @@ #define CDSL_SLIST_TEST_H_ #include "cdsl.h" -#include "cdsl_slist.h" - +#ifdef __cplusplus +extern "C" { +#endif extern BOOL cdsl_slistDoTest(void); - +#ifdef __cplusplus +} +#endif #endif /* CDSL_SLIST_TEST_H_ */ diff --git a/include/test/cdsl_spltree_test.h b/include/test/cdsl_spltree_test.h index 66192cb..b5c417c 100644 --- a/include/test/cdsl_spltree_test.h +++ b/include/test/cdsl_spltree_test.h @@ -8,8 +8,16 @@ #ifndef CDSL_SPLTREE_TEST_H_ #define CDSL_SPLTREE_TEST_H_ +#include "cdsl.h" + +#ifdef __cplusplus +extern "C" { +#endif extern BOOL cdsl_spltreeDoTest(void); +#ifdef __cplusplus +} +#endif #endif /* CDSL_SPLTREE_TEST_H_ */ diff --git a/main.c b/main.c index 8ebfa9d..c512898 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,7 @@ #include #include +#include "cdsl_nrbtree_test.h" #include "cdsl_heap_test.h" #include "cdsl_list_test.h" #include "cdsl_slist_test.h" @@ -60,6 +61,12 @@ int main(void){ exit(-1); } + printf("New Red Black Tree Test Result : %s\n",RESULT_STRING[result = cdsl_nrbtreeDoTest()]); + if(result == FALSE) + { + exit(-1); + } + return 0; } diff --git a/source/base_tree.c b/source/base_tree.c index 7918ea0..a9f615a 100644 --- a/source/base_tree.c +++ b/source/base_tree.c @@ -11,6 +11,7 @@ #define PRINT printf +#define GET_PTR(ptr) ((base_treeNode_t*) (((uint64_t) ptr) & ~1)) static int calc_max_depth_rc(base_treeNode_t** root); static int calc_size_rc(base_treeNode_t** root); @@ -21,7 +22,7 @@ static void print_tab(int cnt); void tree_traverse(base_treeRoot_t* rootp, base_tree_callback_t cb,int order) { - if((cb == NULL) || (rootp == NULL) || (rootp->entry == NULL)) + if((cb == NULL) || (rootp == NULL) || (GET_PTR(rootp->entry) == NULL)) return; int i = 0; if(order == ORDER_DEC) @@ -52,43 +53,42 @@ int tree_max_depth(base_treeRoot_t* rootp) } - static int calc_size_rc(base_treeNode_t** root) { int cnt = 0; - if((root == NULL) || (*root == NULL)) + if((root == NULL) || (GET_PTR(*root) == NULL)) return 0; - if((*root)) + if(GET_PTR(*root)) cnt = 1; - if(!(*root)->left && !(*root)->right) return cnt; - if((*root)->left) - cnt += calc_size_rc(&(*root)->left); - if((*root)->right) - cnt += calc_size_rc(&(*root)->right); + if(!GET_PTR(GET_PTR(*root)->left) && !GET_PTR(GET_PTR(*root)->right)) return cnt; + if(GET_PTR(GET_PTR(*root)->left)) + cnt += calc_size_rc(&GET_PTR(*root)->left); + if(GET_PTR(GET_PTR(*root)->right)) + cnt += calc_size_rc(&GET_PTR(*root)->right); return cnt; } static int calc_max_depth_rc(base_treeNode_t** root) { - if((root == NULL) || (*root == NULL)) + if((root == NULL) || (GET_PTR(*root) == NULL)) return 0; int max = 0; int temp = 0; - if(max < (temp = calc_max_depth_rc(&(*root)->left))) + if(max < (temp = calc_max_depth_rc(&GET_PTR(*root)->left))) max = temp; - if(max < (temp = calc_max_depth_rc(&(*root)->right))) + if(max < (temp = calc_max_depth_rc(&GET_PTR(*root)->right))) max = temp; return max + 1; } static void print_rc(base_treeNode_t* current,cdsl_generic_printer_t print,int depth) { - if(!current) + if(!GET_PTR(current)) return; - print_rc(current->right,print,depth + 1); - print_tab(depth); if(print) print(current); - print_rc(current->left,print,depth + 1); + print_rc(GET_PTR(current)->right,print,depth + 1); + print_tab(depth); if(print) print(GET_PTR(current)); + print_rc(GET_PTR(current)->left,print,depth + 1); } static void print_tab(int cnt) @@ -99,24 +99,24 @@ static void print_tab(int cnt) static int traverse_incremental_rc(base_treeNode_t* current, int* current_order, base_tree_callback_t cb) { - if(current == NULL) + if(GET_PTR(current) == NULL) return 0; - if(traverse_incremental_rc(current->left,current_order,cb) == MSG_BREAK_TRAVERSE) + if(traverse_incremental_rc(GET_PTR(current)->left,current_order,cb) == MSG_BREAK_TRAVERSE) return MSG_BREAK_TRAVERSE; *current_order += 1; if(cb(*current_order,current) == MSG_BREAK_TRAVERSE) return MSG_BREAK_TRAVERSE; - return traverse_incremental_rc(current->right,current_order,cb); + return traverse_incremental_rc(GET_PTR(current)->right,current_order,cb); } static int traverse_decremental_rc(base_treeNode_t* current, int* current_order, base_tree_callback_t cb) { - if(current == NULL) + if(GET_PTR(current) == NULL) return 0; - if(traverse_decremental_rc(current->right,current_order,cb) == MSG_BREAK_TRAVERSE) + if(traverse_decremental_rc(GET_PTR(current)->right,current_order,cb) == MSG_BREAK_TRAVERSE) return MSG_BREAK_TRAVERSE; *current_order += 1; - if(cb(*current_order,current) == MSG_BREAK_TRAVERSE) + if(cb(*current_order,GET_PTR(current)) == MSG_BREAK_TRAVERSE) return MSG_BREAK_TRAVERSE; - return traverse_decremental_rc(current->left,current_order,cb); + return traverse_decremental_rc(GET_PTR(current)->left,current_order,cb); } diff --git a/source/cdsl_bstree.c b/source/cdsl_bstree.c index 9e78285..81d30f1 100644 --- a/source/cdsl_bstree.c +++ b/source/cdsl_bstree.c @@ -12,13 +12,11 @@ #include #include -#define PRINT printf +static bstreeNode_t* move_up_rightmost_rc(bstreeNode_t* node); +static bstreeNode_t* move_up_leftmost_rc(bstreeNode_t* node); -static bs_treeNode_t* move_up_rightmost_rc(bs_treeNode_t* node); -static bs_treeNode_t* move_up_leftmost_rc(bs_treeNode_t* node); - -void bstree_root_init(bs_treeRoot_t* rootp) +void cdsl_bstreeRootInit(bstreeRoot_t* rootp) { if(rootp == NULL) return; @@ -26,7 +24,7 @@ void bstree_root_init(bs_treeRoot_t* rootp) } -void bstree_node_init(bs_treeNode_t* node,int key) +void cdsl_bstreeNodeInit(bstreeNode_t* node,int key) { if(node == NULL) return; @@ -36,7 +34,7 @@ void bstree_node_init(bs_treeNode_t* node,int key) } -bs_treeNode_t* bstree_insert(bs_treeRoot_t* rootp,bs_treeNode_t* item){ +bstreeNode_t* cdsl_bstreeInsert(bstreeRoot_t* rootp,bstreeNode_t* item){ if((rootp == NULL) || (item == NULL)) return NULL; if(rootp->entry == NULL) @@ -47,8 +45,8 @@ bs_treeNode_t* bstree_insert(bs_treeRoot_t* rootp,bs_treeNode_t* item){ item->left = NULL; item->right = NULL; - bs_treeNode_t* current = rootp->entry; - bs_treeNode_t* parent = NULL; + bstreeNode_t* current = rootp->entry; + bstreeNode_t* parent = NULL; while(current) { @@ -76,11 +74,11 @@ bs_treeNode_t* bstree_insert(bs_treeRoot_t* rootp,bs_treeNode_t* item){ return NULL; } -bs_treeNode_t* bstree_lookup(bs_treeRoot_t* rootp,int key) +bstreeNode_t* cdsl_bstreeLookup(bstreeRoot_t* rootp,int key) { if(rootp == NULL) return NULL; - bs_treeNode_t* current = rootp->entry; + bstreeNode_t* current = rootp->entry; while(current == NULL && (current->key != key)) { if(current->key < key) @@ -91,13 +89,13 @@ bs_treeNode_t* bstree_lookup(bs_treeRoot_t* rootp,int key) return current; } -bs_treeNode_t* bstree_delete(bs_treeRoot_t* rootp,int key) +bstreeNode_t* cdsl_bstreeDelete(bstreeRoot_t* rootp,int key) { - bs_treeNode_t* todelete = NULL; + bstreeNode_t* todelete = NULL; if((rootp == NULL) || (rootp->entry == NULL)) return NULL; - bs_treeNode_t* parent = NULL; - bs_treeNode_t** current = &rootp->entry; + bstreeNode_t* parent = NULL; + bstreeNode_t** current = &rootp->entry; while((*current) && ((*current)->key != key)) { if((*current)->key < key) @@ -133,37 +131,8 @@ bs_treeNode_t* bstree_delete(bs_treeRoot_t* rootp,int key) return todelete; } -void bstree_traverse(bs_treeRoot_t* rootp,base_tree_callback_t cb,int order) -{ - tree_traverse(&rootp->root,cb,order); -} - - -void bstree_print(bs_treeRoot_t* rootp,cdsl_generic_printer_t print) -{ - if(rootp == NULL) - return; - tree_print(&rootp->root,print); -} - -int bstree_max_depth(bs_treeRoot_t* rootp) -{ - if((rootp == NULL) || (rootp->entry == NULL)) - return 0; - return tree_max_depth(&rootp->root); -} - -int bstree_size(bs_treeRoot_t* rootp) -{ - if((rootp == NULL) || (rootp->entry == NULL)) - return 0; - return tree_size(&rootp->root); -} - - - -static bs_treeNode_t* move_up_rightmost_rc(bs_treeNode_t* node) +static bstreeNode_t* move_up_rightmost_rc(bstreeNode_t* node) { if(!node) return NULL; if(!node->right) return node; @@ -175,13 +144,13 @@ static bs_treeNode_t* move_up_rightmost_rc(bs_treeNode_t* node) * / \ / \ * c 0 a c */ - bs_treeNode_t* rightmost = move_up_rightmost_rc(node->right); + bstreeNode_t* rightmost = move_up_rightmost_rc(node->right); node->right = rightmost->left; rightmost->left = node; return rightmost; } -static bs_treeNode_t* move_up_leftmost_rc(bs_treeNode_t* node) +static bstreeNode_t* move_up_leftmost_rc(bstreeNode_t* node) { if(!node) return NULL; if(!node->left) return node; @@ -193,7 +162,7 @@ static bs_treeNode_t* move_up_leftmost_rc(bs_treeNode_t* node) * / \ / \ * 0 d d b */ - bs_treeNode_t* leftmost = move_up_leftmost_rc(node->left); + bstreeNode_t* leftmost = move_up_leftmost_rc(node->left); node->left = leftmost->right; leftmost->right = node; return leftmost; diff --git a/source/cdsl_heap.c b/source/cdsl_heap.c index e8c5776..c81075f 100644 --- a/source/cdsl_heap.c +++ b/source/cdsl_heap.c @@ -22,7 +22,7 @@ static heapNode_t* move_min_tree_down_rc(heapNode_t* current); static heapNode_t* get_leaf_node(heapNode_t* current); static heapNode_t* heapify(heapNode_t* current,heapNode_t* child); -void heap_root_init(heapRoot_t* rootp, heapType_t type) +void cdsl_heapRootInit(heapRoot_t* rootp, heapType_t type) { if(rootp == NULL) return; @@ -31,7 +31,7 @@ void heap_root_init(heapRoot_t* rootp, heapType_t type) rootp->dir = DIR_LEFT; } -void heap_node_init(heapNode_t* node, int key) +void cdsl_heapNodeInit(heapNode_t* node, int key) { if(node == NULL) return; @@ -39,7 +39,7 @@ void heap_node_init(heapNode_t* node, int key) node->key = key; } -int heap_enqueue(heapRoot_t* rootp,heapNode_t* item){ +int cdsl_heapEnqueue(heapRoot_t* rootp,heapNode_t* item){ item->left = item->right = NULL; if(!rootp) return (1 < 0); @@ -48,7 +48,7 @@ int heap_enqueue(heapRoot_t* rootp,heapNode_t* item){ return (1 > 0); } -heapNode_t* heap_deqeue(heapRoot_t* rootp){ +heapNode_t* cdsl_heapDeqeue(heapRoot_t* rootp){ if(!rootp) return NULL; heapNode_t* current = rootp->entry; @@ -67,26 +67,6 @@ heapNode_t* heap_deqeue(heapRoot_t* rootp){ } -void heap_print(heapRoot_t* rootp,cdsl_generic_printer_t print){ - if(!rootp || !rootp->entry) - return; - tree_print(&rootp->_root,print); -} - -int heap_size(heapRoot_t* rootp) -{ - if(!rootp || !rootp->entry) - return 0; - return tree_size(&rootp->_root); -} - -int heap_max_depth(heapRoot_t* rootp) -{ - if(!rootp || !rootp->entry) - return 0; - return tree_max_depth(&rootp->_root); -} - static heapNode_t* insert_from_bottom_rc(heapRoot_t* rootp, heapNode_t* current,heapNode_t* item) { diff --git a/source/cdsl_nrbtree.c b/source/cdsl_nrbtree.c new file mode 100644 index 0000000..3adf744 --- /dev/null +++ b/source/cdsl_nrbtree.c @@ -0,0 +1,784 @@ +/* + * cdsl_nrbtree.c + * + * Created on: Mar 25, 2016 + * Author: innocentevil + */ + + +#include +#include +#include "cdsl_nrbtree.h" + + +#define GET_PTR(node) ((nrbtreeNode_t*)(((uint64_t) node) & ~1)) +#define RED ((uint8_t) 1) +#define BLACK ((uint8_t) 0) +#define PAINT_RED(node) do {\ + node = (nrbtreeNode_t*) ((uint64_t) node | RED);\ +}while(0) + +#define PAINT_BLACK(node) do {\ + node = (nrbtreeNode_t*) ((uint64_t) node & ~RED);\ +}while(0) + +#define PAINT_COLOR(node, color) do {\ + PAINT_BLACK(node);\ + node = (nrbtreeNode_t*) ((uint64_t) node | color);\ +}while(0) + +#define GET_COLOR(node) ((uint32_t)(node) & 1) + +#define CTX_RIGHT ((uint8_t) 1) +#define CTX_LEFT ((uint8_t) 0) + + +#define PATTERN_WINDOW ((uint8_t) 0x3) + +#define PATTERN_RED_BLACK ((uint8_t) 0x2) +#define PATTERN_RED_RED ((uint8_t) 0x3) +#define PATTERN_BLACK_RED ((uint8_t) 0x1) +#define PATTERN_BLACK_BLACK ((uint8_t) 0x0) + +#define BB_ALERT ((uint8_t) 0x1) + +#define PATTERN_RIGHT_RIGHT ((uint8_t) 0x3) // right-right +#define PATTERN_RIGHT_LEFT ((uint8_t) 0x2) // right-left +#define PATTERN_LEFT_RIGHT ((uint8_t) 0x1) // left-right +#define PATTERN_LEFT_LEFT ((uint8_t) 0x0) // left-left + +const char* COLOR_STRING[] = { + "BLACK", + "RED" +}; + + +static int max_depth_rc(nrbtreeNode_t* node); +static nrbtreeNode_t* rotate_left(nrbtreeNode_t* gparent_c); +static nrbtreeNode_t* rotate_right(nrbtreeNode_t* gparent_c); +static nrbtreeNode_t* update_color(nrbtreeNode_t* node_c); +static nrbtreeNode_t* resolve_red_red(nrbtreeNode_t* gparent_c,uint8_t color_ctx, uint8_t dir_ctx); +static nrbtreeNode_t* resolve_black_black(nrbtreeNode_t* parent_c, uint8_t color_ctx, uint8_t dir_ctx, nrbtreeNode_t** ctx); + +static nrbtreeNode_t* up_from_rightmost_rc(nrbtreeNode_t* node,nrbtreeNode_t** rm); +static nrbtreeNode_t* up_from_leftmost_rc(nrbtreeNode_t* node, nrbtreeNode_t** lm); + +static BOOL replace_from_next(nrbtreeNode_t** node); +static BOOL replace_from_prev(nrbtreeNode_t** node); + +static void print_tab(int cnt); +static void node_print_rc(nrbtreeNode_t* node,int order); + + +void cdsl_nrbtreeRootInit(nrbtreeRoot_t* rootp) { + if(rootp == NULL) + return; + rootp->entry = NULL; +} + +void cdsl_nrbtreeNodeInit(nrbtreeNode_t* node, rb_key_t key) { + if(node == NULL) + return; + node->left = node->right = NULL; + node->key = key; +} + + + +nrbtreeNode_t* cdsl_nrbtreeInsert(nrbtreeRoot_t* rootp,nrbtreeNode_t* item) { + if(!rootp || !item) + return NULL; + nrbtreeNode_t** cur_node = &rootp->entry; + nrbtreeNode_t** parent = NULL; + nrbtreeNode_t** gparent = NULL; + nrbtreeNode_t** ggp = NULL; + uint8_t dir_ctx = 0; + uint8_t color_ctx = 0; + if(!GET_PTR(*cur_node)) { + rootp->entry = item; + return item; + } + + while(*cur_node) + /* + * leaf node is always null + * so you don't need to mask out LSB of pointer (meaning GET_PTR() macro) + */ + { + if(GET_PTR(*cur_node)->key > item->key) + { + if(!GET_PTR(*cur_node)->left) + { + // add item here + GET_PTR(*cur_node)->left = item; + PAINT_RED(GET_PTR(*cur_node)->left); + // update context info + color_ctx |= RED; + dir_ctx |= CTX_LEFT; + + if((color_ctx & PATTERN_WINDOW) == PATTERN_RED_RED) + { + goto RESOLVE_REDRED; + } + return item; + } + // go to left + ggp = gparent; + gparent = parent; + parent = cur_node; + cur_node = &(GET_PTR(*cur_node)->left); + color_ctx |= GET_COLOR(*cur_node); + dir_ctx |= CTX_LEFT; + } + else + { + if(!GET_PTR(*cur_node)->right) + { + GET_PTR(*cur_node)->right = item; + PAINT_RED(GET_PTR(*cur_node)->right); + + color_ctx |= RED; + dir_ctx |= CTX_RIGHT; + + if((color_ctx & PATTERN_WINDOW) == PATTERN_RED_RED) + { + goto RESOLVE_REDRED; + } + return item; + } + // go to right + ggp = gparent; + gparent = parent; + parent = cur_node; + cur_node = &(GET_PTR(*cur_node)->right); + color_ctx |= GET_COLOR(*cur_node); + dir_ctx |= CTX_RIGHT; + } + // shift ctx left + dir_ctx <<= 1; + color_ctx <<= 1; + } + +RESOLVE_REDRED: + + /* + * hierarchical order is like below + * so grand parent of new item is 'parent' + * gparent - parent - cur_node - item + */ + + *parent = resolve_red_red(*parent, color_ctx,dir_ctx); + color_ctx >>= 3; + color_ctx <<= 1; + color_ctx |= GET_COLOR(*parent); + dir_ctx >>= 2; + + if((color_ctx & PATTERN_WINDOW) == PATTERN_RED_RED) + { + *ggp = resolve_red_red(*ggp, color_ctx,dir_ctx); + } + PAINT_BLACK(rootp->entry); + return item; +} + +nrbtreeNode_t* cdsl_nrbtreeLookup(nrbtreeRoot_t* rootp, rb_key_t key) { + if(!rootp) + return NULL; + nrbtreeNode_t* cur_node = rootp->entry; // always black so don't need to use GET_PTR() macro + while(cur_node) { + if(GET_PTR(cur_node)->key > key) { + cur_node = GET_PTR(cur_node)->left; + }else if(GET_PTR(cur_node)->key < key) { + cur_node = GET_PTR(cur_node)->right; + }else { + return GET_PTR(cur_node); + } + } + return NULL; +} + +/* + * 1> rmv node is leaf node + * gp + * \ + * p + * / \ + * s rmv + * / \ / \ + * + * + */ + +nrbtreeNode_t* cdsl_nrbtreeDelete(nrbtreeRoot_t* rootp, rb_key_t key) +{ + if(!rootp) + return NULL; + if(!GET_PTR(rootp->entry)) + return NULL; + uint8_t color_ctx = 0; + uint8_t dir_ctx = 0; + uint32_t res = 0; + nrbtreeNode_t** cur_node = &rootp->entry; + nrbtreeNode_t** parent = NULL; + nrbtreeNode_t** gparent = NULL; + + nrbtreeNode_t* rmv = NULL; + + while(*cur_node) + { + if(GET_PTR(*cur_node)->key > key) + { + dir_ctx |= CTX_LEFT; + color_ctx |= GET_COLOR(*cur_node); + gparent = parent; + parent = cur_node; + cur_node = &GET_PTR(*cur_node)->left; + } + else if(GET_PTR(*cur_node)->key < key) + { + dir_ctx |= CTX_RIGHT; + color_ctx |= GET_COLOR(*cur_node); + gparent = parent; + parent = cur_node; + cur_node = &GET_PTR(*cur_node)->right; + } + else + { + /* + * matched node found + */ + if(!GET_PTR(GET_PTR(*cur_node)->left) && !GET_PTR(GET_PTR(*cur_node)->right)) + { + + rmv = *cur_node; + if(GET_COLOR(rmv) == RED) + { + *cur_node = NULL; + return GET_PTR(rmv); + } + else + { + /* + * try to resolve black black with sub-tree whose root is parent of black black + * + * parent + * / \ + * cur cur + * + * relative direction of cur from parent(right / left) is checked in resolve_black_black routine + */ + + res = PATTERN_BLACK_BLACK; + *cur_node = resolve_black_black(*parent, color_ctx, dir_ctx, &rmv); + if(!((uint64_t) *parent & BB_ALERT)) + { + *parent = *cur_node; + *cur_node = NULL; + return GET_PTR(rmv); + } + + /* + * if fail to resolve with sub-tree whose root is parent of black black + * retry with sub-tree whose root is grand parent of black-black's origin. + * + * grand parent + * / \ + * parent parent + * + */ + *cur_node = resolve_black_black(*gparent, color_ctx >> 1, dir_ctx >> 1, &rmv); + if(!((uint64_t) rmv & BB_ALERT)) + { + *gparent = *cur_node; + *cur_node = NULL; + return GET_PTR(rmv); + } + fprintf(stderr, "two step is maximum \n"); + exit(1); + } + + } + else if(GET_PTR(GET_PTR(*cur_node)->left)) + { + /* + * non-leaf node with left child + * rightmost-end leaf is chosen as replacement for removed + */ + rmv = *cur_node; + GET_PTR(*cur_node)->left = up_from_rightmost_rc(rmv->left, cur_node); + GET_PTR(*cur_node)->right = GET_PTR(rmv)->right; + PAINT_COLOR(*cur_node,GET_COLOR(rmv)); + return GET_PTR(rmv); + } + else + { + /* + * non-leaf node with right child + * leftmost-end is chosen as replacement for removed + */ + rmv = *cur_node; + GET_PTR(*cur_node)->right = up_from_leftmost_rc(rmv->right, cur_node); + GET_PTR(*cur_node)->left = GET_PTR(rmv)->left; + PAINT_COLOR(*cur_node,GET_COLOR(rmv)); + return GET_PTR(rmv); + } + } + } + return NULL; +} + + +#ifdef __DBG +void cdsl_nrbtreePrint_dev (nrbtreeRoot_t* root) +{ + if(!root) + return; + node_print_rc(root->entry, 0); + +} +#endif + +static BOOL replace_from_next(nrbtreeNode_t** node) +{ + if(!node) + return FALSE; + if(!GET_PTR(*node)) + return FALSE; + if(!GET_PTR(GET_PTR(*node)->right)) + return FALSE; + + nrbtreeNode_t** cur_node = &(GET_PTR(*node)->right); + nrbtreeNode_t** parent = node; + nrbtreeNode_t** gparent = NULL; + + uint8_t color_ctx = GET_COLOR(*cur_node); + uint8_t dir_ctx = CTX_RIGHT; + + + while(GET_PTR(*cur_node)) + { + color_ctx <<= 1; + dir_ctx <<= 1; + + color_ctx |= GET_COLOR(*cur_node); + dir_ctx |= CTX_LEFT; + + gparent = parent; + parent = cur_node; + cur_node = &GET_PTR(*cur_node)->left; + } + /* + * parent is actually the replacement itself + * cur_node is pointing null node + */ + if(parent == node) { + parent = (nrbtreeNode_t**) *node; + *node = NULL; + /* + * don't need to update color + * return false + */ + return FALSE; + } + + switch(color_ctx & PATTERN_WINDOW) + { + case PATTERN_RED_RED: + case PATTERN_BLACK_RED: + PAINT_COLOR(*parent, GET_COLOR(*node)); + GET_PTR(*parent)->left = GET_PTR(*node)->left; + GET_PTR(*parent)->right = GET_PTR(*node)->right; + *node = *parent; + return TRUE; + case PATTERN_BLACK_BLACK: + break; + case PATTERN_RED_BLACK: + break; + } +} + +static BOOL replace_from_prev(nrbtreeNode_t** node) +{ + +} + +static void print_tab(int cnt){ + while(cnt--) + printf("\t"); +} + +static void node_print_rc(nrbtreeNode_t* node,int order) { + if(!GET_PTR(node)) + { + print_tab(order); + printf("NIL(black) \n"); + return; + } + node_print_rc(GET_PTR(node)->right, order + 1); + print_tab(order); printf("%s node : %d / order %d \n", COLOR_STRING[GET_COLOR(node)], GET_PTR(node)->key, order); + node_print_rc(GET_PTR(node)->left, order + 1); +} + + +static nrbtreeNode_t* rotate_left(nrbtreeNode_t* gparent_c) +{ + /* + * n0(gparent_c) n1 + * / \ --> / \ + * n2 n1 n0 n4 + * / \ / \ \ + * n3 n4 n2 n3 n1 + */ + if(!GET_PTR(gparent_c)) + return NULL; + nrbtreeNode_t* ngp = GET_PTR(gparent_c)->right; + GET_PTR(gparent_c)->right = GET_PTR(ngp)->left; + GET_PTR(ngp)->left = update_color(gparent_c); + + return update_color(ngp); +} + +static nrbtreeNode_t* rotate_right(nrbtreeNode_t* gparent_c) +{ + /* + * n0(gparent_c) n2 + * / \ --> / \ + * n2 n1 n3 n0 + * / \ / \ + * n3 n4 n4 n1 + */ + if(!GET_PTR(gparent_c)) + return NULL; + nrbtreeNode_t* ngp = GET_PTR(gparent_c)->left; + GET_PTR(gparent_c)->left = GET_PTR(ngp)->right; + GET_PTR(ngp)->right = update_color(gparent_c); + + return update_color(ngp); +} + +static nrbtreeNode_t* update_color(nrbtreeNode_t* node_c) +{ + /* + * r0 b0 + * / \ / \ + * b1 b2 r1 r2 + */ + if(!GET_PTR(node_c)) + return NULL; + + if((GET_COLOR(GET_PTR(node_c)->left) == BLACK) && (GET_COLOR(GET_PTR(node_c)->right) == BLACK)) + { + return (nrbtreeNode_t*) ((uint64_t)node_c | RED); + } + else + { + return (nrbtreeNode_t*) ((uint64_t)node_c & ~RED); + } + return node_c; +} + +static int max_depth_rc(nrbtreeNode_t* node) +{ + if(!GET_PTR(node)) + return 0; + int a,b; + a = max_depth_rc(GET_PTR(node)->left); + b = max_depth_rc(GET_PTR(node)->right); + return a > b? a : b; +} + + +static nrbtreeNode_t* resolve_red_red(nrbtreeNode_t* gparent_c,uint8_t color_ctx, uint8_t dir_ctx) +{ + /* [ ... | 3 bit | 2 bit | 1 bit | 0 bit ] + * bit pattern of ctx [ ... | ggp | gp | p | new ] + */ + if(!GET_PTR(gparent_c)) + return gparent_c; + if((GET_COLOR(GET_PTR(gparent_c)->left) == RED) && (GET_COLOR(GET_PTR(gparent_c)->right) == RED)) + { + /* + * r0 or b0 r0 + * / \ / \ + * r1 r2 (repaint r1,r2 -> b1,b2)---> b1 b2 + * / / + * r3(new node) r3(new node) + */ + PAINT_BLACK(GET_PTR(gparent_c)->left); + PAINT_BLACK(GET_PTR(gparent_c)->right); + PAINT_RED(gparent_c); + return gparent_c; + } + switch(dir_ctx & PATTERN_WINDOW) + { + case PATTERN_LEFT_RIGHT: + /* + * resolve left-right sequence into left-left + * gp gp + * / \ / + * left .. ---> left + * / \ / \ + * .. new new + */ + GET_PTR(gparent_c)->left = rotate_left(GET_PTR(gparent_c)->left); + /* + * rotate performed to make left-left sequence + * so now PATTERN_LEFT_LEFT case + * I think pass-through can be used here by just omit break statement + * SO PLEASE DON'T PUT BREAK HERE. IT'S INTENDED + */ + case PATTERN_LEFT_LEFT: + return rotate_right(gparent_c); + case PATTERN_RIGHT_LEFT: + /* + * resolve right-left sequence into left-left + * gp gp + * / \ / \ + * .. right ---> .. right + * / \ / \ + * new .. .. new + */ + GET_PTR(gparent_c)->right = rotate_right(GET_PTR(gparent_c)->right); + /* + * rotate performed to make right-right sequence + * so now PATTERN_RIGHT_RIGHT case + * I think pass-through can be used here by just omit break statement + * SO PLEASE DON'T PUT BREAK HERE. IT'S INTENDED + */ + case PATTERN_RIGHT_RIGHT: + return rotate_left(gparent_c); + } + return NULL; +} + +/** + * try to resolve black-black situation + * in this context, parent_c is parent of double blacked node + * and it's actually root of sub-tree where double black is dealt with + * if there is any rotation, new root of sub-tree will be returned + * if there is no rotation, so root of sub-tree is kept same, just return original parent_c + * if fail to resolve double black return original parent but write PATTERN_BLACK_BLACK into ctx + * + * by checking ctx, caller knows the result of resolving operation + * + */ +static nrbtreeNode_t* resolve_black_black(nrbtreeNode_t* parent_c, uint8_t color_ctx, uint8_t dir_ctx, nrbtreeNode_t** ctx) +{ + if(!parent_c) + return NULL; + nrbtreeNode_t** sibling = NULL; + uint8_t sibling_dir_ctx = 0; + + if(dir_ctx >> 1 == CTX_LEFT) + { + /* + * check right sibling + */ + sibling_dir_ctx |= CTX_RIGHT; + sibling_dir_ctx <<= 1; + sibling = &GET_PTR(parent_c)->right; + if((GET_COLOR(GET_PTR(*sibling)->left) == BLACK) \ + && (GET_COLOR(GET_PTR(*sibling)->right) == BLACK)) + { + if(GET_COLOR(*sibling) == BLACK) + { + /* + * black sibling with black children + * + * depend on parent color there are two option + */ + if(GET_COLOR(parent_c) == BLACK) + { + /* + * parent is black + * then all the nodes in sub-tree are black + * in this case, can't resolved within this sub-tree + */ + return parent_c; + } + else + { + /* + * parent is red + * then just repaint the sibling into red and black-black resolved + */ + + PAINT_BLACK(parent_c); + PAINT_COLOR(*sibling, RED); + PAINT_COLOR(*ctx, !BB_ALERT); + return parent_c; + } + } + else + { + /* + * red sibling with black children + * + * paint sibling black + */ + PAINT_BLACK(*sibling); + PAINT_COLOR(*ctx, !BB_ALERT); + return parent_c; + } + } + else + { + /* + * one or more child of sibling(right) is red + * obviously, the sibling is black because successive red + * is not allowed in red black tree + * so we assume sibling is black here + */ + + if(GET_COLOR(GET_PTR(*sibling)->right) == RED) + { + parent_c = rotate_left(parent_c); + PAINT_BLACK(GET_PTR(parent_c)->right); + PAINT_COLOR(*ctx, !BB_ALERT); + return parent_c; + } + else + { + *sibling = rotate_right(*sibling); + parent_c = rotate_left(parent_c); + //TODO: check whether parent don't be required to be repaint into black + PAINT_COLOR(*ctx, !BB_ALERT); + return parent_c; + } + } + } + else + { + /* + * check right sibling + */ + sibling_dir_ctx |= CTX_LEFT; + sibling_dir_ctx <<= 1; + sibling = &GET_PTR(parent_c)->left; + if((GET_COLOR(GET_PTR(*sibling)->left) == BLACK) \ + && (GET_COLOR(GET_PTR(*sibling)->right) == BLACK)) + { + if(GET_COLOR(*sibling) == BLACK) + { + /* + * black sibling with black children + * + * depend on parent color there are two option + */ + if(GET_COLOR(parent_c) == BLACK) + { + /* + * parent is black + * then all the nodes in sub-tree are black + * in this case, can't resolved within this sub-tree + */ + PAINT_COLOR(*sibling, RED); + return parent_c; + } + else + { + /* + * parent is red + * then just repaint the sibling into red and black-black resolved + */ + + PAINT_BLACK(parent_c); + PAINT_COLOR(*sibling, RED); + PAINT_COLOR(*ctx, !BB_ALERT); + return parent_c; + } + } + else + { + /* + * red sibling with black children + * + * paint sibling blakc + */ + PAINT_BLACK(*sibling); + PAINT_COLOR(*ctx, !BB_ALERT); + return parent_c; + } + } + else + { + /* + * one or more child of sibling(right) is red + * obviously, the sibling is black because successive red + * is not allowed in red black tree + * so we assume sibling is black here + */ + + if(GET_COLOR(GET_PTR(*sibling)->left) == RED) + { + parent_c = rotate_right(parent_c); + PAINT_BLACK(GET_PTR(parent_c)->left); + PAINT_COLOR(*ctx, !BB_ALERT); + return parent_c; + } + else + { + *sibling = rotate_left(*sibling); + parent_c = rotate_right(parent_c); + //TODO: check whether parent don't be required to be repaint into black + PAINT_COLOR(*ctx, !BB_ALERT); + return parent_c; + } + } + } + return NULL; +} + +static nrbtreeNode_t* up_from_rightmost_rc(nrbtreeNode_t* node,nrbtreeNode_t** rm) +{ + if(!GET_PTR(node)->right) + { + if(GET_COLOR(node) != RED) + { + /* + * black black case, + * set BB_ALERT in pointer and return + */ + *rm = (nrbtreeNode_t*) ((uint64_t)node | BB_ALERT); + } + else + { + *rm = (nrbtreeNode_t*) ((uint64_t)node & ~BB_ALERT); + } + return NULL; + } + + GET_PTR(node)->right = up_from_rightmost_rc(GET_PTR(node)->right, rm); + if((uint64_t) *rm & BB_ALERT) + { + node = resolve_black_black(node, (GET_COLOR(node) << 1),((CTX_RIGHT << 1) | CTX_RIGHT),rm); + } + return node; +} + +static nrbtreeNode_t* up_from_leftmost_rc(nrbtreeNode_t* node, nrbtreeNode_t** lm) +{ + if(!GET_PTR(node)->left) + { + if(GET_COLOR(node) != RED) + { + /* + * black black case + */ + *lm = (nrbtreeNode_t*) ((uint64_t) node | BB_ALERT); + } + else + { + *lm = (nrbtreeNode_t*) ((uint64_t) node & ~BB_ALERT); + } + return NULL; + } + + GET_PTR(node)->left = up_from_leftmost_rc(GET_PTR(node)->left, lm); + if((uint64_t) *lm & BB_ALERT) + { + node = resolve_black_black(node, (GET_COLOR(node) << 1),((CTX_LEFT << 1) | CTX_LEFT),lm); + } + return node; +} + diff --git a/source/cdsl_rbtree.c b/source/cdsl_rbtree.c index 30183ab..eea2503 100644 --- a/source/cdsl_rbtree.c +++ b/source/cdsl_rbtree.c @@ -12,18 +12,18 @@ -#define BLACK ((unsigned) (1 > 0)) -#define RED ((unsigned) (1 < 0)) +#define BLACK ((unsigned) (1 > 0)) +#define RED ((unsigned) (1 < 0)) -#define CLEAN ((uint8_t) 0) -#define COLLISION ((uint8_t) 1) -#define DIR_RIGHT ((uint8_t) 2) -#define DIR_LEFT ((uint8_t) 3) +#define CLEAN ((uint8_t) 0) +#define COLLISION ((uint8_t) 1) +#define DIR_RIGHT ((uint8_t) 2) +#define DIR_LEFT ((uint8_t) 3) -#define RB_NIL ((rb_treeNode_t*) &NIL_NODE) -#define IS_LEAF_NODE(node) ((node->right == RB_NIL) || (node->left == RB_NIL)) +#define RB_NIL ((rb_treeNode_t*) &NIL_NODE) +#define IS_LEAF_NODE(node) ((node->right == RB_NIL) || (node->left == RB_NIL)) const static rb_treeNode_t NIL_NODE = { @@ -375,7 +375,7 @@ static rb_treeNode_t* insert_r(rb_treeNode_t* parent,rb_treeNode_t* item,uint8_t { if(parent->left->color == parent->right->color){ parent->right->color = !parent->left->color; - parent->left->color =!parent->left->color; + parent->left->color = !parent->left->color; if((parent->left->color == BLACK) && (parent->right->color == BLACK)) parent->color = RED; *context = CLEAN; diff --git a/source/cdsl_spltree.c b/source/cdsl_spltree.c index 8c01820..f278ddc 100644 --- a/source/cdsl_spltree.c +++ b/source/cdsl_spltree.c @@ -18,7 +18,6 @@ #define NOT_FOUND ((uint8_t) 5) #define FOUND ((uint8_t) 6) -static void print_r(spltreeNode_t* current,int depth); static spltreeNode_t* insert_r(spltreeNode_t* current,spltreeNode_t* item,uint8_t* context); static spltreeNode_t* lookup_r(spltreeNode_t* current,int key,uint8_t* context,BOOL splay); static spltreeNode_t* delete_r(spltreeNode_t* current,int key,uint8_t* context,spltreeNode_t** found); @@ -28,91 +27,62 @@ static spltreeNode_t* rotateLeft(spltreeNode_t* parent); static spltreeNode_t* rotateRight(spltreeNode_t* parent); +void cdsl_spltreeRootInit(spltreeRoot_t* root) +{ + if(!root) + return; + root->entry = NULL; +} + + void cdsl_spltreeNodeInit(spltreeNode_t* node,int key){ node->key = key; node->left = node->right = NULL; } -void cdsl_spltreeInsert(spltreeNode_t** root,spltreeNode_t* item){ +void cdsl_spltreeInsert(spltreeRoot_t* root,spltreeNode_t* item){ if(!root) return; - if(!(*root)){ - *root = item; + if(!root->entry){ + root->entry = item; return; } uint8_t context; context = ROOT; - *root = insert_r(*root,item,&context); + root->entry = insert_r(root->entry,item,&context); } -spltreeNode_t* cdsl_spltreeLookup(spltreeNode_t** root,int key,BOOL splay){ - if(!root || !(*root)) +spltreeNode_t* cdsl_spltreeLookup(spltreeRoot_t* root,int key,BOOL splay){ + if(!root) return NULL; uint8_t context; context = ROOT; - return *root = lookup_r(*root,key,&context,splay); + return root->entry = lookup_r(root->entry,key,&context,splay); } -spltreeNode_t* cdsl_spltreeLookupLargest(spltreeNode_t** root,BOOL splay){ - if(!root || !(*root)) +spltreeNode_t* cdsl_spltreeLookupLargest(spltreeRoot_t* root,BOOL splay){ + if(!root) return NULL; uint8_t context = 0; - return (*root = largest_r((*root),&context,splay,FALSE)); + return (root->entry = largest_r(root->entry,&context,splay,FALSE)); } -spltreeNode_t* cdsl_spltreeLookupSmallest(spltreeNode_t** root,BOOL splay){ - if(!root || !(*root)) +spltreeNode_t* cdsl_spltreeLookupSmallest(spltreeRoot_t* root,BOOL splay){ + if(!root) return NULL; uint8_t context = 0; - return (*root = smallest_r((*root),&context,splay,FALSE)); + return (root->entry = smallest_r(root->entry,&context,splay,FALSE)); } -spltreeNode_t* cdsl_spltreeDelete(spltreeNode_t** root,int key){ - if(!root || !(*root)) +spltreeNode_t* cdsl_spltreeDelete(spltreeRoot_t* root,int key){ + if(!root) return NULL; uint8_t context = ROOT; spltreeNode_t* delNode = NULL; - *root = delete_r(*root,key,&context,&delNode); + root->entry = delete_r(root->entry,key,&context,&delNode); return delNode; } -int cdsl_spltreeSize(spltreeNode_t** root){ - if(!root || !(*root)) - return 0; - return cdsl_spltreeSize(&(*root)->right) + 1 + cdsl_spltreeSize(&(*root)->left); -} - - -int cdsl_spltreeMaxDepth(spltreeNode_t** root){ - if(!root || !(*root)) - return 0; - int max = 0; - int temp = 0; - if(max < (temp = cdsl_spltreeMaxDepth(&(*root)->left))) - max = temp; - if(max < (temp = cdsl_spltreeMaxDepth(&(*root)->right))) - max = temp; - return max + 1; -} - - -void cdsl_spltreePrint(spltreeNode_t** root){ - if(!root || !(*root)) - return; - printf("\n"); - print_r(*root,0); - printf("\n"); -} - -static void print_r(spltreeNode_t* current,int depth){ - if(!current) - return; - int k = depth; - print_r(current->right,depth + 1); - while(k--) printf("\t"); printf("{key : %d }@depth : %d\n",current->key,depth); - print_r(current->left,depth + 1); -} - static spltreeNode_t* insert_r(spltreeNode_t* current,spltreeNode_t* item,uint8_t* context){ if(!current){ diff --git a/source/recipe.mk b/source/recipe.mk index 65b228d..9baae5b 100644 --- a/source/recipe.mk +++ b/source/recipe.mk @@ -9,6 +9,7 @@ OBJ-y+= base_list\ cdsl_heap\ cdsl_rbtree\ cdsl_slist\ - cdsl_spltree + cdsl_spltree\ + cdsl_nrbtree \ No newline at end of file diff --git a/source/test/cdsl_bstree_test.c b/source/test/cdsl_bstree_test.c index 7389160..6af68f6 100644 --- a/source/test/cdsl_bstree_test.c +++ b/source/test/cdsl_bstree_test.c @@ -14,14 +14,13 @@ static int bstree_cb(int order,void* bst); static int cb_count; -static void bstree_tprint(void*); BOOL cdsl_bstreeDoTest(void) { - bs_treeNode_t bst_nodepool[TEST_SIZE]; + bstreeNode_t bst_nodepool[TEST_SIZE]; int keys[TEST_SIZE]; - bs_treeRoot_t root; + bstreeRoot_t root; cb_count = 0; - bstree_root_init(&root); + cdsl_bstreeRootInit(&root); int i = 0; int depth,depth_temp; @@ -31,62 +30,57 @@ BOOL cdsl_bstreeDoTest(void) for(i = 0;i < TEST_SIZE;i++) { keys[i] = rand() % TEST_SIZE; - bstree_node_init(&bst_nodepool[i],keys[i]); - bstree_insert(&root,&bst_nodepool[i]); - depth_temp = bstree_max_depth(&root); + cdsl_bstreeNodeInit(&bst_nodepool[i],keys[i]); + cdsl_bstreeInsert(&root,&bst_nodepool[i]); + depth_temp = cdsl_bstreeMaxDepth(&root); if(depth != depth_temp) { depth = depth_temp; } } - if(bstree_size(&root) != TEST_SIZE) + if(cdsl_bstreeSize(&root) != TEST_SIZE) return FALSE; - bs_treeNode_t* delete_node; + bstreeNode_t* delete_node; for(i = 0;i < TEST_SIZE;i++) { delete_node = NULL; - delete_node = bstree_delete(&root,keys[i]); + delete_node = cdsl_bstreeDelete(&root,keys[i]); if(!delete_node) return FALSE; if(delete_node->key != keys[i]) return FALSE; keys[i] = rand() % TEST_SIZE; - bstree_node_init(delete_node,keys[i]); - bstree_insert(&root,delete_node); + cdsl_bstreeNodeInit(delete_node,keys[i]); + cdsl_bstreeInsert(&root,delete_node); } - bstree_traverse(&root,(base_tree_callback_t) bstree_cb,ORDER_INC); + cdsl_bstreeTraverse(&root,(base_tree_callback_t) bstree_cb,ORDER_INC); if(cb_count != 2000) return FALSE; for(i = 0;i < TEST_SIZE;i++) { delete_node = NULL; - delete_node = bstree_delete(&root,keys[i]); + delete_node = cdsl_bstreeDelete(&root,keys[i]); if(!delete_node) return FALSE; if(delete_node->key != keys[i]) return FALSE; } - if(bstree_size(&root) > 0) // size should be zero + if(cdsl_bstreeSize(&root) > 0) // size should be zero return FALSE; return TRUE; } -static void bstree_tprint(void* nodep) -{ - printf("%d\n",((bs_treeNode_t*) nodep)->key); -} - static int bstree_cb(int order,void* bst) { cb_count++; -// printf("#%d : %d\n", order, ((bs_treeNode_t*) bst)->key); + __dev_log("#%d : %d\n", order, ((bstreeNode_t*) bst)->key); if(order == 2000) { return BREAK_TRAVERSE; diff --git a/source/test/cdsl_heap_test.c b/source/test/cdsl_heap_test.c index d39c332..a239d74 100644 --- a/source/test/cdsl_heap_test.c +++ b/source/test/cdsl_heap_test.c @@ -12,40 +12,39 @@ #include #include -static void print_heapnode(void*); BOOL cdsl_heapDoTest(void) { heapRoot_t root; heapNode_t nodes[100]; - heap_root_init(&root,MAX_HEAP); + cdsl_heapRootInit(&root,MAX_HEAP); int i; int max = 0,min = 0; for(i = 0; i < 100;i++) { - heap_node_init(&nodes[i], rand()); - heap_enqueue(&root, &nodes[i]); - if(heap_size(&root) != (i + 1)) + cdsl_heapNodeInit(&nodes[i], rand()); + cdsl_heapEnqueue(&root, &nodes[i]); + if(cdsl_heapSize(&root) != (i + 1)) return FALSE; } heapNode_t* node = NULL; - while((node = heap_deqeue(&root)) != NULL) + while((node = cdsl_heapDeqeue(&root)) != NULL) { if(max < node->key && max != 0) return FALSE; else max = node->key; } - heap_root_init(&root,MIN_HEAP); + cdsl_heapRootInit(&root,MIN_HEAP); for (i = 0;i < 10;i++) { - heap_node_init(&nodes[i],rand()); - heap_enqueue(&root, &nodes[i]); - if(heap_size(&root) != (i + 1)) + cdsl_heapNodeInit(&nodes[i],rand()); + cdsl_heapEnqueue(&root, &nodes[i]); + if(cdsl_heapSize(&root) != (i + 1)) return FALSE; } - while((node = heap_deqeue(&root)) != NULL) + while((node = cdsl_heapDeqeue(&root)) != NULL) { if(min > node->key && min != 0) return FALSE; @@ -56,7 +55,3 @@ BOOL cdsl_heapDoTest(void) } -static void print_heapnode(void* node) -{ - printf("%d\n", ((heapNode_t*)node)->key ); -} diff --git a/source/test/cdsl_nrbtree_test.c b/source/test/cdsl_nrbtree_test.c new file mode 100644 index 0000000..fe16b36 --- /dev/null +++ b/source/test/cdsl_nrbtree_test.c @@ -0,0 +1,65 @@ +/* + * cdsl_nrbtree_test.c + * + * Created on: Mar 26, 2016 + * Author: innocentevil + */ + + +#include "cdsl_nrbtree.h" +#include "cdsl_nrbtree_test.h" + +#include +#include +#include + +#undef TEST_SIZE +#define TEST_SIZE 20 + + +BOOL cdsl_nrbtreeDoTest(void) +{ + nrbtreeRoot_t root; + nrbtreeNode_t node_pool[TEST_SIZE]; + int keys[TEST_SIZE]; + + cdsl_nrbtreeRootInit(&root); + int i = 0; + int depth,depth_temp; + depth = 0; + depth_temp = 0; + + for(i = 0;i < TEST_SIZE;i++){ + keys[i] = rand() % TEST_SIZE; + cdsl_nrbtreeNodeInit(&node_pool[i],keys[i]); + __dev_log("%d inserted!! \n", keys[i]); + cdsl_nrbtreeInsert(&root,&node_pool[i]); + cdsl_nrbtreePrint_dev(&root); + depth_temp = cdsl_nrbtreeMaxDepth(&root); + if(depth != depth_temp){ + __dev_log("Max Depth of Tree : %d @ N : %d\n",depth_temp,i); + depth = depth_temp; + } + } + if(cdsl_nrbtreeSize(&root) != TEST_SIZE) + return FALSE; + + cdsl_nrbtreePrint_dev(&root); + nrbtreeNode_t* delete_node; + for(i = 0;i < TEST_SIZE;i++) + { + delete_node = NULL; + __dev_log("\nkey : %d will be deleted!! \n\n",keys[i]); + delete_node = cdsl_nrbtreeDelete(&root,keys[i]); + cdsl_nrbtreePrint_dev(&root); + if(!delete_node) + return FALSE; + if(delete_node->key != keys[i]) + return FALSE; +// keys[i] = rand() % TEST_SIZE; +// cdsl_nrbtreeNodeInit(delete_node,keys[i]); +// cdsl_nrbtreeInsert(&root,delete_node); + } + + return TRUE; +} diff --git a/source/test/cdsl_rbtree_test.c b/source/test/cdsl_rbtree_test.c index 377ca69..6a309f3 100644 --- a/source/test/cdsl_rbtree_test.c +++ b/source/test/cdsl_rbtree_test.c @@ -29,7 +29,7 @@ BOOL cdsl_rbtreeDoTest(void){ cdsl_rbtreeInsert(&root,&node_pool[i]); depth_temp = cdsl_rbtreeMaxDepth(&root); if(depth != depth_temp){ - // log("Max Depth of Tree : %d @ N : %d\n",depth_temp,i); + __dev_log("Max Depth of Tree : %d @ N : %d\n",depth_temp,i); depth = depth_temp; } } diff --git a/source/test/cdsl_slist_test.c b/source/test/cdsl_slist_test.c index e1b442c..e6cee9d 100644 --- a/source/test/cdsl_slist_test.c +++ b/source/test/cdsl_slist_test.c @@ -8,6 +8,7 @@ #include +#include "cdsl_slist.h" #include "cdsl_slist_test.h" #include "cdsl_rbtree_test.h" @@ -54,9 +55,3 @@ static DECLARE_COMPARE_FN(card_compare){ return ((card_t*) b)->card_num > ((card_t*) a)->card_num? b : a; } -static void printCard(void* card){ - if(!card) - return; - printf("Card : %d\n",((card_t*)card)->card_num); -} - diff --git a/source/test/cdsl_spltree_test.c b/source/test/cdsl_spltree_test.c index 75ca38f..084f231 100644 --- a/source/test/cdsl_spltree_test.c +++ b/source/test/cdsl_spltree_test.c @@ -14,23 +14,23 @@ static spltreeNode_t nodes[TEST_SIZE]; static int keys[TEST_SIZE]; -static spltreeNode_t* root; +static spltreeRoot_t root; BOOL cdsl_spltreeDoTest(void){ int i = 0; - root = NULL; - int depth,depth_temp; depth = 0; depth_temp = 0; + cdsl_spltreeRootInit(&root); + for(;i < TEST_SIZE;i++){ keys[i] = rand() % TEST_SIZE; cdsl_spltreeNodeInit(&nodes[i],keys[i]); cdsl_spltreeInsert(&root,&nodes[i]); depth_temp = cdsl_spltreeMaxDepth(&root); if(depth != depth_temp){ -// log("Max Depth of Tree : %d @ N : %d\n",depth_temp,i); + __dev_log("Max Depth of Tree : %d @ N : %d\n",depth_temp,i); depth = depth_temp; } } diff --git a/source/test/recipe.mk b/source/test/recipe.mk index 214ba47..83b897d 100644 --- a/source/test/recipe.mk +++ b/source/test/recipe.mk @@ -6,4 +6,5 @@ OBJ-y+=cdsl_bstree_test\ cdsl_list_test\ cdsl_rbtree_test\ cdsl_slist_test\ - cdsl_spltree_test \ No newline at end of file + cdsl_spltree_test\ + cdsl_nrbtree_test \ No newline at end of file