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\n", 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("\t");
        }
        printf("%d\n", 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("\n");
    //postorder_traversal(T);
    //printf("\n");
    //pos t = search(2,T);
    //printf("%d\n", t->val);
    T1 = create_tree_preorder(A, 0, 15);
    print_tree(T1);
    preorder_traversal(T1);
    printf("\n");
    tmp = make_empty(T1);
    printf("%d\n", is_empty(tmp));
    print_tree(tmp);
    postorder_traversal(tmp);

    return 0;
}
posted @ 2018-07-01 14:38  main_c  阅读(538)  评论(0编辑  收藏  举报