多叉树的变种有很多很多种,根据不同的应用需要,对树节点的封装,对树的查找等操作的要求各不一样。
在PC数据库中,b-tree比较多,网上也较多可参考的代码,但是在嵌入式软件中,这种可能过于复杂,也不需要那么多的节点管理,
因此在效率上也不是很重视,本代码基于比较简单的实现,目的是实现对线程树的管理。
其中还有很多有待完善,特别是对用户数据的挂接的void *data的使用。
tree.h
#define SUB_TASK_MAX 32
#define TASK_NAME_LEN_MAX 32
// 采用数组方式实现,如果节点数量较多,操作频繁可优化为链表
// 所有查找均采用层次优先遍历
typedef struct ak_tree_node
{
long id;
#if 1
//int level;
struct ak_tree_node *parent;
int n_child; // number of children
struct ak_tree_node* children[SUB_TASK_MAX];
#else
//struct ak_tree_node *parent;
//struct ak_tree_node *sibling_prev;
//struct ak_tree_node *first_child;
//struct ak_tree_node *sibling;
#endif
void *data;
}ak_tree_node_t;
typedef struct ak_tree_node_list
{
ak_tree_node_t *data;
struct ak_tree_node_list *next;
}ak_tree_node_list_t;
typedef int (*TREE_GET_NAME_CB)(long id,char *name);
typedef struct ak_tree
{
ak_tree_node_t root;
char init_flag;
int stack_point;
char stack_buf[SUB_TASK_MAX][TASK_NAME_LEN_MAX];
T_hSemaphore lock;
TREE_GET_NAME_CB get_name;
}ak_tree_t;
ak_tree_node_t* ak_tree_find_node(ak_tree_t *tree,long id);
int ak_tree_insert_node_as_child(ak_tree_t *tree, long id_parent, long id_child);
int ak_tree_insert_node_as_sibling(ak_tree_t *tree, long id_sibling, long id_child);
int ak_tree_remove_node(ak_tree_t *tree, long id);
ak_tree_t *ak_tree_create(void);
int ak_tree_destroy(ak_tree_t *tree);
int ak_tree_init(ak_tree_t *tree,long id_root,TREE_GET_NAME_CB get_name);
// note:调用完后,务必调用ak_tree_release_list 释放内存
ak_tree_node_list_t* ak_tree_to_list(ak_tree_t *tree, long id);
ak_tree_node_list_t* ak_tree_get_children_list(ak_tree_t *tree, long id);
int ak_tree_release_list(ak_tree_node_list_t *list);
/*
打印输出链式结构
IDLE--ringMai--D_UART1--mcuRecv--meMain--D_CAM--command
*/
int ak_tree_print_list(ak_tree_t *tree,long id);
/*
打印输出树形结构
CMain--IDLE
|-ringMai--D_UART1
| |-WifiCon--MOAL_WO
| | `-tcpip_t
| |-TCtrCon
| `-ringHea
`-command
*/
int ak_tree_print(ak_tree_t *tree, long id);
tree.c
static ak_tree_node_t *create_node(void)
{
ak_tree_node_t *node = (ak_tree_node_t *)Fwl_Malloc(sizeof(ak_tree_node_t));
node->n_child = 0;
memset(&node->children,0,SUB_TASK_MAX);
return node;
}
static void *destroy_node(ak_tree_node_t *node)
{
return Fwl_Free(node);
}
// search by name recursion
static ak_tree_node_t* search_node_r(ak_tree_node_t* node,long id)
{
ak_tree_node_t* temp = NULL;
int i = 0;
if (node != NULL) {
if (id == node->id) {
temp = node;
} else {
for (i = 0; i < node->n_child && temp == NULL/*如果temp不为空,则结束查找*/; ++i)
{
temp = search_node_r(node->children[i],id); // 递归查找子节点
}
}
}
return temp; // 将查找到的节点指针返回,也有可能没有找到,此时temp为NULL
}
static int insert_node(ak_tree_t *tree,ak_tree_node_t* parent,long id)
{
int ret = 0;
if(0 == tree->lock) {
tree->lock = AK_Create_Semaphore(1, AK_PRIORITY);
if (tree->lock !=AK_INVALID_SUSPEND){
printf("task tree Create Semaphore ok\n");
return 0 ;
} else {
tree->init_flag = 0;
printf("task tree Create Semaphore fail\n");
return -1;
}
}
AK_Obtain_Semaphore(tree->lock, AK_SUSPEND);
if(NULL != parent) {
ak_tree_node_t *child = create_node();
child->id = id;
child->parent = parent;
parent->children[parent->n_child] = child;
parent->n_child++;
} else {
printf("insert node, parent id null\n");
}
AK_Release_Semaphore(tree->lock);
return ret;
}
ak_tree_node_list_t* tree_to_list_r(ak_tree_t *tree, ak_tree_node_t *head)
{
int i;
//ak_tree_node_t* head = NULL;
ak_tree_node_list_t *list;
// 查找节点
if(NULL == head) {
return NULL;
}
// 申请内存并初始化
list = Fwl_Malloc(sizeof(ak_tree_node_list_t));
list->data = NULL;
list->next = NULL;
ak_tree_node_list_t *list_temp = list;
list_temp->data = head;
list_temp->next = NULL;
// 递归子节点
for (i = 0; i < head->n_child; i++) {
list_temp->next = tree_to_list_r(tree,head->children[i]);
// 更新list_temp,跳到最后一个
while(NULL != list_temp->next) {
list_temp = list_temp->next;
}
}
return list;
}
static void get_node_name(ak_tree_t *tree,long id,char *name)
{
if(NULL != tree->get_name) {
tree->get_name(id,name);
} else {
name[0] = 0;
}
}
static int tree_print_node_r(ak_tree_t *tree,ak_tree_node_t *node)
{
char i;
char j;
int offset_flag = 0;
T_S8 name[16];
T_S8 prefix[8];
int name_len = 0;
get_node_name(tree,node->id,name);
name_len = strlen(name);
prefix[0] = 0;
// 利用递归,依次入栈路径上各父节点的打印信息
ak_tree_node_t *parent = node->parent;
i = 0;
if(0 != tree->stack_point) {
// 前缀 "--" or "|-" or "--"
if(NULL == parent) {
printf("parent is null,should not enter here\n");
return -1;
}
if (node == parent->children[0]) {
prefix[i] = ‘-‘;
tree->stack_buf[tree->stack_point][i++] = ‘|‘;
offset_flag = 0;
} else if(node == parent->children[parent->n_child-1]){
prefix[i] = ‘`‘;
tree->stack_buf[tree->stack_point][i++] = ‘ ‘;
offset_flag = 1;
} else {
prefix[i] = ‘|‘;
tree->stack_buf[tree->stack_point][i++] = ‘|‘;
offset_flag = 1;
}
prefix[i] = ‘-‘;
tree->stack_buf[tree->stack_point][i++] = ‘ ‘;
}
// name域
for(j = i; j < name_len+i; j++) {
tree->stack_buf[tree->stack_point][j] = ‘ ‘;
}
tree->stack_buf[tree->stack_point][j] = ‘\0‘;
tree->stack_point++;
// 打印偏移
if(offset_flag) {
for(j = 0; j < tree->stack_point-1; j++) {
printf("%s",tree->stack_buf[j]);
}
}
// 打印本节点
prefix[i] = ‘\0‘;
printf("%s",prefix);
printf("%s",name);
if(0 == node->n_child) {
printf("\n");
}
for (i = 0; i < node->n_child; i++) {
// 递归子节点
tree_print_node_r(tree,node->children[i]);
}
if(tree->stack_point > 0) {
tree->stack_point--;
}
}
//-------------------- tree api -----------------------
ak_tree_node_t* ak_tree_find_node(ak_tree_t *tree,long id)
{
return search_node_r(&tree->root,id);
}
int ak_tree_insert_node_as_child(ak_tree_t *tree, long id_parent, long id_child)
{
int ret = 0;
ak_tree_node_t* parent = NULL;
parent = search_node_r(&tree->root,id_parent);
ret = insert_node(tree,parent,id_child);
return ret;
}
int ak_tree_insert_node_as_sibling(ak_tree_t *tree, long id_sibling, long id_child)
{
int ret = 0;
ak_tree_node_t* sibling = NULL;
sibling = search_node_r(&tree->root,id_sibling);
ret = insert_node(tree,sibling->parent,id_child);
return ret;
}
int ak_tree_remove_node(ak_tree_t *tree, long id)
{
int ret = 0;
ak_tree_node_t* temp = NULL;
int i;
temp = search_node_r(&tree->root,id);
AK_Obtain_Semaphore(tree->lock, AK_SUSPEND);
if(NULL != temp) {
ak_tree_node_t *parent = temp->parent;
//printf("ak_tree_remove_node parent=%0x n_child=%d",parent,parent->n_child);
if(parent->n_child > 0) {
for(i = 0; i < parent->n_child;i++) {
if(temp == parent->children[i]) break;
}
if(i < parent->n_child) {
for(;i < parent->n_child;i++) {
parent->children[i] = parent->children[i+1];
}
destroy_node(temp);
parent->n_child--;
} else {
ret = -1;
printf("remove tree node error: match child fail\n");
}
} else {
ret = -2;
printf("remove tree node error : chilsren num is 0\n");
}
}
AK_Release_Semaphore(tree->lock);
return ret;
}
ak_tree_t *ak_tree_create(void)
{
ak_tree_t *tree = (ak_tree_t *)Fwl_Malloc(sizeof(ak_tree_t));
return tree;
}
int ak_tree_destroy(ak_tree_t *tree)
{
return Fwl_Free(tree);
}
int ak_tree_init(ak_tree_t *tree,long id_root,TREE_GET_NAME_CB get_name)
{
memset(tree,0,sizeof(ak_tree_t));
tree->root.id = id_root;
tree->init_flag = 1;
tree->get_name = get_name;
// 不能在这里创建一个为1的信号量,否则系统崩溃,因为OS调度还没有启动??
#if 0
//tree->lock = AK_Create_Semaphore(1, AK_PRIORITY);
if (tree->lock !=AK_INVALID_SUSPEND){
printf("ak_tree_init ok\n");
tree->init_flag = 1;
return 0 ;
} else {
printf("ak_tree_init fail\n");
return -1;
}
#endif
}
ak_tree_node_list_t* ak_tree_to_list(ak_tree_t *tree, long id)
{
ak_tree_node_t *head = search_node_r(&tree->root,id);
return tree_to_list_r(tree,head);
}
ak_tree_node_list_t* ak_tree_get_children_list(ak_tree_t *tree, long id)
{
ak_tree_node_list_t *self = NULL;
ak_tree_node_list_t *children = NULL;
ak_tree_node_t *head = search_node_r(&tree->root,id);
self = tree_to_list_r(tree,head);
if(NULL != self && NULL != self->next) {
children = self->next;
}
return children;
}
int ak_tree_release_list(ak_tree_node_list_t *list)
{
ak_tree_node_list_t *list_temp = NULL;
while(NULL != list) {
list_temp = list->next;
Fwl_Free(list);
list = list_temp;
}
}
/*
打印输出链式结构
IDLE--ringMai--D_UART1--mcuRecv--meMain--D_CAM--command
*/
int ak_tree_print_list(ak_tree_t *tree,long id)
{
T_S8 name[16];
ak_tree_node_list_t *children_head;
ak_tree_node_list_t *temp;
children_head = ak_tree_get_children_list(tree,id);
temp = children_head;
printf("ak_tree_print_list:\n");
get_node_name(tree,temp->data->id, name);
printf("%s",name);
temp = temp->next;
while(NULL != temp && temp->data != NULL) {
get_node_name(tree,temp->data->id, name);
printf("--%s",name);
temp = temp->next;
}
ak_tree_release_list(children_head);
printf("\r\n");
}
/*
打印输出树形结构
CMain--IDLE
|-ringMai--D_UART1
| |-WifiCon--MOAL_WO
| | `-tcpip_t
| |-TCtrCon
| `-ringHea
`-command
*/
int ak_tree_print(ak_tree_t *tree, long id)
{
memset(tree->stack_buf,0,sizeof(tree->stack_buf));
tree->stack_point = 0;
ak_tree_t *head = search_node_r(&tree->root, id);
tree_print_node_r(tree,head);
printf("\r\n");
}
原文:https://www.cnblogs.com/mic-chen/p/9245137.html