zoukankan      html  css  js  c++  java
  • 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
    ", 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("	");
            }
            printf("%d
    ", T->val);
            i++;
            if(!(T->left == NULL && T->right == NULL)) {
                if(T->left == NULL) {
                    printf("
    ");
                    output(T->right,i);//输出右子树
                } else if(T->right == NULL) {
                    output(T->left,i);//输出左子树
                    printf("
    ");
                } 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("
    ");
        inorder_traversal(T);
        printf("
    ");
        postorder_traversal(T);
        printf("
    ");
    
        preorder_traversal1(T);
        printf("
    ");
    
        Btree pos = search(x,T);
        h = Btree_height(pos);
        printf("height of the node %d: %d
    ", x,h);
    
    
        sum = node_sum(T);
        printf("this tree has %d node(s)
    ", sum);
    
        leaves = leaves_sum(T);
        printf("this tree has %d leaves
    ", leaves);
    
        tmp = make_empty(T);
        printf("%d
    ", is_empty(tmp));
    
        print_Btree(T1);
        print_Btree(T2);
        T = union_btree(T1,T2);
        print_Btree(T);
    
        return 0;
    }
  • 相关阅读:
    linux下通过命令行把文件拷贝到U盘上
    Fuzzy finder(fzf+vim) 使用入门指南
    利器: Mac自带的图片工具Sips
    C/C++性能测试工具GNU gprof
    ubuntu 16.04安装perf
    带你了解SDL
    Android USB Headset: Device Specification
    程序猿的看迪士尼
    音频处理贤内助--libsndfile
    蓝牙协议中的SBC编解码原理和仿真
  • 原文地址:https://www.cnblogs.com/born2run/p/9581331.html
Copyright © 2011-2022 走看看