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

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

二叉树(binary tree)是一棵树,其中每个节点都不能有多于两个的儿子。

二叉树的一个性质是平均二叉树的深度要比N小得多,这个性质有时很重要。分析表明,这个平均深度为O(N),而对于特殊类型的二叉树,即二叉查找树(binary search tree),其深度的平均值是O(logN)

二叉树的C语言实现如下:

binary_tree.h

/*
二叉树(binary Btree):
二叉树是一颗树,其中每个节点都不能有多余两个的儿子。

                    root
                   /    \
                 left   right

二叉树的一个性质是平均二叉树的深度要比N小得多。这个平均深度为O(\sqrt(n)),最大深度为N-1。
而对于特殊类型的二叉树,即二叉查找树(binary search Btree),其深度的平均值是O(log n)。


*/

#ifndef BINARY_Btree_H
#define BINARY_Btree_H

/*
二叉树的节点用左右孩子表示法来存储。
*/

typedef enum {
    false = 0,
    true
} BOOL;

struct node;
typedef struct node node;
typedef node *Btree;
typedef node *pos;

//根据先序遍历数组来创建树(先序遍历数组中用'#'来表示空节点)
Btree create_Btree_preorder(int v[], int begin, int end);
Btree create_Btree(int v[], int *begin, int end);

//将一颗树置空
Btree make_empty(Btree T);

//判断树是不是空的
BOOL is_empty(Btree T);

//为节点p添加孩子节点x
BOOL add_child(node *p, int x);

//合并两棵树T1和T2
Btree union_btree(Btree T1, Btree T2);

//先序遍历树
void preorder_traversal(Btree T);
//以数组形式打印
//数组规定如下:用'#'来表示空节点
void preorder_traversal1(Btree T);

//中序遍历
void inorder_traversal(Btree T);

//后序遍历
void postorder_traversal(Btree T);

//寻找节点x的位置
pos search(int x, Btree T);


//输出二叉树的高度
int Btree_height(Btree T);

//输出二叉树总结点数目
int node_sum(Btree T);

//叶子结点数目
int leaves_sum(Btree T);

//取出节点p的值
int retrieve_p(pos p);

//以层次方式打印输出
void print_Btree(Btree T);
void output(Btree T, int i);

#endif

binary_tree.c

#include "binary_tree.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


struct node {
    int val;
    struct node *left;//left child
    struct node *right;//right child
};

struct node;
typedef struct node node;
typedef node *Btree;
typedef node *pos;

//根据先序遍历数组来创建树(先序遍历数组中用'#'来表示空节点)
Btree create_Btree_preorder(int v[], int begin, int end)
{
    return create_Btree(v, &begin, end);
}

Btree create_Btree(int v[], int *begin, int end)
{
    if((*begin)>end || v==NULL) 
        return NULL;
    Btree T = NULL;
    if(v[*begin]!='#') {
        T=(node *)malloc(sizeof(node));
        T->val = v[*begin];
        (*begin)++;
        if(v[*begin] == '#') {
            T->left = NULL;
            (*begin)++;
            T->right = create_Btree(v, begin, end);
        } else {
            T->left = create_Btree(v, begin, end);
            (*begin)++;
            T->right = create_Btree(v, begin, end);
        }
    }
    return T;
}

//将一颗树置空
Btree make_empty(Btree T)
{
    if(T!=NULL) {
        make_empty(T->left);
        make_empty(T->right);
        printf("free node with value %d\n", T->val);
        free(T);
        T = NULL;
    }
    return T;
}

//判断树是不是空的
BOOL is_empty(Btree T)
{
    return (T == NULL);
}

//为节点p添加孩子节点x
BOOL add_child(node *p, int x)
{
    if(p->left == NULL) {
        p->left = (node*)malloc(sizeof(node));
        p->left->val = x;
        p->left->left = p->left->right = NULL;
        return true;
    } else if(p->right == NULL) {
        p->right = (node*)malloc(sizeof(node));
        p->right->val = x;
        p->right->left = p->right->right = NULL;
        return true;
    } else {
        return false;
    }
}

//合并两棵树T1和T2
Btree union_btree(Btree T1, Btree T2)
{
    Btree T;
    if(T1!=NULL && T2!=NULL) {
        /*
         * 先假设合并后的树根节点是原来两棵树根节点之和
         */
        T = (Btree)malloc(sizeof(node));
        T->val = T1->val+T2->val;
        T->left = T1;
        T->right = T2;
    } else if(T1 == NULL) {
        T = T2;
    } else {
        T = T1;
    }
    return T;
}

//先序遍历树
void preorder_traversal(Btree T)
{
    if(T!=NULL) {
        printf("%d", T->val);
        preorder_traversal(T->left);
        preorder_traversal(T->right);
    }
}

