zoukankan      html  css  js  c++  java
  • 0x01数据结构——C语言实现(树)

    0x01数据结构——C语言实现(树)

    树(tree):
    一棵树是一些节点的集合。这个集合可以是空集;若非空,则一棵树由称为根(root)的节点r以及0个或多个非空的(子)树T1,T2,…,Tk组成,这些子树种每一颗的根都被来自根r的一条有向边(edge)所连接。每一棵子树的根叫做根r的儿子(child),而r是每一棵子树的根的父亲(parent)。

    从节点n1到节点nk的路径(path)定义为节点n1,n2,…,nk的一个序列,使得对于1i<k,节点ni是节点ni+1的父亲。这个路径的长(length)为该路径上的变得条数,即k-1.从每一个节点到它自己有一条长为0的路径。在一颗树中从根到每一个节点恰好存在一条路径。

    对任意节点nini的深度(depth)为从根到ni的唯一路径的长。因此,根的深度为0。ni的高(height)是从ni到一片树叶的最长路径的长。因此所有树叶的高度都是0。一棵树的高等于它的根的高。一棵树的深度等于它的最深的树叶的深度,该深度总是等于这棵树的高。

    树的C语言实现:

    tree.h

    /*
    树(tree):
    一棵树是一些节点的集合。
    这个集合可以是空集;若非空,则一棵树由称为根(root)的节点r以及0个或多个非空的(子)
    树T1,T2,...,Tk组成,这些子树种每一颗的根都被来自根r的一条有向边(edge)所连接。
    每一棵子树的根叫做根r的儿子(child),而r是每一棵子树的根的父亲(parent)。
    
                        root
    
                    /  /   |     ...  
                   T1  T2  T3   T4 ... Tk
    */
    
    #ifndef TREE_H
    #define TREE_H
    
    /*
    树的节点用孩子兄弟表示法来存储。
    */
    
    typedef enum {
        false = 0,
        true
    } BOOL;
    
    struct node;
    typedef struct node node;
    typedef node *tree;
    typedef node *pos;
    
    
    //根据先序遍历创建一棵树
    //输入数组规定如下:如果一个节点没有孩子,他后面接‘#’,如果没有兄弟接‘$’,如果两种情况都有接“%”
    tree create_tree_preorder(int v[], int left, int right);
    
    //将一颗树置空
    tree make_empty(tree T);
    
    //判断树是不是空的
    BOOL is_empty(tree T);
    
    //为节点p添加孩子节点x
    void add_child(node *p, int x);
    
    //根据先序遍历数组来创建树(先序遍历数组中用'#'来表示空节点)
    tree create_by_preorder(int n[], int N);
    
    //先序遍历树
    void preorder_traversal(tree T);
    //以数组形式打印
    //数组规定如下:如果一个节点没有孩子,他后面接‘#’,如果没有兄弟接‘$’,如果两种情况都有接“%”
    void preorder_traversal1(tree T);
    
    //后序遍历
    void postorder_traversal(tree T);
    
    //寻找节点x的位置
    pos search(int x, tree T);
    
    //取出节点p的值
    int retrieve_p(pos p);
    
    //以层次方式打印输出
    void print_tree(tree T);
    void output(tree T, int i);
    
    #endif
    

    tree.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "tree.h"
    
    
    struct node {
        int val;
        struct node *child;
        struct node *bro;
    };
    
    /*
    struct node;
    typedef struct node node;
    typedef node *tree;
    typedef node *pos;
    */
    
    
    
    //根据先序遍历创建一棵树, 层与层之间
    //输入数组规定如下:如果一个节点没有孩子,他后面接‘#’,如果没有兄弟接‘$’,如果两种情况都有接“%”
    tree create_tree_preorder(int v[], int left, int right)
    {
        if(left>right || v==NULL) 
            return NULL;
        tree T = NULL;
        int i = left;
        if(v[i]!='#' && v[i]!='$' && v[i]!='%') {
            T = (node *)malloc(sizeof(node));
            T->val = v[i];
            i++;
            if(v[i] == '#') {
                i++;
                T->child = NULL;
                T->bro = create_tree_preorder(v, i, right);
            } else if(v[i] == '$') {
                i++;
                T->bro = NULL;
                T->child = create_tree_preorder(v, i, right);
            } else if(v[i] == '%') {
                i++;
                T->bro = NULL;
                T->child = NULL;
            } else {
                T->child = create_tree_preorder(v, i, right);
                while(v[i]!='%') {
                    i++;
                }
                i++;
                T->bro = create_tree_preorder(v, i, right);
            }
        }
        return T;
    }
    
    //将一颗树置空
    tree make_empty(tree T)
    {
        if(T!=NULL) {
            make_empty(T->child);
            make_empty(T->bro);
            printf("free node with value %d
    ", T->val);
            free(T);
            T = NULL;
        }
        return T;
    }
    
    //判断树是不是空的
    BOOL is_empty(tree T)
    {
        return T == NULL;
    }
    
    //为节点p添加孩子节点x
    void add_child(node *p, int x)
    {
        node *tmp = p->child;
        if(tmp == NULL) {
            tmp = (node *)malloc(sizeof(node));
            tmp->val = x;
            tmp->child = NULL;
            tmp->bro = NULL;
        } else {
            while(tmp->bro != NULL) {
                tmp = tmp->bro;
            }
            tmp->bro = (node *)malloc(sizeof(node));
            tmp->bro->val = x;
            tmp->bro->child = NULL;
            tmp->bro->bro = NULL;
        }
    }
    
    //先序遍历树
    void preorder_traversal(tree T)
    {
        if(T != NULL) {
            printf("%d", T->val);
            tree tmp;
            tmp = T->child;
            while(tmp!=NULL) {
                preorder_traversal(tmp);
                tmp = tmp->bro;
            }
        }
    }
    
    //输出一种可以回复成原始树的先序遍历数组
    //数组规定如下:如果一个节点没有孩子,他后面接‘#’,如果没有兄弟接‘$’,如果两种情况都有接“%”
    void preorder_traversal1(tree T)
    {
        tree tmp;
        if(T!=NULL) {
            printf("%d",T->val);
            if(T->child == NULL && T->bro != NULL) {
                printf("#");
            }
            if(T->child != NULL && T->bro == NULL) {
                printf("$");
            }
            if(T->child == NULL && T->bro == NULL) {
                printf("%%");
            }
            tmp = T->child;
            while(tmp!=NULL) {
                preorder_traversal1(tmp);
                tmp = tmp->bro;
            }
        }
    
    }
    
    
    //后序遍历
    void postorder_traversal(tree T)
    {
        if(T != NULL) {
            tree tmp;
            tmp = T->child;
            while(tmp!=NULL) {
                postorder_traversal(tmp);
                tmp = tmp->bro;
            }
            printf("%d", T->val);
        }
    }
    
    
    //寻找节点x的位置
    pos search(int x, tree T)
    {
        if(T!=NULL) {
            if(T->val == x) {
                return T;
            } else {
                tree tmp = T->child;
                while(tmp!=NULL) {
                    if((T=search(x, tmp)) != NULL) {
                        break;
                    }
                    tmp = tmp->bro;
                }
            }
        }
        return T;
    
    }
    
    //取出节点p的值
    int retrieve_p(pos p)
    {
        return p->val;
    }
    
    //以层次方式打印输出
    void print_tree(tree T)
    {
        output(T,0);
    }
    
    void output(tree T, int i)//i用来记录节点的深度
    {
        if(T != NULL) {
            for(int j = 0; j<i; j++) {
                printf("	");
            }
            printf("%d
    ", T->val);
            tree tmp;
            tmp = T->child;
            i++;
            while(tmp!=NULL) {
                output(tmp,i);//输出各个子树
                tmp = tmp->bro;
            }
        }
    }

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "tree.h"
    
    struct node {
        int val;
        struct node *child;
        struct node *bro;
    };
    
    int main()
    {
        tree T, T1;
        pos tmp;
        int A[16] = {1,'$',2,8,'#',9,'%',3,5,'%',4,'$',6,'#',7,'%'};
    
        //print_tree(T);
        //preorder_traversal1(T);
        //printf("
    ");
        //postorder_traversal(T);
        //printf("
    ");
        //pos t = search(2,T);
        //printf("%d
    ", t->val);
        T1 = create_tree_preorder(A, 0, 15);
        print_tree(T1);
        preorder_traversal(T1);
        printf("
    ");
        tmp = make_empty(T1);
        printf("%d
    ", is_empty(tmp));
        print_tree(tmp);
        postorder_traversal(tmp);
    
        return 0;
    }
  • 相关阅读:
    Pro ASP.NET Core MVC2
    vscode
    git命令使用
    单行函数
    过滤和排序
    oracle基本查询
    斐波那契数列的递归实现
    队列的顺序存储结构
    队列的链式存储结构
    折半查找法
  • 原文地址:https://www.cnblogs.com/born2run/p/9581332.html
Copyright © 2011-2022 走看看