zoukankan      html  css  js  c++  java
  • 一种多叉树的实现,提供树形结构打印,树转表输出等功能

    多叉树的变种有很多很多种,根据不同的应用需要,对树节点的封装,对树的查找等操作的要求各不一样。

    在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
    ");
                return 0 ; 
            } else {
                tree->init_flag = 0;
                printf("task tree Create Semaphore fail
    ");
                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
    ");
        }
        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
    ");
                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] = '';
        tree->stack_point++;
    
        // 打印偏移
        if(offset_flag) {
            for(j = 0; j < tree->stack_point-1; j++) {
                printf("%s",tree->stack_buf[j]);
            }
        }
       
        // 打印本节点
        prefix[i] = '';
        printf("%s",prefix);
        printf("%s",name);
        if(0 == node->n_child) {
            printf("
    ");
        }
    
        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
    ");
                }
            } else {
                ret = -2;
                printf("remove tree node error : chilsren num is 0
    ");
            }
        }
        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
    ");
            tree->init_flag = 1;
            return 0 ; 
        } else {
            printf("ak_tree_init fail
    ");
            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:
    ");
    
        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("
    ");
    
    }
    
    
    /*
    打印输出树形结构
    
    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("
    ");
    }
    

      

  • 相关阅读:
    【NOIp复习】图论算法模板合集
    【NOI导刊】【归并排序求逆序对】最接近神的人
    【NOIp 2012】【线段树】借教室
    【NOIp复习】最近公共祖先LCA&区间最大最小RMQ
    【NOIp 2015】【二分答案】跳石头
    【NOIp 2015】【DFS】斗地主
    【vijos】【BFS+hash】毒药?解药?
    【NOIp模拟】【dp】俄罗斯方块
    【NOIp模拟】【二分图or并查集】GoToandPlay
    【vjios】【DFS】切蛋糕
  • 原文地址:https://www.cnblogs.com/mic-chen/p/9245137.html
Copyright © 2011-2022 走看看