//以先序遍历数组形式打印
//数组规定如下:用'#'来表示空节点
void preorder_traversal1(Btree T)
{
    if(T!=NULL) {
        printf("%d", T->val);
        if(T->left == NULL) {
            printf("#");
            if(T->right == NULL) {
                printf("#");
            } else {
                preorder_traversal1(T->right);
            }
        } else {
            preorder_traversal1(T->left);
            if(T->right == NULL) {
                printf("#");
            } else {
                preorder_traversal1(T->right);
            }
        }
    }
}

//中序遍历
void inorder_traversal(Btree T)
{
    if(T!=NULL) {
        inorder_traversal(T->left);
        printf("%d", T->val);
        inorder_traversal(T->right);
    }
}

//后序遍历
void postorder_traversal(Btree T)
{
    if(T!=NULL) {
        postorder_traversal(T->left);
        postorder_traversal(T->right);
        printf("%d", T->val);
    }
}

//寻找节点x的位置
pos search(int x, Btree T)
{
    if(T!=NULL) {
        if(T->val == x) {
            return T;
        } else {
            pos tmp = NULL;
            if(search(x,T->left)==NULL) {
                search(x,T->right);
            }
            return tmp;
        }
    } else {
        return NULL;
    }
}


//输出二叉树中某个节点的高度
//对任意节点n_i,n_i的深度(depth)为从根到n_i的唯一路径的长。因此,根的深度为0。
//n_i的高(height)是从n_i到一片树叶的最长路径的长。
//因此所有树叶的高度都是0。一棵树的高等于它的根的高。
//一棵树的深度等于它的最深的树叶的深度,该深度总是等于这棵树的高。
int Btree_height(Btree T)
{
    static int h = -1;
    if(T!=NULL) {
        if(T->left==NULL && T->right==NULL) {
            h=0;
        }else {
            int h1, h2;
            h1 = Btree_height(T->left)+1;
            h2 = Btree_height(T->right)+1;
            h = (h1>h2?h1:h2);
        }
    }
    return h;
}

//输出二叉树总结点数目
int node_sum(Btree T)
{
    int sum = 0;
    if(T!=NULL) {
        if(T->left==NULL && T->right==NULL) {
            sum = 1;
        }else {
            int sum1, sum2;
            sum1 = node_sum(T->left);
            sum2 = node_sum(T->right);
            sum = sum1+sum2+1;
        }
    }
    return sum;
}

//叶子结点数目
int leaves_sum(Btree T)
{
    int sum = 0;
    if(T!=NULL) {
        if(T->left==NULL && T->right==NULL) {
            sum = 1;
        }else {
            int sum1, sum2;
            sum1 = leaves_sum(T->left);
            sum2 = leaves_sum(T->right);
            sum = sum1+sum2;
        }
    }
    return sum;
}

//取出节点p的值
int retrieve_p(pos p)
{
    return p->val;
}

//以层次方式打印输出
void print_Btree(Btree T)
{
    output(T,0);
}
void output(Btree T, int i)
{
    if(T != NULL) {
        for(int j = 0; j<i; j++) {
            printf("\t");
        }
        printf("%d\n", T->val);
        i++;
        if(!(T->left == NULL && T->right == NULL)) {
            if(T->left == NULL) {
                printf("\n");
                output(T->right,i);//输出右子树
            } else if(T->right == NULL) {
                output(T->left,i);//输出左子树
                printf("\n");
            } else {
                output(T->left,i);//输出左子树
                output(T->right,i);//输出右子树
            }
        }
    }
}

main.c

#include "binary_tree.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int main()
{
    int A[15]={1,2,4,'#','#',5,'#','#',3,6,'#','#',7,'#','#'};
    int B[9] = {1,2,4,'#','#','#',3,'#','#'};
    int C[7] = {5,6,'#','#',7,'#','#'};
    int h = 0, sum = 0, leaves = 0;
    int x = 2;
    pos tmp = NULL;
    Btree T = create_Btree_preorder(A,0,14);
    Btree T1 = create_Btree_preorder(B,0,8);
    Btree T2 = create_Btree_preorder(C,0,6);

    print_Btree(T);
    preorder_traversal(T);
    printf("\n");
    inorder_traversal(T);
    printf("\n");
    postorder_traversal(T);
    printf("\n");

    preorder_traversal1(T);
    printf("\n");

    Btree pos = search(x,T);
    h = Btree_height(pos);
    printf("height of the node %d: %d\n", x,h);


    sum = node_sum(T);
    printf("this tree has %d node(s)\n", sum);

    leaves = leaves_sum(T);
    printf("this tree has %d leaves\n", leaves);

    tmp = make_empty(T);
    printf("%d\n", is_empty(tmp));

    print_Btree(T1);
    print_Btree(T2);
    T = union_btree(T1,T2);
    print_Btree(T);

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