From 18d30450cd58c022e01d8beee5bd1f9524ae1d0d Mon Sep 17 00:00:00 2001 From: wjf-hs Date: Tue, 18 Jun 2024 10:08:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 36 +- datastruct.sln | 31 + datastruct/common.h | 32 + datastruct/config.h | 30 + datastruct/datastruct.vcxproj | 172 +++ datastruct/datastruct.vcxproj.filters | 87 ++ datastruct/datastruct.vcxproj.user | 4 + datastruct/demo.h | 6 + datastruct/list.c | 166 +++ datastruct/list.h | 39 + datastruct/list_test.c | 72 ++ datastruct/main.c | 15 + datastruct/queue.c | 138 +++ datastruct/queue.h | 38 + datastruct/queue_test.c | 156 +++ datastruct/rbtree.c | 1186 +++++++++++++++++++++ datastruct/rbtree.h | 49 + datastruct/rbtree_test.c | 254 +++++ datastruct/stack.c | 115 ++ datastruct/stack.h | 36 + datastruct/stack_test.c | 120 +++ datastruct/test.h | 35 + datastruct/tree.c | 1394 +++++++++++++++++++++++++ datastruct/tree.h | 69 ++ datastruct/tree_test.c | 271 +++++ 25 files changed, 4548 insertions(+), 3 deletions(-) create mode 100644 datastruct.sln create mode 100644 datastruct/common.h create mode 100644 datastruct/config.h create mode 100644 datastruct/datastruct.vcxproj create mode 100644 datastruct/datastruct.vcxproj.filters create mode 100644 datastruct/datastruct.vcxproj.user create mode 100644 datastruct/demo.h create mode 100644 datastruct/list.c create mode 100644 datastruct/list.h create mode 100644 datastruct/list_test.c create mode 100644 datastruct/main.c create mode 100644 datastruct/queue.c create mode 100644 datastruct/queue.h create mode 100644 datastruct/queue_test.c create mode 100644 datastruct/rbtree.c create mode 100644 datastruct/rbtree.h create mode 100644 datastruct/rbtree_test.c create mode 100644 datastruct/stack.c create mode 100644 datastruct/stack.h create mode 100644 datastruct/stack_test.c create mode 100644 datastruct/test.h create mode 100644 datastruct/tree.c create mode 100644 datastruct/tree.h create mode 100644 datastruct/tree_test.c diff --git a/.gitignore b/.gitignore index c6127b3..2f75ee7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,33 @@ + +# chm +*.chm + +# SI4 +SIP.si4project/ + +# python +__pycache__/ + +# .vs +*.vs +Debug/ +Release/ +x86/ +x64/ +ARM/ + +# .vscode +.vscode/ + +# MDK-ARM +DebugConfig/ +Listings/ +Objects/ +# *.uvoptx +*.uvguix.* +*.scvd +JLinkLog.txt + # Prerequisites *.d @@ -17,19 +47,19 @@ *.pch # Libraries -*.lib +# *.lib *.a *.la *.lo # Shared objects (inc. Windows DLLs) -*.dll +# *.dll *.so *.so.* *.dylib # Executables -*.exe +# *.exe *.out *.app *.i*86 diff --git a/datastruct.sln b/datastruct.sln new file mode 100644 index 0000000..c07e05c --- /dev/null +++ b/datastruct.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.757 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "datastruct", "datastruct\datastruct.vcxproj", "{3990515A-48AA-4CFF-9014-C35B11F02C87}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3990515A-48AA-4CFF-9014-C35B11F02C87}.Debug|x64.ActiveCfg = Debug|x64 + {3990515A-48AA-4CFF-9014-C35B11F02C87}.Debug|x64.Build.0 = Debug|x64 + {3990515A-48AA-4CFF-9014-C35B11F02C87}.Debug|x86.ActiveCfg = Debug|Win32 + {3990515A-48AA-4CFF-9014-C35B11F02C87}.Debug|x86.Build.0 = Debug|Win32 + {3990515A-48AA-4CFF-9014-C35B11F02C87}.Release|x64.ActiveCfg = Release|x64 + {3990515A-48AA-4CFF-9014-C35B11F02C87}.Release|x64.Build.0 = Release|x64 + {3990515A-48AA-4CFF-9014-C35B11F02C87}.Release|x86.ActiveCfg = Release|Win32 + {3990515A-48AA-4CFF-9014-C35B11F02C87}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {65951581-EEEC-4CFD-AC52-2B52711979E5} + EndGlobalSection +EndGlobal diff --git a/datastruct/common.h b/datastruct/common.h new file mode 100644 index 0000000..fb4e4fb --- /dev/null +++ b/datastruct/common.h @@ -0,0 +1,32 @@ + +#ifndef _DEMO_H_ +#define _DEMO_H_ + +#include +#include +#include +#include + + +#include "config.h" + +// --------------------------------------- +#if RBTREE == 1 +#include "rbtree.h" + typedef prbtree_node_t stack_data_t; + typedef prbtree_node_t queue_data_t; + + typedef int list_data_t; +#elif AVLTREE == 1 +#include "tree.h" + typedef ptree_node_t stack_data_t; + typedef ptree_node_t queue_data_t; +#else + typedef int stack_data_t; + typedef int queue_data_t; + typedef int list_data_t; +#endif + + +#endif // _DEMO_H_ + diff --git a/datastruct/config.h b/datastruct/config.h new file mode 100644 index 0000000..c18c13d --- /dev/null +++ b/datastruct/config.h @@ -0,0 +1,30 @@ + +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#include +#include +#include +#include + + +// optional +#define RBTREE 1 +#define AVLTREE 0 +#define RAVLTREE 0 // avl tree by recursion +#define QUEUE 1 +#define STACK 1 +#define LIST 1 + + +// -------------------------------------------------- +#if RBTREE == 1 && AVLTREE == 1 +#error "Rbtree and avltree cannot coexist" +#endif + +#if RAVLTREE == 1 && AVLTREE == 1 +#error "Recursive avltree and avltree cannot coexist" +#endif + +#endif // _CONFIG_H_ + diff --git a/datastruct/datastruct.vcxproj b/datastruct/datastruct.vcxproj new file mode 100644 index 0000000..df2fd4d --- /dev/null +++ b/datastruct/datastruct.vcxproj @@ -0,0 +1,172 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {3990515A-48AA-4CFF-9014-C35B11F02C87} + Win32Proj + datastruct + 10.0.17763.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + true + Console + + + + + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + true + Console + + + + + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + true + true + true + Console + + + + + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + true + true + true + Console + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/datastruct/datastruct.vcxproj.filters b/datastruct/datastruct.vcxproj.filters new file mode 100644 index 0000000..0d59ba4 --- /dev/null +++ b/datastruct/datastruct.vcxproj.filters @@ -0,0 +1,87 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {03f28c38-31fa-4cef-97f5-67fbe3b4a2e2} + + + {9b4f0950-addb-4047-9212-61b574e2b25d} + + + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 测试 + + + 测试 + + + 测试 + + + 测试 + + + 测试 + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 示例 + + + 测试 + + + 头文件 + + + 头文件 + + + \ No newline at end of file diff --git a/datastruct/datastruct.vcxproj.user b/datastruct/datastruct.vcxproj.user new file mode 100644 index 0000000..be25078 --- /dev/null +++ b/datastruct/datastruct.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/datastruct/demo.h b/datastruct/demo.h new file mode 100644 index 0000000..bed27c4 --- /dev/null +++ b/datastruct/demo.h @@ -0,0 +1,6 @@ + +#ifndef _DEMO_H_ +#define _DEMO_H_ + + +#endif diff --git a/datastruct/list.c b/datastruct/list.c new file mode 100644 index 0000000..ebc5c88 --- /dev/null +++ b/datastruct/list.c @@ -0,0 +1,166 @@ + +#include "list.h" + +bool list_init(plist_t *list) +{ + *list = (plist_t)malloc(sizeof(list_t)); + if(*list == NULL) + { + return false; + } + (*list)->data = (list_data_t)0; + (*list)->prev = *list; + (*list)->next = *list; + return true; +} + +void list_destroy(plist_t *list) +{ + if (*list != NULL) + { + list_clear(*list); + free(*list); + (*list)->prev = NULL; + (*list)->next = NULL; + *list = NULL; + } +} + +bool list_empty(plist_t list) +{ + return (list == NULL || (list->prev == list && list->next == list)) ? true : false; +} + +void list_clear(plist_t list) +{ + if(!list_empty(list)) + { + plist_t p = list->next; + plist_t ptmp = p; + while(p != list) + { + ptmp = p; + p->prev->next = p->next; + p->next->prev = p->prev; + p = p->next; + + // finally free memory + free(ptmp); + ptmp->prev = NULL; + ptmp->next = NULL; + } + } +} + +bool list_insert_head(plist_t list, list_data_t data) +{ + plist_t new_item; + if(list == NULL) + { + return false; + } + + new_item = (plist_t)malloc(sizeof(list_t)); + if(new_item == NULL) + { + return false; + } + new_item->data = data; + + // insert from head + new_item->next = list->next; + new_item->prev = list->next->prev; + list->next->prev = new_item; + list->next = new_item; + + return true; +} + +bool list_insert_tail(plist_t list, list_data_t data) +{ + plist_t new_item; + if(list == NULL) + { + return false; + } + + new_item = (plist_t)malloc(sizeof(list_t)); + if(new_item == NULL) + { + return false; + } + new_item->data = data; + + // insert from tail + new_item->prev = list->prev; + new_item->next = list->prev->next; + list->prev->next = new_item; + list->prev = new_item; + + return true; +} + +bool list_delete(plist_t list, list_data_t data) +{ + if(!list_empty(list)) + { + plist_t p = list; + while(p->next != list) + { + p = p->next; + if(p->data == data) + { + // delete the item + p->prev->next = p->next; + p->next->prev = p->prev; + free(p); + p->prev = NULL; + p->next = NULL; + return true; + } + } + } + return false; +} + +uint32_t list_count(plist_t list) +{ + uint32_t count = 0; + if(!list_empty(list)) + { + plist_t p = list; + while(p->next != list) + { + p = p->next; + count++; + } + } + return count; +} + +void list_traversal_sequence(plist_t list, list_data_disp_t disp) +{ + if(!list_empty(list)) + { + plist_t p = list->next; + while(p != list) + { + disp(p->data); + p = p->next; + } + } +} + +void list_traversal_reversed(plist_t list, list_data_disp_t disp) +{ + if(!list_empty(list)) + { + plist_t p = list->prev; + while(p != list) + { + disp(p->data); + p = p->prev; + } + } +} + diff --git a/datastruct/list.h b/datastruct/list.h new file mode 100644 index 0000000..23b88ab --- /dev/null +++ b/datastruct/list.h @@ -0,0 +1,39 @@ +#ifndef _LIST_H_ +#define _LIST_H_ + +#include "common.h" + +#define LIST_TEST + +#ifdef LIST_TEST + typedef int list_data_t; +#else + typedef int list_data_t; +#endif + +typedef struct _list_t +{ + list_data_t data; + struct _list_t * prev; + struct _list_t * next; +}list_t,*plist_t; + +typedef void (*list_data_disp_t)(list_data_t data); + + +bool list_init(plist_t *list); +void list_destroy(plist_t *list); +bool list_empty(plist_t list); +void list_clear(plist_t list); +bool list_insert_head(plist_t list, list_data_t data); +bool list_insert_tail(plist_t list, list_data_t data); +bool list_delete(plist_t list, list_data_t data); +uint32_t list_count(plist_t list); +void list_traversal_sequence(plist_t list, list_data_disp_t disp); +void list_traversal_reversed(plist_t list, list_data_disp_t disp); + + + +extern void list_test(void); + +#endif // _LIST_H_ diff --git a/datastruct/list_test.c b/datastruct/list_test.c new file mode 100644 index 0000000..35f8ddd --- /dev/null +++ b/datastruct/list_test.c @@ -0,0 +1,72 @@ + +#include "test.h" + +#if LIST_TEST == 1 + +static void list_data_display(list_data_t data) +{ + printf("%d ", data); +} + +void list_test(void) +{ + int32_t i = 0; + list_data_t dat[10] = { 0,1,2,3,4,5,6,7,8,9 }; + plist_t list; + if (!list_init(&list)) + { + printf("list_init failureed!\n"); + } + printf("list_init success!\n"); + if (!list_empty(list)) + { + printf("list is empty!\n"); + } + for (i = 0; i < 10; i++) + { + list_insert_tail(list, dat[i]); + } + list_traversal_sequence(list, list_data_display); + printf("\nlist_traversal_sequence success!\n"); + list_traversal_reversed(list, list_data_display); + printf("\nlist_traversal_reversed success!\n"); + if (list_empty(list)) + { + printf("list is not empty!\n"); + } + + list_clear(list); + printf("list_clear success\n"); + for (i = 0; i < 10; i++) + { + list_insert_head(list, dat[i]); + } + if (!list_delete(list, 5)) + { + printf("list_delete failureed!\n"); + } + printf("list_delete success! Data5 has been deleted\n"); + printf("list_count = %d\n", list_count(list)); + + list_traversal_sequence(list, list_data_display); + printf("\nlist_traversal_sequence success!\n"); + list_traversal_reversed(list, list_data_display); + printf("\nlist_traversal_reversed success!\n"); + + list_destroy(&list); + printf("list_destroy success\n"); + + if (!list_insert_tail(list, dat[0])) + { + printf("list_insert_tail success\n"); + } + if (!list_insert_head(list, dat[0])) + { + printf("list_insert_head success\n"); + } + + printf("----------------------------------------\n"); +} + +#endif + diff --git a/datastruct/main.c b/datastruct/main.c new file mode 100644 index 0000000..21be23c --- /dev/null +++ b/datastruct/main.c @@ -0,0 +1,15 @@ +#include "common.h" +#include "test.h" + +int main() +{ + while (1) + { + //stack_test(); + //queue_test(); + // list_test(); + //tree_test(); + rbtree_test(); + } + return 0; +} diff --git a/datastruct/queue.c b/datastruct/queue.c new file mode 100644 index 0000000..ad85744 --- /dev/null +++ b/datastruct/queue.c @@ -0,0 +1,138 @@ + +#include "queue.h" +#if QUEUE == 1 + +bool queue_init(pqueue_t * head) +{ + *head = (pqueue_t)malloc(sizeof(queue_t)); + if(*head == NULL) + { + return false; + } + (*head)->front = NULL; + (*head)->rear = NULL; + (*head)->size = 0; + return true; +} + +void queue_destroy(pqueue_t * head) +{ + if(*head != NULL) + { + queue_clear(*head); + free(*head); + *head = NULL; + } +} + +bool queue_empty(pqueue_t head) +{ + return (head == NULL || head->front == NULL || head->rear == NULL) ? true : false; +} + +void queue_clear(pqueue_t head) +{ + pqueue_node_t front_item; + if(head != NULL) + { + front_item = head->front; + while(head->front != NULL) + { + head->front = front_item->next; + free(front_item); + front_item = head->front; + } + head->rear = head->front; + head->size = 0; + } +} + +uint32_t queue_get_size(pqueue_t head) +{ + return head->size; +} + +bool queue_in(pqueue_t head, queue_data_t data) +{ + pqueue_node_t new_item; + if(head == NULL) + { + return false; + } + new_item = (pqueue_node_t)malloc(sizeof(queue_node_t)); + if(new_item == NULL) + { + return false; + } + new_item->data = data; + new_item->next = NULL; + if(head->front == NULL) + { + head->front = new_item; + } + // insert from tail + if(head->rear != NULL) + { + head->rear->next = new_item; + } + head->rear = new_item; + + if (head->size < _UI32_MAX) + { + head->size++; + } + + return true; +} + +void queue_out(pqueue_t head, queue_data_t *data) +{ + pqueue_node_t front_item; + if(!queue_empty(head)) + { + front_item = head->front; + *data = front_item->data; + + // free the front item + head->front = front_item->next; + free(front_item); + front_item = NULL; + if (queue_get_size(head) == 1) + { + head->rear = NULL; + } + + if (head > 0) + { + head->size--; + } + } +} + +bool queue_get_front(pqueue_t head, queue_data_t *data) +{ + if(!queue_empty(head)) + { + *data = head->front->data; + return true; + } + else + { + return false; + } +} + +bool queue_get_rear(pqueue_t head, queue_data_t *data) +{ + if(!queue_empty(head)) + { + *data = head->rear->data; + return true; + } + else + { + return false; + } +} + +#endif diff --git a/datastruct/queue.h b/datastruct/queue.h new file mode 100644 index 0000000..5a8cebe --- /dev/null +++ b/datastruct/queue.h @@ -0,0 +1,38 @@ +#ifndef _QUEUE_H_ +#define _QUEUE_H_ + +#include "common.h" + +#if QUEUE == 1 +// typedef int queue_data_t; + +// node of queue +typedef struct _queue_node_t +{ + queue_data_t data; + struct _queue_node_t * next; +} queue_node_t, *pqueue_node_t; + +// queue +typedef struct _queue_t +{ + struct _queue_node_t * front; + struct _queue_node_t * rear; + uint32_t size; +}queue_t,*pqueue_t; + + +bool queue_init(pqueue_t * head); +void queue_destroy(pqueue_t * head); +bool queue_empty(pqueue_t head); +void queue_clear(pqueue_t head); +uint32_t queue_get_size(pqueue_t head); + +bool queue_in(pqueue_t head, queue_data_t data); +void queue_out(pqueue_t head, queue_data_t *data); +bool queue_get_front(pqueue_t head, queue_data_t *data); +bool queue_get_rear(pqueue_t head, queue_data_t *data); + +#endif + +#endif // _QUEUE_H_ diff --git a/datastruct/queue_test.c b/datastruct/queue_test.c new file mode 100644 index 0000000..628f667 --- /dev/null +++ b/datastruct/queue_test.c @@ -0,0 +1,156 @@ + +#include "test.h" + +#if QUEUE_TEST == 1 + +void queue_test(void) +{ + int32_t i = 0; + uint32_t size; + queue_data_t dat[10] = {0,1,2,3,4,5,6,7,8,9}; + queue_data_t tmp; + pqueue_t que; + + if(!queue_init(&que)) + { + printf("failure -> queue_init\n"); + } + printf("success -> queue_init\n"); + + for(i = 0; i < 10; i++) + { + if(!queue_in(que,dat[i])) + { + printf("failure -> queue_in\n"); + } + if(!queue_get_front(que,&tmp)) + { + printf("failure -> queue_get_front\t"); + } + else + { + printf(" front = %d",tmp); + } + + if(!queue_get_rear(que,&tmp)) + { + printf("failure -> queue_get_rear\n"); + } + else + { + printf(" rear = %d\n",tmp); + } + } + printf("success -> queue_in\n"); + if(!queue_empty(que)) + { + printf("success -> queue is not empty!\n"); + } + else + { + printf("failure -> queue is not empty!\n"); + } + + size = queue_get_size(que); + if (size != 10) + { + printf("failure -> the size of queue is : %d\n", size); + } + else + { + printf("success -> the size of queue is : %d\n", size); + } + + printf("success -> queue_empty\n"); + for(i = 0; i < 10; i++) + { + if(!queue_get_front(que,&tmp)) + { + printf("failure -> queue_get_front\t"); + } + else + { + printf(" front = %d\t",tmp); + } + if(!queue_get_rear(que,&tmp)) + { + printf("failure -> queue_get_rear\n"); + } + else + { + printf(" rear = %d\n",tmp); + } + queue_out(que,&tmp); + } + printf("success -> queue_out\n"); + if(queue_empty(que)) + { + printf("success -> queue is empty!\n"); + } + + size = queue_get_size(que); + if (size != 0) + { + printf("failure -> the size of queue is : %d\n", size); + } + else + { + printf("success -> the size of queue is : %d\n", size); + } + + for(i = 0; i < 5; i++) + { + if(!queue_in(que,dat[i])) + { + printf("failure -> queue_in\n"); + } + } + + if(!queue_empty(que)) + { + printf("success -> queue is not empty!\n"); + queue_clear(que); + printf("success -> queue_clear\n"); + + if(queue_empty(que)) + { + printf("success -> queue is empty!\n"); + } + else + { + printf("failure -> queue is not empty!\n"); + } + } + + queue_destroy(&que); + printf("success -> queue_destroy\n"); + + if(!queue_in(que,dat[0])) + { + printf("success -> If que if NULL, queue_in return failure\n"); + } + + queue_out(que,&tmp); + printf("success -> queue_out invalid!\n"); + + if(queue_empty(que)) + { + printf("success -> If que is NULL, queue_empty alse return true!\n"); + } + else + { + printf("failure -> Que is NULL, but queue_empty return true!\n"); + } + + printf("----------------------------------------\n"); +} + +#else + +void queue_test(void) +{ + +} + +#endif + diff --git a/datastruct/rbtree.c b/datastruct/rbtree.c new file mode 100644 index 0000000..9ff6eae --- /dev/null +++ b/datastruct/rbtree.c @@ -0,0 +1,1186 @@ + +#include "rbtree.h" +#include "stack.h" +#include "queue.h" + +#if RBTREE == 1 + +// ---------------------------------------- +// rbtree Ը +#define RBT_COLOR(x) ((x)->color) +#define RBT_COLOR_INIT(x) (RBT_COLOR(x) = 0) + +// color <- bit[0] +#define RBT_COLOR_MASK (0x01) +#define RBT_BALCK (0x01) +#define BRT_RED (0x00) + +#define RBT_SET_RED(x) (RBT_COLOR(x) &= ~RBT_BALCK) +#define RBT_SET_BLACK(x) (RBT_COLOR(x) |= RBT_BALCK) +#define RBT_IS_BLACK(x) (((RBT_COLOR(x) & RBT_BALCK) == RBT_BALCK)?true:false) +#define RBT_IS_RED(x) (!RBT_IS_BLACK(x)) +#define RBT_COLOR_ASSIGN(a,b) (RBT_COLOR(a) = RBT_COLOR(b)) + +// ---------------------------------------- +// visited node <- bit[1:2] +#define RBT_VISIT_FLAG_MASK (0x06) +#define RBT_VISIT_FLAG_LEFT (0x04) +#define RBT_VISIT_FLAG_RIGHT (0x02) + +#define RBT_VISIT_CLR(x) (RBT_COLOR(x) &= ~RBT_VISIT_FLAG_MASK) +#define RBT_VISIT_LEFT(x) (RBT_COLOR(x) |= RBT_VISIT_FLAG_LEFT) +#define RBT_VISIT_RIGHT(x) (RBT_COLOR(x) |= RBT_VISIT_FLAG_RIGHT) +#define RBT_IS_VISITED_LEFT(x) (((RBT_COLOR(x) & RBT_VISIT_FLAG_LEFT) == RBT_VISIT_FLAG_LEFT)?\ + true:false) +#define RBT_IS_VISITED_RIGHT(x) (((RBT_COLOR(x) & RBT_VISIT_FLAG_RIGHT) == RBT_VISIT_FLAG_RIGHT)?\ + true:false) + + + +/** + * + */ +static bool rbtree_insert_fixup(prbtree_t head, prbtree_node_t tree); +static bool rbtree_delete_fixup(prbtree_t head, prbtree_node_t tree); + + +bool rbtree_init(prbtree_t *head) +{ + *head = (prbtree_t)malloc(sizeof(rbtree_t)); + if (*head == NULL) + { + return false; + } + (*head)->tree = NULL; + (*head)->size = 0; + return true; +} + +void rbtree_destroy(prbtree_t * head) +{ + if (*head != NULL) + { + rbtree_clear(*head); + free(*head); + *head = NULL; + } +} + +bool rbtree_empty(prbtree_t head) +{ + return ((head == NULL) || (head->tree == NULL)) ? true : false; +} + +void rbtree_clear(prbtree_t head) +{ + pqueue_t queue; + prbtree_node_t root; + prbtree_node_t tree_node; + + if ((head == NULL) || head->tree == NULL) + { + return; + } + root = head->tree; + + queue_init(&queue); + queue_in(queue, root); + + while (!queue_empty(queue)) + { + queue_out(queue, &tree_node); + if (tree_node->left != NULL) + { + queue_in(queue, tree_node->left); + } + if (tree_node->right != NULL) + { + queue_in(queue, tree_node->right); + } + + free(tree_node); + tree_node = NULL; + } + + queue_destroy(&queue); + + head->tree = NULL; + head->size = 0; +} + +uint32_t rbtree_get_size(prbtree_t head) +{ + return head->size; +} + +static prbtree_node_t rbtree_find(prbtree_t head, rbtree_data_t data) +{ + prbtree_node_t root; + + if ((head == NULL) || head->tree == NULL) + { + return NULL; + } + root = head->tree; + + while (root != NULL) + { + if (data < root->data) + { + if (root->left != NULL) + { + root = root->left; + } + else + { + return root; + } + } + else if (data > root->data) + { + if (root->right != NULL) + { + root = root->right; + } + else + { + return root; + } + } + else + { + // == + return root; + } + } + + return root; +} + +static prbtree_node_t get_parent_node(prbtree_node_t tree) +{ + if (tree == NULL) + { + return NULL; + } + return tree->parent; +} + +bool rbtree_insert(prbtree_t head, rbtree_data_t data) +{ + prbtree_node_t tree_node; + prbtree_node_t new_node; + + if (head == NULL) + { + return false; + } + + // no root of tree + if (head->tree == NULL) + { + new_node = (prbtree_node_t)malloc(sizeof(rbtree_node_t)); + if (new_node == NULL) + { + return false; + } + new_node->data = data; + new_node->left = NULL; + new_node->right = NULL; + new_node->parent = NULL; // the parent of root is NULL + RBT_COLOR_INIT(new_node); + + head->tree = new_node; + } + else + { + tree_node = rbtree_find(head, data); + if (data < tree_node->data) + { + new_node = (prbtree_node_t)malloc(sizeof(rbtree_node_t)); + if (new_node == NULL) + { + return false; + } + new_node->data = data; + new_node->left = NULL; + new_node->right = NULL; + new_node->parent = tree_node; + RBT_COLOR_INIT(new_node); + + tree_node->left = new_node; + } + else if(data > tree_node->data) + { + new_node = (prbtree_node_t)malloc(sizeof(rbtree_node_t)); + if (new_node == NULL) + { + return false; + } + new_node->data = data; + new_node->left = NULL; + new_node->right = NULL; + new_node->parent = tree_node; + RBT_COLOR_INIT(new_node); + + tree_node->right = new_node; + } + else + { + // keyȣ˵Ӧ滻valueֵ + // ĴǸ̼򵥹ʾ + // dataһݣ˴˴ֱӺԡ + return true; + } + } + + rbtree_insert_fixup(head, new_node); + + if (head->size < _UI32_MAX) + { + head->size++; + } + return true; +} + + +static prbtree_node_t rbtree_turn_left(prbtree_node_t tree) +{ + // ԵǰڵΪת + // ע⸸ڵ㲢ֻΪµӽڵ + // + prbtree_node_t node_n; // ǰڵ + prbtree_node_t node_nr; // ǰڵӽڵ + prbtree_node_t node_p; // ǰڵĸڵ + + if (tree == NULL) + { + return NULL; + } + node_n = tree; + node_nr = node_n->right; + node_p = node_n->parent; + + // 1. node_pӽڵ + if (node_p != NULL) + { + // not root of tree + if (node_p->left == node_n) + { + node_p->left = node_nr; + } + else + { + node_p->right = node_nr; + } + } + node_nr->parent = node_p; + + // 2. ת + node_n->parent = node_nr; // ֱnode_p=node_nrԭ㶮 + node_n->right = node_nr->left; + node_nr->left = node_n; + if (node_n->right != NULL) + { + node_n->right->parent = node_n; + } + + // 3. µĽڵ + return node_nr; +} + + +static prbtree_node_t rbtree_turn_right(prbtree_node_t tree) +{ + // ԵǰڵΪת + // ע⸸ڵ㲢ֻΪµӽڵ + // + prbtree_node_t node_n; // ǰڵ + prbtree_node_t node_nl; // ǰڵӽڵ + prbtree_node_t node_p; // ǰڵĸڵ + + if (tree == NULL) + { + return NULL; + } + node_n = tree; + node_nl = node_n->left; + node_p = node_n->parent; + + // 1. node_pӽڵ + if (node_p != NULL) + { + // not node_n + if (node_p->left == node_n) + { + node_p->left = node_nl; + } + else + { + node_p->right = node_nl; + } + } + node_nl->parent = node_p; + + // 2. ת + node_n->parent = node_nl; // ֱnode_p=node_nlԭ㶮 + node_n->left = node_nl->right; + node_nl->right = node_n; + if (node_n->left != NULL) + { + node_n->left->parent = node_n; + } + + // 3. µĽڵ + return node_nl; +} + +static bool rbtree_insert_fixup(prbtree_t head, prbtree_node_t tree) +{ + prbtree_node_t father, grandfather, uncle; + if ((head == NULL) || head->tree == NULL) + { + return false; + } + + if (tree == NULL) + { + return false; + } + + // --------------------------------------- + // case1.ڵ㲻ڣֱӲɫڵ + // case2.ڵΪڣɫڵԿ + // Ҫinsert⣩ + // case3.ҪΪǣ + // ҶԳƣҲͲˣ + // ---------------------------------------- + while (tree->parent != NULL && RBT_IS_RED(tree->parent)) + { + father = get_parent_node(tree); + grandfather = get_parent_node(father); + + if (father == grandfather->left) + { + uncle = grandfather->right; + if (uncle != NULL && RBT_IS_RED(uncle)) + { + RBT_SET_BLACK(father); + RBT_SET_BLACK(uncle); + RBT_SET_RED(grandfather); + tree = grandfather; + } + else + { + if (tree == father->right) + { + tree = rbtree_turn_left(father); + RBT_SET_BLACK(tree); + } + else + { + RBT_SET_BLACK(father); + } + RBT_SET_RED(grandfather); + tree = rbtree_turn_right(grandfather); + break; + } + } + else + { + uncle = grandfather->left; + if (uncle != NULL && RBT_IS_RED(uncle)) + { + RBT_SET_BLACK(father); + RBT_SET_BLACK(uncle); + RBT_SET_RED(grandfather); + tree = grandfather; + } + else + { + if (tree == father->left) + { + tree = rbtree_turn_right(father); + RBT_SET_BLACK(tree); + } + else + { + RBT_SET_BLACK(father); + } + RBT_SET_RED(grandfather); + tree = rbtree_turn_left(grandfather); + break; + } + } + } + + if (tree->parent == NULL) + { + head->tree = tree; + RBT_SET_BLACK(head->tree); + } + + return true; +} + +static prbtree_node_t tree_get_node_min(prbtree_node_t tree) +{ + while (tree != NULL) + { + if (tree->left != NULL) + { + tree = tree->left; + } + else + { + return tree; + } + } + return tree; +} + +bool rbtree_delete(prbtree_t head, rbtree_data_t data) +{ + prbtree_node_t tree_node; //ǰɾĽڵ + prbtree_node_t tree_node_del; //ʵϱɾĽڵ + + if ((head == NULL) || head->tree == NULL) + { + return false; + } + + tree_node = rbtree_find(head, data); + if (tree_node == NULL) + { + return false; + } + + if (tree_node->data != data) + { + // ûҵò + return false; + } + + if (tree_node->left == NULL && tree_node->right == NULL) + { + tree_node_del = tree_node; + } + else if (tree_node->left != NULL && tree_node->right == NULL) + { + tree_node_del = tree_node->left; + tree_node->data = tree_node_del->data; + } + else if (tree_node->left == NULL && tree_node->right != NULL) + { + tree_node_del = tree_node->right; + tree_node->data = tree_node_del->data; + } + else + { + // ˫ӶڣҺ̽ڵ + tree_node_del = tree_get_node_min(tree_node->right); + + tree_node->data = tree_node_del->data; + if (tree_node_del->right != NULL) + { + // غ + tree_node_del->data = tree_node_del->right->data; + tree_node_del = tree_node_del->right; + } + } + + if (RBT_IS_BLACK(tree_node_del)) + { + rbtree_delete_fixup(head, tree_node_del); + } + + // treeɾ + if (tree_node_del->parent != NULL) + { + if (tree_node_del == tree_node_del->parent->left) + { + tree_node_del->parent->left = NULL; + } + else + { + tree_node_del->parent->right = NULL; + } + } + else + { + // Ϊڵ + head->tree = NULL; + } + // ͷڴ + free(tree_node_del); + + if (head->size > 0) + { + head->size--; + } + return true; +} + +static bool rbtree_delete_fixup(prbtree_t head, prbtree_node_t tree) +{ + prbtree_node_t node_temp = NULL; + prbtree_node_t father, brother; + if ((head == NULL) || head->tree == NULL) + { + return false; + } + + while ((tree->parent != NULL) && RBT_IS_BLACK(tree)) + { + father = get_parent_node(tree); + if (tree == father->left) + { + brother = father->right; + if (RBT_IS_RED(brother)) + { + // rbtreeʣڵضΪڣ + // brotherӽڵ˫ڻ˫ + // case 5 + RBT_SET_BLACK(brother); + RBT_SET_RED(father); + node_temp = rbtree_turn_left(father); + // ڵδɾʱƽ⣬ɾֲ֮ƽ + // Ҫж + } + else if(brother->right != NULL && RBT_IS_RED(brother->right)) + { + // botherrightڵ㣬Ϊɫ + // ڵɫδ֪ + // case 1 Ӻ죩 case 3˫Ӻ죩 һ + RBT_COLOR_ASSIGN(brother,father); //color(f) -> color(b) + RBT_SET_BLACK(father); + RBT_SET_BLACK(brother->right); + tree = rbtree_turn_left(father); + // ɾڵ֮󣬿϶ƽˣ˳ + // ⣬ת֮պǸڵ㡣ֵtree + // ѭж + break; + } + else if(brother->left != NULL && RBT_IS_RED(brother->left)) + { + // botherleftڵ㣬leftΪɫ,rigth + // ڵɫδ֪ + // case 2 + // ע⣺дĻcase2ǰжcase1/case3 + RBT_SET_RED(brother); + RBT_SET_BLACK(brother->left); + node_temp = rbtree_turn_right(brother); + // תΪcase 1 + } + else + { + // brotherӽڵΪ˫ջ˫ + // case 4 + if(RBT_IS_BLACK(father)) + { + // ڵΪڣbrotherȾΪɫ + // һڣԸڵΪtreeϵݹ + RBT_SET_RED(brother); + tree = father; + } + else + { + // brother˫ӿգʾbrotherͱɾĽڵƽ + // ֱתɫ + RBT_SET_RED(brother); + RBT_SET_BLACK(father); + // ɾڵ֮󣬿϶ƽˣ˳ + break; + } + } + } + else + { + brother = father->left; + if (RBT_IS_RED(brother)) + { + // rbtreeʣڵضΪڣ + // brotherӽڵ˫ڻ˫ + // case 5 + RBT_SET_BLACK(brother); + RBT_SET_RED(father); + node_temp = rbtree_turn_right(father); + // ڵδɾʱƽ⣬ɾֲ֮ƽ + // Ҫж + } + else if (brother->left != NULL && RBT_IS_RED(brother->left)) + { + // botherleftڵ㣬Ϊɫ + // ڵɫδ֪ + // case 1 Ӻ죩 case 3˫Ӻ죩 һ + RBT_COLOR_ASSIGN(brother,father); + RBT_SET_BLACK(father); + RBT_SET_BLACK(brother->left); + tree = rbtree_turn_right(father); + // ɾڵ֮󣬿϶ƽˣ˳ + // ⣬ת֮պǸڵ㡣ֵtree + // ѭж + break; + } + else if (brother->right != NULL && RBT_IS_RED(brother->right)) + { + // botherrightڵ㣬rightΪɫleft + // ڵɫδ֪ + // case 2 + // ע⣺дĻcase2ǰжcase1/case3 + RBT_SET_RED(brother); + RBT_SET_BLACK(brother->right); + node_temp = rbtree_turn_left(brother); + // תΪ case 1 + } + else + { + // brotherӽڵΪ˫ջ˫ + // case 4 + if(RBT_IS_BLACK(father)) + { + // ڵΪڣbrotherȾΪɫ + // һڣԸڵΪtreeϵݹ + RBT_SET_RED(brother); + tree = father; + } + else + { + // brother˫ӿգʾbrotherͱɾĽڵƽ + // ֱתɫ + RBT_SET_RED(brother); + RBT_SET_BLACK(father); + // ɾڵ֮󣬿϶ƽˣ˳ + break; + } + } + } + + // ڴУֹڵ㶪ʧ + if (node_temp != NULL && node_temp->parent == NULL) + { + head->tree = node_temp; + } + } + + if (tree->parent == NULL) + { + head->tree = tree; + } + + RBT_SET_BLACK(head->tree); + return true; +} + + + +bool rbtree_get_min(prbtree_t head, rbtree_data_t *data) +{ + prbtree_node_t root; + + if ((head == NULL) || head->tree == NULL) + { + return false; + } + root = head->tree; + + while (root != NULL) + { + if (root->left != NULL) + { + root = root->left; + } + else + { + *data = root->data; + return true; + } + } + return false; +} + +bool rbtree_get_max(prbtree_t head, rbtree_data_t *data) +{ + prbtree_node_t root; + if ((head == NULL) || head->tree == NULL) + { + return false; + } + root = head->tree; + + while (root != NULL) + { + if (root->right != NULL) + { + root = root->right; + } + else + { + *data = root->data; + return true; + } + } + return false; +} + +#if 1 +void rbtree_traversal_depth_preorder(prbtree_t head, tree_data_disp_t tree_data_disp) +{ + pstack_t stack; + prbtree_node_t root; + prbtree_node_t tree_node; + + if ((head == NULL) || head->tree == NULL) + { + return; + } + root = head->tree; + + stack_init(&stack); + tree_node = root; + while (!stack_empty(stack) || tree_node != NULL) + { + if (tree_node != NULL) + { + tree_data_disp(tree_node->data); + + stack_push(stack, tree_node); + tree_node = tree_node->left; + } + else + { + stack_pop(stack, &tree_node); + tree_node = tree_node->right; + } + } + + stack_destroy(&stack); +} + +void rbtree_traversal_depth_inorder(prbtree_t head, tree_data_disp_t tree_data_disp) +{ + pstack_t stack; + prbtree_node_t root; + prbtree_node_t tree_node; + + if ((head == NULL) || head->tree == NULL) + { + return; + } + root = head->tree; + + stack_init(&stack); + tree_node = root; + while (!stack_empty(stack) || tree_node != NULL) + { + if (tree_node != NULL) + { + stack_push(stack, tree_node); + tree_node = tree_node->left; + } + else + { + stack_pop(stack, &tree_node); + tree_data_disp(tree_node->data); + tree_node = tree_node->right; + } + } + + stack_destroy(&stack); +} + +void rbtree_traversal_depth_postorder(prbtree_t head, tree_data_disp_t tree_data_disp) +{ + pstack_t stack; + pstack_t stack_disp; + prbtree_node_t root; + prbtree_node_t tree_node; + + if ((head == NULL) || head->tree == NULL) + { + return; + } + root = head->tree; + + stack_init(&stack); + stack_init(&stack_disp); + tree_node = root; + while (!stack_empty(stack) || tree_node != NULL) + { + if (tree_node != NULL) + { + stack_push(stack_disp, tree_node); + + stack_push(stack, tree_node); + tree_node = tree_node->right; + } + else + { + stack_pop(stack, &tree_node); + tree_node = tree_node->left; + } + } + + while (!stack_empty(stack_disp)) + { + stack_pop(stack_disp, &tree_node); + tree_data_disp(tree_node->data); + } + + stack_destroy(&stack); + stack_destroy(&stack_disp); +} +#else +// ------------------------------------------------- +// ʽ2 ˷ʱ־иƣ߶ +// ------------------------------------------------- +void rbtree_traversal_depth_preorder(prbtree_t head, tree_data_disp_t tree_data_disp) +{ + pstack_t stack; + prbtree_node_t root; + prbtree_node_t tree_node; + + if ((head == NULL) || head->tree == NULL) + { + return; + } + root = head->tree; + + stack_init(&stack); + stack_push(stack, root); + tree_data_disp(root->data); + while (!stack_empty(stack)) + { + stack_get_top(stack, &tree_node); + + if (tree_node->left != NULL && !RBT_IS_VISITED_LEFT(tree_node)) + { + RBT_VISIT_LEFT(tree_node); + + stack_push(stack, tree_node->left); + tree_node = tree_node->left; + + tree_data_disp(tree_node->data); + } + else if (tree_node->right != NULL && !RBT_IS_VISITED_RIGHT(tree_node)) + { + RBT_VISIT_RIGHT(tree_node); + + stack_push(stack, tree_node->right); + tree_node = tree_node->right; + + tree_data_disp(tree_node->data); + } + else + { + RBT_VISIT_CLR(tree_node); + stack_pop(stack, &tree_node); + } + } + + stack_destroy(&stack); +} + +void rbtree_traversal_depth_inorder(prbtree_t head, tree_data_disp_t tree_data_disp) +{ + pstack_t stack; + prbtree_node_t root; + prbtree_node_t tree_node; + + if ((head == NULL) || head->tree == NULL) + { + return; + } + root = head->tree; + + stack_init(&stack); + stack_push(stack, root); + while (!stack_empty(stack)) + { + stack_get_top(stack, &tree_node); + + if (tree_node->left != NULL && !RBT_IS_VISITED_LEFT(tree_node)) + { + RBT_VISIT_LEFT(tree_node); + + stack_push(stack, tree_node->left); + tree_node = tree_node->left; + } + else if (tree_node->right != NULL && !RBT_IS_VISITED_RIGHT(tree_node)) + { + RBT_VISIT_RIGHT(tree_node); + + tree_data_disp(tree_node->data); + + stack_push(stack, tree_node->right); + tree_node = tree_node->right; + } + else + { + if (!RBT_IS_VISITED_RIGHT(tree_node)) + { + tree_data_disp(tree_node->data); + } + + RBT_VISIT_CLR(tree_node); + stack_pop(stack, &tree_node); + } + } + + stack_destroy(&stack); +} + +void rbtree_traversal_depth_postorder(prbtree_t head, tree_data_disp_t tree_data_disp) +{ + pstack_t stack; + prbtree_node_t root; + prbtree_node_t tree_node; + + if ((head == NULL) || head->tree == NULL) + { + return; + } + root = head->tree; + + stack_init(&stack); + stack_push(stack, root); + while (!stack_empty(stack)) + { + stack_get_top(stack, &tree_node); + + if (tree_node->left != NULL && !RBT_IS_VISITED_LEFT(tree_node)) + { + RBT_VISIT_LEFT(tree_node); + + stack_push(stack, tree_node->left); + tree_node = tree_node->left; + } + else if (tree_node->right != NULL && !RBT_IS_VISITED_RIGHT(tree_node)) + { + RBT_VISIT_RIGHT(tree_node); + + stack_push(stack, tree_node->right); + tree_node = tree_node->right; + } + else + { + RBT_VISIT_CLR(tree_node); + stack_pop(stack, &tree_node); + + tree_data_disp(tree_node->data); + } + } + + stack_destroy(&stack); +} +#endif + + +void rbtree_traversal_breadth(prbtree_t head, tree_data_disp_t tree_data_disp) +{ + pqueue_t queue; + prbtree_node_t root; + prbtree_node_t tree_node; + + if ((head == NULL) || head->tree == NULL) + { + return; + } + root = head->tree; + + queue_init(&queue); + queue_in(queue, root); + if (root != NULL) + { + while (!queue_empty(queue)) + { + queue_out(queue, &tree_node); + if (tree_node->left != NULL) + { + queue_in(queue, tree_node->left); + } + if (tree_node->right != NULL) + { + queue_in(queue, tree_node->right); + } + + tree_data_disp(tree_node->data); + } + } + + queue_destroy(&queue); +} + + +static bool rbtree_node_check(prbtree_node_t tree_node) +{ + // check + if (tree_node->parent == NULL) + { + if (RBT_IS_RED(tree_node)) + { + return false; + } + } + else + { + if (RBT_IS_RED(tree_node)) + { + if (tree_node->left != NULL && tree_node->right != NULL) + { + if (RBT_IS_RED(tree_node->left) || RBT_IS_RED(tree_node->right)) + { + // error + return false; + } + } + else if (tree_node->left != NULL && tree_node->right == NULL) + { + // error + return false; + } + else if (tree_node->left == NULL && tree_node->right != NULL) + { + // error + return false; + } + else + { + // pass + } + } + else + { + if (tree_node->left != NULL && tree_node->right == NULL) + { + if (RBT_IS_BLACK(tree_node->left)) + { + // error + return false; + } + } + else if (tree_node->left == NULL && tree_node->right != NULL) + { + if (RBT_IS_BLACK(tree_node->right)) + { + // error + return false; + } + } + else + { + // pass + } + } + } + + return true; +} + + +bool rbtree_check(prbtree_t head) +{ + pstack_t stack; + prbtree_node_t root; + prbtree_node_t tree_node; + + bool ret = true; + uint32_t black_cnt = 0, black_cnt_max = 0; + + if ((head == NULL) || head->tree == NULL) + { + // ok + return ret; + } + root = head->tree; + + if (RBT_IS_RED(root)) + { + ret = false; + return ret; + } + else + { + black_cnt++; + if (black_cnt > black_cnt_max) + { + black_cnt_max = black_cnt; + } + } + + stack_init(&stack); + stack_push(stack, root); + while (!stack_empty(stack)) + { + stack_get_top(stack,&tree_node); + + if (tree_node->left != NULL && !RBT_IS_VISITED_LEFT(tree_node)) + { + RBT_VISIT_LEFT(tree_node); + + stack_push(stack, tree_node->left); + tree_node = tree_node->left; + + if (RBT_IS_BLACK(tree_node)) + { + black_cnt++; + if (black_cnt > black_cnt_max) + { + black_cnt_max = black_cnt; + } + } + } + else if (tree_node->right != NULL && !RBT_IS_VISITED_RIGHT(tree_node)) + { + RBT_VISIT_RIGHT(tree_node); + + stack_push(stack, tree_node->right); + tree_node = tree_node->right; + + if (RBT_IS_BLACK(tree_node)) + { + black_cnt++; + if (black_cnt > black_cnt_max) + { + black_cnt_max = black_cnt; + } + } + } + else + { + if (tree_node->left == NULL && tree_node->right == NULL) + { + if (black_cnt != black_cnt_max) + { + ret = false; + goto black_check_exit; + } + } + + RBT_VISIT_CLR(tree_node); + stack_pop(stack, &tree_node); + + if (RBT_IS_BLACK(tree_node)) + { + if (black_cnt > 0) + { + black_cnt--; + } + } + + // check node + if (true != rbtree_node_check(tree_node)) + { + ret = false; + goto black_check_exit; + } + } + } + +black_check_exit: + stack_destroy(&stack); + return ret; +} + +#endif // RBTREE == 1 + diff --git a/datastruct/rbtree.h b/datastruct/rbtree.h new file mode 100644 index 0000000..ecbcef1 --- /dev/null +++ b/datastruct/rbtree.h @@ -0,0 +1,49 @@ + +#ifndef _RBTREE_H_ +#define _RBTREE_H_ + +#include "config.h" + +#if RBTREE == 1 +typedef int rbtree_data_t; + +typedef struct _rbtree_node_t +{ + rbtree_data_t data; + struct _rbtree_node_t * left; + struct _rbtree_node_t * right; + struct _rbtree_node_t * parent; + uint32_t color; +}rbtree_node_t, *prbtree_node_t; + +typedef struct _rbtree_t +{ + struct _rbtree_node_t * tree; + uint32_t size; +}rbtree_t, *prbtree_t; + + +typedef void (*tree_data_disp_t)(rbtree_data_t data); + + +bool rbtree_init(prbtree_t *head); +void rbtree_destroy(prbtree_t * head); +bool rbtree_empty(prbtree_t head); +void rbtree_clear(prbtree_t head); +uint32_t rbtree_get_size(prbtree_t head); +bool rbtree_insert(prbtree_t head, rbtree_data_t data); +bool rbtree_delete(prbtree_t head, rbtree_data_t data); + + +bool rbtree_get_min(prbtree_t head, rbtree_data_t *data); +bool rbtree_get_max(prbtree_t head, rbtree_data_t *data); +void rbtree_traversal_depth_preorder(prbtree_t head, tree_data_disp_t tree_data_disp); +void rbtree_traversal_depth_inorder(prbtree_t head, tree_data_disp_t tree_data_disp); +void rbtree_traversal_depth_postorder(prbtree_t head, tree_data_disp_t tree_data_disp); +void rbtree_traversal_breadth(prbtree_t head, tree_data_disp_t tree_data_disp); + +// check +bool rbtree_check(prbtree_t head); +#endif + +#endif // _RBTREE_H_ diff --git a/datastruct/rbtree_test.c b/datastruct/rbtree_test.c new file mode 100644 index 0000000..ff95a39 --- /dev/null +++ b/datastruct/rbtree_test.c @@ -0,0 +1,254 @@ + +#include "test.h" + +#if RBTREE_TEST == 1 + +#define TREE_DISP_DEPTH_PRE(tree) {rbtree_traversal_depth_preorder(tree,tree_data_display);printf("\n");} +#define TREE_DISP_DEPTH_IN(tree) {rbtree_traversal_depth_inorder(tree,tree_data_display);printf("\n");} +#define TREE_DISP_DEPTH_POST(tree) {rbtree_traversal_depth_postorder(tree,tree_data_display);printf("\n");} +#define TREE_DISP_BREADTH(tree) {rbtree_traversal_breadth(tree,tree_data_display);printf("\n");} + +// tree display +#define TREE_DISP(tree) TREE_DISP_DEPTH_IN(tree) + +static void tree_data_display(rbtree_data_t data) +{ + printf("%4d ", data); +} + +void rbtree_base(void) +{ + int32_t i = 0; + rbtree_data_t dat[10] = { 5,0,2,4,3,1,8,7,9,6 }; // debug data + rbtree_data_t tmp; + prbtree_t tree = NULL; + + rbtree_init(&tree); + + for (i = 0; i < 10; i++) + { + rbtree_insert(tree, dat[i]); + } + printf("tree : "); + TREE_DISP(tree); + + rbtree_get_min(tree, &tmp); + if (tmp == 0) + { + printf("success -> tree_get_min is %d\n", tmp); + } + else + { + printf("failure -> tree_get_min is %d ?\n", tmp); + } + + rbtree_get_max(tree, &tmp); + if (tmp == 9) + { + printf("success -> tree_get_max is %d\n", tmp); + } + else + { + printf("failure -> tree_get_max is %d ?\n", tmp); + } + + // delete the leaf + rbtree_delete(tree, 6); + printf("del %d: ", 6); + TREE_DISP(tree); + + // delete the node which one child + rbtree_delete(tree, 0); + printf("del %d: ", 0); + TREE_DISP(tree); + + // delete the node which has two nodes + rbtree_delete(tree, 2); + printf("del %d: ", 2); + TREE_DISP(tree); + + // delete the root + rbtree_delete(tree, 4); + printf("del %d: ", 4); + TREE_DISP(tree); + + rbtree_clear(tree); + printf("success -> tree_clear success!\n"); + if (rbtree_empty(tree)) + { + printf("success -> the tree is empty\n"); + } + else + { + printf("failure -> the tree is not empty\n"); + } + + if (!rbtree_delete(tree, 8)) + { + printf("success -> tree is empty, so delete failureed!\n"); + } + else + { + printf("failure -> tree is empty, but delete succeed!\n"); + } + + + // ------------------------------------ + // insert again + for (i = 0; i < 10; i++) + { + rbtree_insert(tree, dat[i]); + } + printf("tree : "); + TREE_DISP(tree); + + for (i = 0; i < 10; i++) + { + if (rbtree_delete(tree, i)) + { + printf("del %d: ", i); + TREE_DISP(tree); + } + } + + if (rbtree_empty(tree)) + { + printf("success -> the tree is empty\n"); + } + else + { + printf("failure -> the tree is not empty\n"); + } + + rbtree_destroy(&tree); + if (!rbtree_insert(tree, dat[0])) + { + printf("success -> after tree destroyed, tree_insert failureed!\n"); + } + + if (!rbtree_get_min(tree, &tmp)) + { + printf("success -> after tree destroyed, tree_get_min failured!\n"); + } + + if (!rbtree_get_max(tree, &tmp)) + { + printf("success -> after tree destroyed, tree_get_max failured!\n"); + } + + printf("----------------------------------------\n"); +} + +void rbtree_random_insert_test(void) +{ +#define INSERT_NUM_MAX 128 + uint32_t i = 0; + const uint32_t len = INSERT_NUM_MAX; + rbtree_data_t dat[INSERT_NUM_MAX]; + rbtree_data_t dd[] = { 5,0,2,4,3,1,8,7,9,6 }; + + prbtree_t tree = NULL; + rbtree_init(&tree); + + printf("orig_data:\n"); + srand((uint32_t)time(0)); + for (i = 0; i < len; i++) + { + dat[i] = rand() % len; + // dat[i] = dd[i]; + printf("%d,", dat[i]); + } + printf("\n----------------------------------------\n"); + + for (i = 0; i < len; i++) + { + // printf("insert %-04d\n", dat[i]); + rbtree_insert(tree, dat[i]); + // TREE_DISP(tree); + + if (true != rbtree_check(tree)) + { + printf("failure -> insert\n"); + SYSTEM_PAUSE(); + } + } + + TREE_DISP_DEPTH_PRE(tree); + TREE_DISP_DEPTH_IN(tree); + TREE_DISP_DEPTH_POST(tree); + TREE_DISP_BREADTH(tree); + + rbtree_destroy(&tree); +} + + +void rbtree_random_delete_test(void) +{ +#define MAX_NUMBER 128 + uint32_t i = 0; + const uint32_t len = MAX_NUMBER; + rbtree_data_t dat[MAX_NUMBER]; + rbtree_data_t dd[] = { 22,12,5,2,0,21,5,22,30,11,6,18,22,5,7,17,13,13,24,13,14,1,20,12,22,24,19,14,17,13,24 }; + + prbtree_t tree = NULL; + rbtree_init(&tree); + static uint8_t srand_flag = 0; + + if (srand_flag == 0) + { + srand((uint32_t)time(0)); + srand_flag = 1; + } + printf("orig_data:\n"); + for (i = 0; i < len; i++) + { + dat[i] = rand() % len; + // dat[i] = dd[i]; + printf("%d,", dat[i]); + } + printf("\n----------------------------------------\n"); + + for (i = 0; i < len; i++) + { + rbtree_insert(tree, dat[i]); + + if (true != rbtree_check(tree)) + { + printf("failure -> insert\n"); + SYSTEM_PAUSE(); + } + } + // TREE_DISP(tree); + printf("----------------------------------------\n"); + + for (i = 0; i < len; i++) + { + // printf("delete %-04d\n", dat[i]); + rbtree_delete(tree, dat[i]); + // TREE_DISP(tree); + if (true != rbtree_check(tree)) + { + printf("failure -> delete\n"); + SYSTEM_PAUSE(); + } + } + printf("----------------------------------------\n"); + + if (rbtree_empty(tree)) + { + printf("success -> the tree is empty\n"); + } + + rbtree_destroy(&tree); +} + + +void rbtree_test(void) +{ + // rbtree_base(); + // rbtree_random_insert_test(); + rbtree_random_delete_test(); +} + +#endif + diff --git a/datastruct/stack.c b/datastruct/stack.c new file mode 100644 index 0000000..95a6cda --- /dev/null +++ b/datastruct/stack.c @@ -0,0 +1,115 @@ + +#include "stack.h" + +#if STACK == 1 + +bool stack_init(pstack_t *head) +{ + *head = (pstack_t)malloc(sizeof(stack_t)); + if(*head == NULL) + { + return false; + } + (*head)->top = NULL; + (*head)->size = 0; + return true; +} + +void stack_destroy(pstack_t *head) +{ + if(*head != NULL) + { + stack_clear(*head); + free(*head); + *head = NULL; + } +} + +bool stack_empty(pstack_t head) +{ + return (head == NULL || head->top == NULL) ? true : false; +} + +void stack_clear(pstack_t head) +{ + pstack_node_t top_item; + if(head != NULL) + { + top_item = head->top; + while(top_item != NULL) + { + head->top = top_item->next; + free(top_item); + top_item = head->top; + } + } + head->size = 0; +} + +bool stack_push(pstack_t head, stack_data_t data) +{ + pstack_node_t new_item; + if(head == NULL) + { + return false; + } + + new_item = (pstack_node_t)malloc(sizeof(stack_node_t)); + if(new_item == NULL) + { + return false; + } + new_item->data = data; + + // insert from head + new_item->next = head->top; + head->top = new_item; + + // increase + if(head->size < _UI32_MAX) + { + head->size ++; + } + return true; +} + +void stack_pop(pstack_t head, stack_data_t *data) +{ + pstack_node_t top_item; + if(!stack_empty(head)) + { + top_item = head->top; + *data = top_item->data; + + // free the top item + head->top = top_item->next; + free(top_item); + top_item = NULL; + + // decrease + if(head->size > 0) + { + head->size--; + } + } +} + +bool stack_get_top(pstack_t head, stack_data_t *data) +{ + if(!stack_empty(head)) + { + *data = head->top->data; + return true; + } + else + { + return false; + } +} + +uint32_t stack_get_size(pstack_t head) +{ + return head->size; +} + +#endif diff --git a/datastruct/stack.h b/datastruct/stack.h new file mode 100644 index 0000000..1ea9cfe --- /dev/null +++ b/datastruct/stack.h @@ -0,0 +1,36 @@ +#ifndef _STACK_H_ +#define _STACK_H_ + +#include "common.h" + +#if STACK == 1 + +// typedef int stack_data_t; + +typedef struct _stack_node_t +{ + stack_data_t data; + struct _stack_node_t * next; +} stack_node_t, *pstack_node_t; + +typedef struct _stack_t +{ + struct _stack_node_t * top; + uint32_t size; +} stack_t, *pstack_t; + + +bool stack_init(pstack_t *head); +void stack_destroy(pstack_t *head); +bool stack_empty(pstack_t head); +void stack_clear(pstack_t head); +uint32_t stack_get_size(pstack_t head); + +bool stack_push(pstack_t head, stack_data_t data); +void stack_pop(pstack_t head, stack_data_t *data); +bool stack_get_top(pstack_t head, stack_data_t *data); + +#endif + +#endif // _STACK_H_ + diff --git a/datastruct/stack_test.c b/datastruct/stack_test.c new file mode 100644 index 0000000..26c292f --- /dev/null +++ b/datastruct/stack_test.c @@ -0,0 +1,120 @@ +#include "test.h" + +#if STACK_TEST == 1 + +void stack_test(void) +{ + int32_t i = 0; + uint32_t size = 0; + stack_data_t dat[10] = {0,1,2,3,4,5,6,7,8,9}; + stack_data_t tmp; + pstack_t pst; + if(!stack_init(&pst)) + { + printf("failure -> stack_init\n"); + } + printf("success -> stack_init\n"); + + // push + for(i = 0; i < 10; i++) + { + if(!stack_push(pst,dat[i])) + { + printf("failure -> stack_push\n"); + } + printf(" push %d\n",dat[i]); + } + printf("success -> stack_push\n"); + + // stack size + size = stack_get_size(pst); + if(size != 10) + { + printf("failure -> the size of stack is %d\n",size); + } + else + { + printf("success -> the size of stack is %d\n",size); + } + + if(!stack_empty(pst)) + { + printf("success -> the stack is not empty!\n"); + } + else + { + printf("failure -> the stack is empty!\n"); + } + + // pop + for(i = 0; i < 10; i++) + { + stack_get_top(pst,&tmp); + printf(" top = %d",tmp); + stack_pop(pst,&tmp); + printf(" pop %d\n",tmp); + } + printf("stack_pop success!\n"); + + // stack size + size = stack_get_size(pst); + if(size != 0) + { + printf("failure -> the size of stack is %d\n",size); + } + else + { + printf("success -> the size of stack is %d\n",size); + } + + if(stack_empty(pst)) + { + printf("success -> the stack is empty!\n"); + } + else + { + printf("failure -> the stack is empty!\n"); + } + + for(i = 0; i < 5; i++) + { + stack_push(pst,dat[i]); + } + if(!stack_empty(pst)) + { + stack_clear(pst); + printf("success -> stack_clear\n"); + if(stack_empty(pst)) + { + printf("success -> the stack is empty!\n"); + } + } + + stack_destroy(&pst); + printf("success -> stack_destroy\n"); + + if(!stack_push(pst,dat[0])) + { + printf("success -> stack_push failed!\n"); + } + + stack_pop(pst,&tmp); + printf("success -> stack_pop invalid!\n"); + + if(stack_empty(pst)) + { + printf("success -> If pst is NULL, stack_empty alse return true!\n"); + } + + printf("----------------------------------------\n"); +} + +#else + +void stack_test(void) +{ + +} + +#endif + diff --git a/datastruct/test.h b/datastruct/test.h new file mode 100644 index 0000000..c5b77e8 --- /dev/null +++ b/datastruct/test.h @@ -0,0 +1,35 @@ + +#ifndef _TEST_H_ +#define _TEST_H_ + +#include +#include + +#include "common.h" + +// It is recommended to keep one at the same time +#define RBTREE_TEST 1 +#define AVLTREE_TEST 0 +#define RAVLTRE_TEST 0 +#define STACK_TEST 0 +#define QUEUE_TEST 0 +#define LIST_TEST 0 + + +#if AVLTREE == 1 || RAVLTREE == 1 || RBTREE == 1 + #if QUEUE_TEST == 1 || STACK_TEST == 1 + #error "When use the tree, you can't use the base data type of stack or queue! " + #endif +#endif + + +#define SYSTEM_PAUSE() (system("pause")) + +void stack_test(void); +void queue_test(void); +void list_test(void); +void tree_test(void); +void rbtree_test(void); + +#endif // _TEST_H_ + diff --git a/datastruct/tree.c b/datastruct/tree.c new file mode 100644 index 0000000..8793f45 --- /dev/null +++ b/datastruct/tree.c @@ -0,0 +1,1394 @@ + +#include "tree.h" + +#if RAVLTREE == 1 +// function declare +static bool tree_rebalance(ptree_node_t tree); + +bool tree_init(ptree_node_t *tree) +{ + *tree = (ptree_node_t)malloc(sizeof(tree_node_t)); + if(*tree == NULL) + { + return false; + } + // (*tree)->data = (tree_data_t)0; // the data of header is invalid + (*tree)->left = *tree; // The left subtree of the header node of the tree points to itself + (*tree)->right = NULL; // The right subtree of the header node of the tree points to the root + (*tree)->parent = NULL; // Invalid, because this is the pointer of tree header + (*tree)->balance = 0; // balance of avl tree + return true; +} + +void tree_destroy(ptree_node_t *tree) +{ + if(*tree != NULL) + { + tree_clear(*tree); + free(*tree); + *tree = NULL; + } +} + +bool tree_empty(ptree_node_t tree) +{ + return ((tree == NULL) || (tree->left == tree) && (tree->right == NULL)) ? true : false; +} + +void tree_clear(ptree_node_t tree) +{ + // the header of tree pointer + if(tree != NULL && tree->left == tree) + { + tree_clear(tree->right); + free(tree->right); + tree->right = NULL; + return; + } + + if(!tree_empty(tree)) + { + if(tree->left != NULL) + { + tree_clear(tree->left); + free(tree->left); + tree->left = NULL; + } + + if(tree->right != NULL) + { + tree_clear(tree->right); + free(tree->right); + tree->right = NULL; + } + } +} + +static ptree_node_t tree_find(ptree_node_t tree, tree_data_t data) +{ + if (tree != NULL && tree->left == tree) + { + return tree_find(tree->right,data); + } + + if(tree == NULL) + { + return NULL; + } + + if(tree->data == data) + { + return tree; + } + + if(data < tree->data) + { + if(tree->left != NULL) + { + return tree_find(tree->left,data); + } + else + { + return tree; + } + } + + if(data > tree->data) + { + if(tree->right != NULL) + { + return tree_find(tree->right,data); + } + else + { + return tree; + } + } + + // invalid + return NULL; +} + +bool tree_insert(ptree_node_t tree, tree_data_t data) +{ + ptree_node_t tree_node; + if (tree == NULL) + { + return false; + } + + // the header of tree pointer + if(tree != NULL && tree->left == tree) + { + if (tree->right == NULL) + { + ptree_node_t new_item = (ptree_node_t)malloc(sizeof(tree_node_t)); + if (new_item == NULL) + { + return false; + } + new_item->data = data; + new_item->left = NULL; + new_item->right = NULL; + // new_item->parent = NULL; // root no parent + new_item->parent = tree; // the parent of root is header of tree + new_item->balance = 0; // balance of avl tree + + tree->right = new_item; + return true; + } + else + { + return tree_insert(tree->right, data); + } + } + + tree_node = tree_find(tree,data); + if(data < tree_node->data) + { + ptree_node_t new_item = (ptree_node_t)malloc(sizeof(tree_node_t)); + if(new_item == NULL) + { + return false; + } + new_item->data = data; + new_item->left = NULL; + new_item->right = NULL; + new_item->parent = tree_node; + new_item->balance = 0; // balance of avl tree + + tree_node->left = new_item; + // avl tree rebalance + tree_rebalance(tree_node); + } + else + { + ptree_node_t new_item = (ptree_node_t)malloc(sizeof(tree_node_t)); + if(new_item == NULL) + { + return false; + } + new_item->data = data; + new_item->left = NULL; + new_item->right = NULL; + new_item->parent = tree_node; + new_item->balance = 0; // balance of avl tree + + tree_node->right = new_item; + + // avl tree rebalance + tree_rebalance(tree_node); + } + return true; +} + +static ptree_node_t tree_get_node_min(ptree_node_t tree) +{ + if (tree != NULL && tree->left == tree) + { + return tree_get_node_min(tree->right); + } + + if(tree != NULL) + { + if(tree->left != NULL) + { + return tree_get_node_min(tree->left); + } + else + { + return tree; + } + } + else + { + return NULL; + } +} + +static void tree_delete_single_child(ptree_node_t tree) +{ + if (tree != NULL && tree->left == tree) + { + tree_delete_single_child(tree->right); + return ; + } + + if(tree != NULL) + { + // becaue the parent of root is header of tree + // if(tree->parent == NULL) + if(tree->parent->parent == NULL) + { + // delete the root of tree + if(tree->left == NULL) + { + tree->parent->right = tree->right; + if(tree->right != NULL) + { + tree->right->parent = tree->parent; + } + } + else + { + tree->parent->right = tree->left; + tree->left->parent = tree->parent; + } + } + else + { + // delete other node of tree + if(tree->parent->left == tree) + { + // left subtree + if(tree->left == NULL) + { + tree->parent->left = tree->right; + if(tree->right != NULL) + { + tree->right->parent = tree->parent; + } + } + else + { + tree->parent->left = tree->left; + tree->left->parent = tree->parent; + } + } + else + { + // rigth subtree + if(tree->left == NULL) + { + tree->parent->right = tree->right; + if(tree->right != NULL) + { + tree->right->parent = tree->parent; + } + } + else + { + tree->parent->right = tree->left; + tree->left->parent = tree->parent; + } + } + + // avl tree rebalance + tree_rebalance(tree->parent); + } + free(tree); + } +} + +static void tree_delete_double_child(ptree_node_t tree) +{ + // I think this idea is great! + ptree_node_t t = tree_get_node_min(tree->right); + if(t != NULL) + { + tree->data = t->data; + tree_delete_single_child(t); + } +} + +bool tree_delete(ptree_node_t tree, tree_data_t data) +{ + ptree_node_t tree_node; + if (tree == NULL) + { + return false; + } + + if (tree != NULL && tree->left == tree) + { + return tree_delete(tree->right, data); + } + + tree_node = tree_find(tree,data); + if(tree_node->data == data) + { + if((tree_node->left != NULL) && (tree_node->right != NULL)) + { + tree_delete_double_child(tree_node); + } + else + { + tree_delete_single_child(tree_node); + } + return true; + } + else + { + return false; + } +} + +bool tree_get_min(ptree_node_t tree, tree_data_t *data) +{ + if (tree != NULL && tree->left == tree) + { + return tree_get_min(tree->right, data); + } + + if(tree != NULL) + { + if(tree->left != NULL) + { + return tree_get_min(tree->left, data); + } + else + { + *data = tree->data; + return true; + } + } + else + { + return false; + } + + // invalid but compile prevention warning + return true; +} + +bool tree_get_max(ptree_node_t tree, tree_data_t *data) +{ + if (tree != NULL && tree->left == tree) + { + return tree_get_max(tree->right, data); + } + + if(tree != NULL) + { + if(tree->right != NULL) + { + return tree_get_max(tree->right, data); + } + else + { + *data = tree->data; + return true; + } + } + else + { + return false; + } + + // invalid but compile prevention warning + return true; +} + +void tree_traversal_depth_preorder(ptree_node_t tree, tree_data_disp_t tree_data_disp) +{ + if (tree != NULL && tree->left == tree) + { + tree_traversal_depth_preorder(tree->right, tree_data_disp); + return; + } + + if (tree != NULL) + { + tree_data_disp(tree->data); + tree_traversal_depth_preorder(tree->left, tree_data_disp); + tree_traversal_depth_preorder(tree->right, tree_data_disp); + } +} + +void tree_traversal_depth_inorder(ptree_node_t tree, tree_data_disp_t tree_data_disp) +{ + if (tree != NULL && tree->left == tree) + { + tree_traversal_depth_inorder(tree->right, tree_data_disp); + return; + } + + if (tree != NULL) + { + tree_traversal_depth_inorder(tree->left, tree_data_disp); + tree_data_disp(tree->data); + tree_traversal_depth_inorder(tree->right, tree_data_disp); + } +} + +void tree_traversal_depth_postorder(ptree_node_t tree, tree_data_disp_t tree_data_disp) +{ + +} + +void tree_traversal_breadth(ptree_node_t tree, tree_data_disp_t tree_data_disp) +{ + +} + + +// --------------- AVL ---------------------- +static int32_t tree_get_height(ptree_node_t tree) +{ + int32_t left_height; + int32_t right_height; + if (tree != NULL && tree->left == tree) + { + return tree_get_height(tree->right); + } + if(tree == NULL) + { + return 0; + } + left_height = tree_get_height(tree->left); + right_height = tree_get_height(tree->right); + return (left_height > right_height) ? (left_height + 1) : (right_height + 1); +} + +static void tree_set_balance(ptree_node_t tree) +{ + if (tree != NULL && tree->left == tree) + { + tree_get_height(tree->right); + return; + } + + if(tree != NULL) + { + tree->balance = tree_get_height(tree->right) - tree_get_height(tree->left); + } +} + +static ptree_node_t tree_turn_left(ptree_node_t tree) +{ + ptree_node_t tree_node; + if (tree != NULL && tree->left == tree) + { + return tree_turn_left(tree->right); + } + + if(tree == NULL) + { + return NULL; + } + + // tree -> original node[a] + // tree_node -> original right subnode[b] of [a] + tree_node = tree->right; + + // 1. replace the children of the parent node + if(tree->parent->parent != NULL) + { + // not root + if(tree->parent->left == tree) + { + tree->parent->left = tree_node; + } + else + { + tree->parent->right = tree_node; + } + } + tree_node->parent = tree->parent; + + // 2. turn left + tree->parent = tree_node; + tree->right = tree_node->left; + tree_node->left = tree; + if(tree->right != NULL) + { + tree->right->parent = tree; + } + tree_set_balance(tree); + tree_set_balance(tree_node); + return tree_node; +} + + +static ptree_node_t tree_turn_right(ptree_node_t tree) +{ + ptree_node_t tree_node; + if (tree != NULL && tree->left == tree) + { + return tree_turn_left(tree->right); + } + + if(tree == NULL) + { + return NULL; + } + + // tree -> original node[a] + // tree_node -> original left subnode[b] of [a] + tree_node = tree->left; + + // 1. replace the children of the parent node + if(tree->parent->parent != NULL) + { + // not root + if(tree->parent->left == tree) + { + tree->parent->left = tree_node; + } + else + { + tree->parent->right = tree_node; + } + } + tree_node->parent = tree->parent; + + // 2. turn left + tree->parent = tree_node; + tree->left = tree_node->right; + tree_node->right = tree; + if(tree->left != NULL) + { + tree->left->parent = tree; + } + tree_set_balance(tree); + tree_set_balance(tree_node); + return tree_node; +} + + +static ptree_node_t tree_turn_left_then_right(ptree_node_t tree) +{ + if (tree != NULL && tree->left == tree) + { + return tree_turn_left(tree->right); + } + + if(tree == NULL) + { + return NULL; + } + + // first left then right + tree->left = tree_turn_left(tree->left); + return tree_turn_right(tree); +} + + +static ptree_node_t tree_turn_right_then_left(ptree_node_t tree) +{ + if (tree != NULL && tree->left == tree) + { + return tree_turn_left(tree->right); + } + + if(tree == NULL) + { + return NULL; + } + + // first left then right + tree->right = tree_turn_right(tree->right); + return tree_turn_left(tree); +} + + +bool tree_rebalance(ptree_node_t tree) +{ + if (tree != NULL && tree->left == tree) + { + return tree_rebalance(tree->right); + } + + if(tree == NULL) + { + return false; + } + + tree_set_balance(tree); + // left is greater than right + if(tree->balance == -2) + { + if(tree->left->balance <= 0) + { + // node-left-left + tree = tree_turn_right(tree); + } + else + { + // node-left-rigt + tree = tree_turn_left_then_right(tree); + } + } + // right is greater than left + else if(tree->balance == 2) + { + if(tree->right->balance >= 0) + { + // node-right-right + tree = tree_turn_left(tree); + } + else + { + // node-right-left + tree = tree_turn_right_then_left(tree); + } + } + + if(tree->parent->parent != NULL) + { + tree_rebalance(tree->parent); + } + else + { + tree->parent->right = tree; + } + + return true; +} +#endif + + +#if AVLTREE == 1 +#include "stack.h" +#include "queue.h" + +// function declare +static bool tree_rebalance(ptree_t head, ptree_node_t tree); + + +bool tree_init(ptree_t *head) +{ + *head = (ptree_t)malloc(sizeof(tree_t)); + if(*head == NULL) + { + return false; + } + (*head)->tree = NULL; + (*head)->size = 0; + return true; +} + +void tree_destroy(ptree_t * head) +{ + if(*head != NULL) + { + tree_clear(*head); + free(*head); + *head = NULL; + } +} + +bool tree_empty(ptree_t head) +{ + return ((head == NULL) || (head->tree == NULL)) ? true : false; +} + +void tree_clear(ptree_t head) +{ + pqueue_t queue; + ptree_node_t root; + ptree_node_t tree_node; + + if((head == NULL) || head->tree == NULL) + { + return ; + } + root = head->tree; + + queue_init(&queue); + queue_in(queue,root); + + while(!queue_empty(queue)) + { + queue_out(queue, &tree_node); + if(tree_node->left != NULL) + { + queue_in(queue,tree_node->left); + } + if(tree_node->right != NULL) + { + queue_in(queue,tree_node->right); + } + + free(tree_node); + tree_node = NULL; + } + + queue_destroy(&queue); + + head->tree = NULL; + head->size = 0; +} + +uint32_t tree_get_size(ptree_t head) +{ + return head->size; +} + +static ptree_node_t tree_find(ptree_t head, tree_data_t data) +{ + ptree_node_t root; + + if((head == NULL) || head->tree == NULL) + { + return NULL; + } + root = head->tree; + + while(root != NULL) + { + if(data < root->data) + { + if(root->left != NULL) + { + root = root->left; + } + else + { + return root; + } + } + else if(data > root->data) + { + if(root->right != NULL) + { + root = root->right; + } + else + { + return root; + } + } + else + { + // == + return root; + } + } + + return root; +} + +bool tree_insert(ptree_t head, tree_data_t data) +{ + ptree_node_t tree_node; + ptree_node_t new_node; + + if(head == NULL) + { + return false; + } + + // no root of tree + if(head->tree == NULL) + { + new_node = (ptree_node_t)malloc(sizeof(tree_node_t)); + if (new_node == NULL) + { + return false; + } + new_node->data = data; + new_node->left = NULL; + new_node->right = NULL; + new_node->parent = NULL; // the parent of root is NULL + new_node->balance = 0; // balance of avl tree + + head->tree = new_node; + } + else + { + tree_node = tree_find(head,data); + if(data < tree_node->data) + { + new_node = (ptree_node_t)malloc(sizeof(tree_node_t)); + if(new_node == NULL) + { + return false; + } + new_node->data = data; + new_node->left = NULL; + new_node->right = NULL; + new_node->parent = tree_node; + new_node->balance = 0; // balance of avl tree + + tree_node->left = new_node; + // avl tree rebalance + tree_rebalance(head, tree_node); + } + else + { + new_node = (ptree_node_t)malloc(sizeof(tree_node_t)); + if(new_node == NULL) + { + return false; + } + new_node->data = data; + new_node->left = NULL; + new_node->right = NULL; + new_node->parent = tree_node; + new_node->balance = 0; // balance of avl tree + + tree_node->right = new_node; + + // avl tree rebalance + tree_rebalance(head, tree_node); + } + } + + if (head->size < _UI32_MAX) + { + head->size++; + } + return true; +} + +static ptree_node_t tree_get_node_min(ptree_node_t tree) +{ + while(tree != NULL) + { + if(tree->left != NULL) + { + tree = tree->left; + } + else + { + return tree; + } + } + return tree; +} + +static void tree_delete_single_child(ptree_t head, ptree_node_t tree) +{ + if((head == NULL) || head->tree == NULL) + { + return ; + } + + if(tree == NULL) + { + return ; + } + + if(tree->parent == NULL) + { + // delete the root of tree + if(tree->left == NULL) + { + head->tree = tree->right; + if(tree->right != NULL) + { + tree->right->parent = tree->parent; + } + } + else + { + head->tree = tree->left; + tree->left->parent = tree->parent; + } + } + else + { + // delete other node of tree + if(tree->parent->left == tree) + { + // left subtree + if(tree->left == NULL) + { + tree->parent->left = tree->right; + if(tree->right != NULL) + { + tree->right->parent = tree->parent; + } + } + else + { + tree->parent->left = tree->left; + tree->left->parent = tree->parent; + } + } + else + { + // rigth subtree + if(tree->left == NULL) + { + tree->parent->right = tree->right; + if(tree->right != NULL) + { + tree->right->parent = tree->parent; + } + } + else + { + tree->parent->right = tree->left; + tree->left->parent = tree->parent; + } + } + + // avl tree rebalance + tree_rebalance(head, tree->parent); + } + free(tree); +} + +static void tree_delete_double_child(ptree_t head, ptree_node_t tree) +{ + if((head == NULL) || head->tree == NULL) + { + return ; + } + + // I think this idea is great! + ptree_node_t tree_node = tree_get_node_min(tree->right); + if(tree_node != NULL) + { + tree->data = tree_node->data; + tree_delete_single_child(head, tree_node); + } +} + +bool tree_delete(ptree_t head, tree_data_t data) +{ + ptree_node_t tree_node; + + if((head == NULL) || head->tree == NULL) + { + return false; + } + + tree_node = tree_find(head,data); + if(tree_node == NULL) + { + return false; + } + + if((tree_node->left != NULL) && (tree_node->right != NULL)) + { + tree_delete_double_child(head, tree_node); + } + else + { + tree_delete_single_child(head, tree_node); + } + + if(head->size > 0) + { + head->size--; + } + return true; +} + +bool tree_get_min(ptree_t head, tree_data_t *data) +{ + ptree_node_t root; + + if((head == NULL) || head->tree == NULL) + { + return false; + } + root = head->tree; + + while(root != NULL) + { + if(root->left != NULL) + { + root = root->left; + } + else + { + *data = root->data; + return true; + } + } + return false; +} + +bool tree_get_max(ptree_t head, tree_data_t *data) +{ + ptree_node_t root; + if((head == NULL) || head->tree == NULL) + { + return false; + } + root = head->tree; + + while(root != NULL) + { + if(root->right != NULL) + { + root = root->right; + } + else + { + *data = root->data; + return true; + } + } + return false; +} + +void tree_traversal_depth_preorder(ptree_t head, tree_data_disp_t tree_data_disp) +{ + pstack_t stack; + ptree_node_t root; + ptree_node_t tree_node; + + if((head == NULL) || head->tree == NULL) + { + return ; + } + root = head->tree; + + stack_init(&stack); + tree_node = root; + while(!stack_empty(stack) || tree_node != NULL) + { + if (tree_node != NULL) + { + tree_data_disp(tree_node->data); + + stack_push(stack, tree_node); + tree_node = tree_node->left; + } + else + { + stack_pop(stack, &tree_node); + tree_node = tree_node->right; + } + } + + stack_destroy(&stack); +} + +void tree_traversal_depth_inorder(ptree_t head, tree_data_disp_t tree_data_disp) +{ + pstack_t stack; + ptree_node_t root; + ptree_node_t tree_node; + + if((head == NULL) || head->tree == NULL) + { + return ; + } + root = head->tree; + + stack_init(&stack); + tree_node = root; + while(!stack_empty(stack) || tree_node != NULL) + { + if (tree_node != NULL) + { + stack_push(stack, tree_node); + tree_node = tree_node->left; + } + else + { + stack_pop(stack, &tree_node); + tree_data_disp(tree_node->data); + tree_node = tree_node->right; + } + } + + stack_destroy(&stack); +} + +void tree_traversal_depth_postorder(ptree_t head, tree_data_disp_t tree_data_disp) +{ + pstack_t stack; + pstack_t stack_disp; + ptree_node_t root; + ptree_node_t tree_node; + + if((head == NULL) || head->tree == NULL) + { + return ; + } + root = head->tree; + + stack_init(&stack); + stack_init(&stack_disp); + tree_node = root; + while(!stack_empty(stack) || tree_node != NULL) + { + if (tree_node != NULL) + { + stack_push(stack_disp,tree_node); + + stack_push(stack, tree_node); + tree_node = tree_node->right; + } + else + { + stack_pop(stack, &tree_node); + tree_node = tree_node->left; + } + } + + while(!stack_empty(stack_disp)) + { + stack_pop(stack_disp, &tree_node); + tree_data_disp(tree_node->data); + } + + stack_destroy(&stack); + stack_destroy(&stack_disp); +} + +void tree_traversal_breadth(ptree_t head, tree_data_disp_t tree_data_disp) +{ + pqueue_t queue; + ptree_node_t root; + ptree_node_t tree_node; + + if((head == NULL) || head->tree == NULL) + { + return ; + } + root = head->tree; + + queue_init(&queue); + queue_in(queue,root); + if(root != NULL) + { + while(!queue_empty(queue)) + { + queue_out(queue,&tree_node); + if(tree_node->left != NULL) + { + queue_in(queue,tree_node->left); + } + if(tree_node->right != NULL) + { + queue_in(queue,tree_node->right); + } + + tree_data_disp(tree_node->data); + } + } + + queue_destroy(&queue); +} + +// --------------- AVL ---------------------- +static int32_t tree_get_height(ptree_node_t tree) +{ + pqueue_t queue; + ptree_node_t root; + ptree_node_t tree_node; + + int32_t height = 0; + uint32_t count = 0; + uint32_t next_level_node_cnt = 0; + + if(tree == NULL) + { + return false; + } + root = tree; + + queue_init(&queue); + queue_in(queue,root); + if(root != NULL) + { + while(!queue_empty(queue)) + { + queue_out(queue,&tree_node); + if(tree_node->left != NULL) + { + queue_in(queue,tree_node->left); + } + if(tree_node->right != NULL) + { + queue_in(queue,tree_node->right); + } + + if(count == next_level_node_cnt) + { + next_level_node_cnt = queue_get_size(queue); + count = 1; + height ++; + } + else + { + count++; + } + } + } + + queue_destroy(&queue); + return height; +} + +static void tree_set_balance(ptree_node_t tree) +{ + if (tree != NULL) + { + tree->balance = tree_get_height(tree->right) - tree_get_height(tree->left); + } +} + +static ptree_node_t tree_turn_left(ptree_node_t tree) +{ + ptree_node_t tree_node; + ptree_node_t root; + + if(tree == NULL) + { + return NULL; + } + root = tree; + + // tree -> original node[a] + // tree_node -> original right subnode[b] of [a] + tree_node = root->right; + + // 1. replace the children of the parent node + if(root->parent != NULL) + { + // not root + if(root->parent->left == root) + { + root->parent->left = tree_node; + } + else + { + root->parent->right = tree_node; + } + } + tree_node->parent = root->parent; + + // 2. turn left + root->parent = tree_node; + root->right = tree_node->left; + tree_node->left = root; + if(root->right != NULL) + { + root->right->parent = root; + } + + // 3. set balance + tree_set_balance(root); + tree_set_balance(tree_node); + return tree_node; +} + + +static ptree_node_t tree_turn_right(ptree_node_t tree) +{ + ptree_node_t tree_node; + ptree_node_t root; + + if(tree == NULL) + { + return NULL; + } + root = tree; + + // tree -> original node[a] + // tree_node -> original left subnode[b] of [a] + tree_node = root->left; + + // 1. replace the children of the parent node + if(root->parent != NULL) + { + // not root + if(root->parent->left == root) + { + root->parent->left = tree_node; + } + else + { + root->parent->right = tree_node; + } + } + tree_node->parent = root->parent; + + // 2. turn left + root->parent = tree_node; + root->left = tree_node->right; + tree_node->right = root; + if(root->left != NULL) + { + root->left->parent = root; + } + tree_set_balance(root); + tree_set_balance(tree_node); + return tree_node; +} + + +static ptree_node_t tree_turn_left_then_right(ptree_node_t tree) +{ + ptree_node_t root; + if(tree == NULL) + { + return NULL; + } + root = tree; + + // first left then right + root->left = tree_turn_left(root->left); + return tree_turn_right(root); +} + + +static ptree_node_t tree_turn_right_then_left(ptree_node_t tree) +{ + ptree_node_t root; + if(tree == NULL) + { + return NULL; + } + root = tree; + + // first left then right + root->right = tree_turn_right(root->right); + return tree_turn_left(root); +} + + +static bool tree_rebalance(ptree_t head, ptree_node_t tree) +{ + ptree_node_t root; + + if((head == NULL) || head->tree == NULL) + { + return false; + } + if(tree == NULL) + { + return false; + } + + do + { + tree_set_balance(tree); + // left is greater than right + if(tree->balance == -2) + { + if(tree->left->balance <= 0) + { + // node-left-left + tree = tree_turn_right(tree); + } + else + { + // node-left-rigt + tree = tree_turn_left_then_right(tree); + } + } + // right is greater than left + else if(tree->balance == 2) + { + if(tree->right->balance >= 0) + { + // node-right-right + tree = tree_turn_left(tree); + } + else + { + // node-right-left + tree = tree_turn_right_then_left(tree); + } + } + + root = tree; + tree = tree->parent; + }while(tree != NULL); + + head->tree = root; + return true; +} + +#endif + diff --git a/datastruct/tree.h b/datastruct/tree.h new file mode 100644 index 0000000..e2db10d --- /dev/null +++ b/datastruct/tree.h @@ -0,0 +1,69 @@ +#ifndef _TREE_H_ +#define _TREE_H_ + +#include "common.h" + +#if AVLTREE == 1 || RAVLTREE == 1 +// typedef int tree_data_t; + +typedef struct _tree_node_t +{ + tree_data_t data; + struct _tree_node_t * left; + struct _tree_node_t * right; + struct _tree_node_t * parent; + int32_t balance; // balance of avl tree +}tree_node_t, *ptree_node_t; + + +typedef struct _tree_t +{ + struct _tree_node_t * tree; + uint32_t size; +}tree_t, *ptree_t; + +typedef void (*tree_data_disp_t)(tree_data_t data); + +#endif + + +#if RAVLTREE == 1 + bool tree_init(ptree_node_t *head); + void tree_destroy(ptree_node_t *head); + bool tree_empty(ptree_node_t head); + void tree_clear(ptree_node_t head); + uint32_t tree_get_size(ptree_node_t head); + + bool tree_insert(ptree_node_t head, tree_data_t data); + bool tree_delete(ptree_node_t head, tree_data_t data); + bool tree_get_min(ptree_node_t head, tree_data_t *data); + bool tree_get_max(ptree_node_t head, tree_data_t *data); + + void tree_traversal_depth_preorder(ptree_node_t head, tree_data_disp_t tree_data_disp); + void tree_traversal_depth_inorder(ptree_node_t head, tree_data_disp_t tree_data_disp); + //void tree_traversal_depth_postorder(ptree_node_t head, tree_data_disp_t tree_data_disp); + //void tree_traversal_breadth(ptree_node_t head, tree_data_disp_t tree_data_disp); + +#endif + +#if AVLTREE == 1 + bool tree_init(ptree_t *head); + void tree_destroy(ptree_t *head); + bool tree_empty(ptree_t head); + void tree_clear(ptree_t head); + uint32_t tree_get_size(ptree_t head); + + bool tree_insert(ptree_t head, tree_data_t data); + bool tree_delete(ptree_t head, tree_data_t data); + bool tree_get_min(ptree_t head, tree_data_t *data); + bool tree_get_max(ptree_t head, tree_data_t *data); + + void tree_traversal_depth_preorder(ptree_t head, tree_data_disp_t tree_data_disp); + void tree_traversal_depth_inorder(ptree_t head, tree_data_disp_t tree_data_disp); + void tree_traversal_depth_postorder(ptree_t head, tree_data_disp_t tree_data_disp); + void tree_traversal_breadth(ptree_t head, tree_data_disp_t tree_data_disp); +#endif + + +#endif // _TREE_H_ + diff --git a/datastruct/tree_test.c b/datastruct/tree_test.c new file mode 100644 index 0000000..fa6f537 --- /dev/null +++ b/datastruct/tree_test.c @@ -0,0 +1,271 @@ + +#include "test.h" + +#ifdef TREE_TEST + +static void tree_data_display(tree_data_t data) +{ + printf("%d ", data); +} + +#ifdef TREE_RECURSION + +#define TREE_DISP_DEPTH_PRE(tree) {tree_traversal_depth_preorder(tree,tree_data_display);printf("\n");} +#define TREE_DISP_DEPTH_IN(tree) {tree_traversal_depth_inorder(tree,tree_data_display);printf("\n");} + +// tree display +#define TREE_DISP(tree) TREE_DISP_DEPTH_IN(tree) + +void tree_test(void) +{ + int32_t i = 0; + // tree_data_t dat[10] = {5,0,2,4,3,1,8,7,9,6}; // debug data + tree_data_t dat[10] = { 0,1,2,3,4,5,6,7,8,9 }; // test data1 + // tree_data_t dat[10] = { 3,1,2,5,4,8,6,7,9,0 }; // test data2 + tree_data_t tmp; + ptree_node_t tree = NULL; + + tree_init(&tree); + + for (i = 0; i < 10; i++) + { + tree_insert(tree, dat[i]); + } + printf("tree : "); + TREE_DISP(tree); + + tree_get_min(tree, &tmp); + if (tmp == 0) + { + printf("success -> tree_get_min is %d\n", tmp); + } + else + { + printf("failure -> tree_get_min is %d ?\n", tmp); + } + + tree_get_max(tree, &tmp); + if (tmp == 9) + { + printf("success -> tree_get_max is %d\n", tmp); + } + else + { + printf("failure -> tree_get_max is %d ?\n", tmp); + } + + // delete the root + tree_delete(tree, 5); + printf("del %d: ", 5); + TREE_DISP(tree); + + // delete the leaf + tree_delete(tree, 3); + printf("del %d: ", 3); + TREE_DISP(tree); + + // delete the node which has two nodes + tree_delete(tree, 8); + printf("del %d: ", 8); + TREE_DISP(tree); + + tree_clear(tree); + printf("success -> tree_clear success!\n"); + if (tree_empty(tree)) + { + printf("success -> the tree is empty\n"); + } + else + { + printf("failure -> the tree is not empty\n"); + } + + if (!tree_delete(tree, 8)) + { + printf("success -> tree is empty, so delete failureed!\n"); + } + else + { + printf("failure -> tree is empty, but delete succeed!\n"); + } + + // ------------------------------------ + // insert again + for (i = 0; i < 10; i++) + { + tree_insert(tree, dat[i]); + } + printf("tree : "); + TREE_DISP(tree); + + for (i = 0; i < 10; i++) + { + if (tree_delete(tree, i)) + { + printf("del %d: ", i); + TREE_DISP(tree); + } + } + + if (tree_empty(tree)) + { + printf("success -> the tree is empty\n"); + } + else + { + printf("failure -> the tree is not empty\n"); + } + + tree_destroy(&tree); + if (!tree_insert(tree, dat[0])) + { + printf("success -> after tree destroyed, tree_insert failureed!\n"); + } + + if (!tree_get_min(tree, &tmp)) + { + printf("success -> after tree destroyed, tree_get_min failured!\n"); + } + + if (!tree_get_max(tree, &tmp)) + { + printf("success -> after tree destroyed, tree_get_max failured!\n"); + } + + printf("----------------------------------------\n"); +} + + +#else + +#define TREE_DISP_DEPTH_PRE(tree) {tree_traversal_depth_preorder(tree,tree_data_display);printf("\n");} +#define TREE_DISP_DEPTH_IN(tree) {tree_traversal_depth_inorder(tree,tree_data_display);printf("\n");} +#define TREE_DISP_DEPTH_POST(tree) {tree_traversal_depth_postorder(tree,tree_data_display);printf("\n");} +#define TREE_DISP_BREADTH(tree) {tree_traversal_breadth(tree,tree_data_display);printf("\n");} + +// tree display +#define TREE_DISP(tree) TREE_DISP_DEPTH_IN(tree) + +void tree_test(void) +{ + int32_t i = 0; + // tree_data_t dat[10] = {5,0,2,4,3,1,8,7,9,6}; // debug data + tree_data_t dat[10] = {0,1,2,3,4,5,6,7,8,9}; // test data1 + // tree_data_t dat[10] = { 3,1,2,5,4,8,6,7,9,0 }; // test data2 + tree_data_t tmp; + ptree_t tree = NULL; + + tree_init(&tree); + + for (i = 0; i < 10; i++) + { + tree_insert(tree, dat[i]); + } + printf("tree : "); + TREE_DISP(tree); + + tree_get_min(tree, &tmp); + if(tmp == 0) + { + printf("success -> tree_get_min is %d\n",tmp); + } + else + { + printf("failure -> tree_get_min is %d ?\n", tmp); + } + + tree_get_max(tree, &tmp); + if (tmp == 9) + { + printf("success -> tree_get_max is %d\n", tmp); + } + else + { + printf("failure -> tree_get_max is %d ?\n", tmp); + } + + // delete the root + tree_delete(tree, 5); + printf("del %d: ", 5); + TREE_DISP(tree); + + // delete the leaf + tree_delete(tree, 3); + printf("del %d: ", 3); + TREE_DISP(tree); + + // delete the node which has two nodes + tree_delete(tree, 8); + printf("del %d: ", 8); + TREE_DISP(tree); + + tree_clear(tree); + printf("success -> tree_clear success!\n"); + if (tree_empty(tree)) + { + printf("success -> the tree is empty\n"); + } + else + { + printf("failure -> the tree is not empty\n"); + } + + if (!tree_delete(tree, 8)) + { + printf("success -> tree is empty, so delete failureed!\n"); + } + else + { + printf("failure -> tree is empty, but delete succeed!\n"); + } + + // ------------------------------------ + // insert again + for (i = 0; i < 10; i++) + { + tree_insert(tree, dat[i]); + } + printf("tree : "); + TREE_DISP(tree); + + for (i = 0; i < 10; i++) + { + if (tree_delete(tree, i)) + { + printf("del %d: ", i); + TREE_DISP(tree); + } + } + + if (tree_empty(tree)) + { + printf("success -> the tree is empty\n"); + } + else + { + printf("failure -> the tree is not empty\n"); + } + + tree_destroy(&tree); + if (!tree_insert(tree, dat[0])) + { + printf("success -> after tree destroyed, tree_insert failureed!\n"); + } + + if(!tree_get_min(tree,&tmp)) + { + printf("success -> after tree destroyed, tree_get_min failured!\n"); + } + + if(!tree_get_max(tree,&tmp)) + { + printf("success -> after tree destroyed, tree_get_max failured!\n"); + } + + printf("----------------------------------------\n"); +} +#endif + + +#endif +