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("
    ");
    }
    

      

  • 相关阅读:
    scrapy中selenium的应用
    Django的锁和事务
    redis
    【leetcode】187. Repeated DNA Sequences
    【leetcode】688. Knight Probability in Chessboard
    【leetcode】576. Out of Boundary Paths
    【leetcode】947. Most Stones Removed with Same Row or Column
    【leetcode】948. Bag of Tokens
    【leetcode】946. Validate Stack Sequences
    【leetcode】945. Minimum Increment to Make Array Unique
  • 原文地址:https://www.cnblogs.com/mic-chen/p/9245137.html
Copyright © 2011-2022 走看看