数据结构之二叉树

              今天和大家讨论的是二叉树,在讨论二叉树之前,我们在之前也接触了一维的线性存储结构,比如数组,双端链表,以及对双端的链表的封装形成栈和队列,之后又将数组和双端链表的结合形成hash表,在存储和查找方面解决了很多问题,但是一维线性存储结构仍然存在问题,比如一维的线性数据结构在查找时的效率只能达到o(n)的时间复杂度,所以为了解决上述问题,我们引入树型数据结构。

         最常见的树型结构为二叉树,二叉树有左右两个孩子,在处理二叉树时基本都采用了递归的思想,在本文章中也会给大家分享一些非递归的操作,在非递归操作时就需要借助于栈和队列。那么首先对于栈和队列进行封装,本文章中的栈和队列都是在双端链表的基础上进行封装,对于双端链表的实现在之前的博客中已经详细的进行了介绍,今天则主要说明栈、队列、二叉树的接口实现:

        我们先来说明栈的实现:

    stack.h:

#ifndef _STACK_H_
#define _STACK_H_

#include "dlist.h"
//用通用双端链表实现通用栈
//
//栈的功能是为了保存和记忆
typedef struct Stack{
    Dlist *dlist;   //使用双端链表封装栈
}Stack;


//栈的接口
Stack   *init_stack(void)                  ;    //栈的初始化
void    destroy_stack(Stack **stack)       ;    //栈的销毁
Boolean get_top(Stack *stack, void **value);    //得到栈顶元素
Boolean pop(Stack *stack)                  ;    //出栈
void    push(Stack *stack, void *value)    ;   //入栈
Boolean is_stack_empty(Stack *stack)       ;   //判断栈是否为空
int     get_stack_count(Stack *stack)      ;   //得到栈元素


#endif

接下来我们看栈的接口实现:

#include <stdio.h>
#include <stdlib.h>
#include "stack.h"

Stack   *init_stack(void)                      //栈的初始化
{
     Stack *stack = (Stack *)Malloc(sizeof(Stack));
     stack->dlist = init_dlist();

     return stack;
}

void    destroy_stack(Stack **stack)           //栈的销毁
{
    if(stack == NULL || *stack == NULL){ 
        return ;
    }
    //1.先销毁双端链表,再销毁stack控制信息
    destroy_dlist(&((*stack)->dlist));
    free(*stack); 
    *stack = NULL;
}

Boolean get_top(Stack *stack, void **value)    //得到栈顶元素
{
    if(stack == NULL || is_stack_empty(stack)){
        return FALSE;
    }
    if(value != NULL){
        get_front(stack->dlist, value);
        return TRUE;
    }
}
Boolean pop(Stack *stack)                      //出栈
{
    if(stack == NULL || is_stack_empty(stack)){
        return FALSE;
    }
    pop_front(stack->dlist);
    return TRUE;
}

void    push(Stack *stack, void *value)       //入栈
{
    if(stack == NULL || value == NULL){ 
        return ;
    }
    push_front(stack->dlist, value);
}

Boolean is_stack_empty(Stack *stack)          //判断栈是否为空
{
    return get_stack_count(stack) == ZERO;
}

int     get_stack_count(Stack *stack)         //得到栈元素
{
    if(stack == NULL){
        return -1;
    }
    return get_dlist_count(stack->dlist);  
}
上述则是对栈的描述,下面我们来看对于队列(queue)的实现:

      首先我们来看queue.h:

   

#ifndef _QUEUE_H_
#define _QUEUE_H_

#include "dlist.h"

typedef struct Queue{
    Dlist *dlist;
}Queue;


//队列的接口
Queue   *init_queue(void)                          ;    //队列的初始化
void    destory_queue(Queue **queue)               ;    //队列的销毁
Boolean get_queue_front(Queue *queue, void **value);    //得到对首元素
Boolean is_queue_empty(Queue *queue)               ;    //判断队列是否为空
void    in(Queue *queue, void *value)              ;    //入队
Boolean out(Queue *queue)                          ;    //出队
int     get_queue_count(Queue *queue)              ;    //得到队列元素个数


#endif

    上述是对于接口的声明,下面我们来看实现:

#include <stdio.h>
#include <stdlib.h>
#include "queue.h"

Queue   *init_queue(void)                              //队列的初始化
{
    Queue * queue = NULL;
    queue = (Queue *)Malloc(sizeof(Queue));
    queue -> dlist = init_dlist();
    return queue;
}

void    destory_queue(Queue **queue)                   //队列的销毁
{
    if(queue == NULL || *queue == NULL){
        return ;
    }
    destroy_dlist (&((*queue) -> dlist));
    free(*queue);
    *queue = NULL;
}

Boolean get_queue_front(Queue *queue, void **value)    //得到对首元素
{
    if(queue == NULL || is_queue_empty(queue)){
        return FALSE;
    }
    if(value != NULL){
        return get_tail(queue -> dlist , value);
    }
    return FALSE;
}

Boolean is_queue_empty(Queue *queue)                   //判断队列是否为空
{
    return get_queue_count(queue) == ZERO;
}

void    in(Queue *queue, void *value)                  //入队
{
    if(queue == NULL || value == NULL){
        return ;
    }
    push_front(queue->dlist,value);
}

Boolean out(Queue *queue)                              //出队
{
    if(queue == NULL || is_queue_empty(queue)){
        return FALSE;
    }
    return pop_back(queue->dlist);
}

int     get_queue_count(Queue *queue)                  //得到队列元素个数
{
    if(queue == NULL){
        return -1;
    }
    return get_dlist_count(queue->dlist);
}
至此,栈(stack)和队列(queue)的封装已实现。。。

下面我们来看二叉树的实现:

      对于二叉树的节点,我们不仅要记录其数据域的值,还要记录其左孩子和右孩子的值。对于binary_tree.h的定义如下:

   

#ifndef _BINARY_TREE_H_
#define _BINARY_TREE_H_

#include "tools.h"

typedef struct Tree_node{
    char                     data;    //数据区域
    struct Tree_node *left_child ;    //左孩子  
    struct Tree_node *right_child;    //右孩子
}Tree_node;

typedef Tree_node *Bin_tree;   //二叉树根节点指针

//二叉树的接口

//二叉树的创建和销毁

Bin_tree create_tree(char **string);   //创建二叉树

Bin_tree create_tree_by_pre_mid(const char *pre_str,
             const char *mid_str, int length);    //通过先序和中序构建二叉树

Bin_tree create_tree_by_mid_last(const char *mid_str,
             const char *last_str, int length);    //通过中序和后序构建二叉树

void destroy_tree(Bin_tree *root);   //二叉树的销毁
void destroy_tree_nr(Bin_tree *root);    //二叉树的非递归销毁

//二叉树的遍历(先序、中序、后序、层序)
void pre_order_print(Bin_tree root);     //先序遍历(递归)
void mid_order_print(Bin_tree root);     //中序遍历(递归)
void last_order_print(Bin_tree root);    //后序遍历(递归)

void pre_order_print_nr(Bin_tree root);     //先序遍历(非递归)
void mid_order_print_nr(Bin_tree root);     //中序遍历(非递归)
void last_order_print_nr(Bin_tree root);    //后序遍历(非递归)

void level_order_print(Bin_tree root);    //层序遍历

//二叉树的性质(高度、节点个数、叶子节点个数)
int get_binarytree_height(Bin_tree root);    //得到二叉树的高度
int get_binarytree_node_count(Bin_tree root);    //得到二叉树的节点个数
int get_binarytree_leaf_count(Bin_tree root);    //得到二叉树的叶子节点个数
int get_binarytree_level_count(Bin_tree root, int level);  //得到二叉树指定层级节点个数

//判断是否是满二叉树、完全二叉树、平衡二叉树
Boolean is_full_binarytree(Bin_tree root);    //是否是满二叉树
Boolean is_complete_binarytree(Bin_tree root);    //是否是完全二叉树
Boolean is_balance_binarytree(Bin_tree root);    //是否是平衡二叉树

//其他操作
Bin_tree copy_binarytree(Bin_tree root);   //二叉树的拷贝
Boolean is_binarytree_equal(Bin_tree root1,
                            Bin_tree root2);    //判断两个二叉树是否相等
Tree_node *find_value(Bin_tree root, char value);    //找到指定数值的节点

Tree_node *find_common_parent(Bin_tree root, Tree_node *node1,
                   Tree_node *node2);    //找到两个节点的最近双亲节点

Tree_node *find_parent(Bin_tree root, Tree_node *node);    //找到指定节点的双亲节点
Boolean is_include_tree(Bin_tree root1,
                        Bin_tree root2);   //判断二叉树是否有包含关系
#endif

接下来我们一一讨论接口的实现:

(1)二叉树的创建:

    今天我们利用字符串创建二叉树,当遇到普通字符时我们直接创建二叉树节点,当遇到‘#’字符的时候我们认为该二叉树节点不存在,并且当二叉树的节点存在后,再遇到普通字符认为是其左孩子,当左孩子存在时再遇到普通字符我们认为是右孩子,下面我们举一个例子。

例:

ABC##DE##F##GH#I##J##

则其对应的二叉树如下图所示:

二叉树图
数据结构之二叉树_第1张图片

二叉树的创建代码如下:

Bin_tree create_tree(char **string)   //创建二叉树
{
    //"ABC##DE##F##GH#I##J##"
    //
    //
    //           A
    //         /   \
    //        B     G
    //       / \   / \
    //      C   D H   J
    //         / \ \
    //        E   F I
    //     先序:ABCDEFGHIJ
    //     中序:CBEDFAHIGJ
    //     后序:CEFDBIHJGA
    Bin_tree root = NULL;
    if(string != NULL && *string != NULL && **string != '#'){
        root = create_tree_node();
        root ->data = **string;
        (*string)++;
        root ->left_child = create_tree(string);
        (*string)++;
        root ->right_child = create_tree(string);
    }
    return root;
}
使用遍历结果创建二叉树:
      我们都知道二叉树的遍历包括先序遍历、中序遍历、后序遍历。先序遍历的访问顺序为访根、访左、访右。中序遍历的访问顺序:访左、访根、访右。后序遍历的访问顺序为:访左、访右、访根。如果我们知道先序和后序,则可以唯一确定一颗二叉树。


数据结构之二叉树_第2张图片

先序:A  B  C  D  E  F  G  H  I  J

中序:C  B  E  D  F  A  H   I  G J

后序:C  E  F  D  B   I   H  J  G A

我们可以通过先序和中序唯一确定二叉树,在先序的遍历中,在先序遍历中,我们可以很容易确定根节点,然后在中序中先确定出根节点的位置,然后左递归,右递归进行创建,其代码实现如下;

      

static int find_index(const char * pre_str,char ch)
{
    char *find = NULL;
    return (find = strchr(pre_str,ch)) ? (find - pre_str) : -1;
}
Bin_tree create_tree_by_pre_mid(const char *pre_str,
             const char *mid_str, int length)    //通过先序和中序构建二叉树
{
    //     先序:ABCDEFGHIJ
    //     中序:CBEDFAHIGJ
    Bin_tree root = NULL;
    int root_index = -1;
    char root_value = 0;
    
    if(pre_str == NULL || mid_str == NULL || length <= 0){
        return root;
    }
    root_value = pre_str[0];
    root = create_tree_node();
    root ->data = root_value;
    
    root_index = find_index(mid_str,root_value);

    root ->left_child = create_tree_by_pre_mid(pre_str + 1,mid_str,root_index);
    root ->right_child = create_tree_by_pre_mid(pre_str + root_index + 1,
                            mid_str + root_index + 1,length - root_index - 1);

    return root;
}

同理,也可由中序和后序确定出二叉树,其代码如下:

     

Bin_tree create_tree_by_mid_last(const char *mid_str,
             const char *last_str, int length)    //通过中序和后序构建二叉树
{
    //     中序:CBEDFAHIGJ
    //     后序:CEFDBIHJGA
    Bin_tree root = NULL;
    char root_value = 0;
    int root_index = -1; 
    if(mid_str == NULL || last_str == NULL || length <= 0){
        return root;
    }
    root_value = last_str[length - 1];
    root = create_tree_node();
    root ->data = root_value;
    
    root_index = find_index(mid_str,root_value);
    root ->left_child = create_tree_by_mid_last(mid_str,last_str,root_index);
    root ->right_child = create_tree_by_mid_last(mid_str + root_index + 1,
                         last_str + root_index ,length - root_index - 1); 
    return root;
}

(2)至此我们讨论完创建,接下来我们来看二叉树的销毁:

    对于二叉树的销毁,我们应该采用递归的思想,先销毁其左孩子,再销毁其右孩子,如果直接销毁根节点,则会导致二叉树的丢失。我们先来看利用递归销毁二叉树,其代码如下:

   

void destroy_tree(Bin_tree *root)   //二叉树的销毁
{
    if(root == NULL || *root == NULL){
        return;
    }    
    destroy(*root);
    *root = NULL;
}
static void destroy(Bin_tree root)
{
    if(root != NULL){
        destroy(root ->left_child);
        destroy(root ->right_child);
        free(root);
    }
}

我们也可以采用非递归来销毁二叉树,采用非递归销毁时,我们需要借助于队列,其代码实现如下:

void destroy_tree_nr(Bin_tree *root)    //二叉树的非递归销毁
{
    Queue *queue = NULL;
    Tree_node *node = NULL; 
    if(root == NULL || *root == NULL){
        return;
    }
    queue = init_queue();
    in(queue,*root);
    while(!is_queue_empty(queue)){
        get_queue_front(queue,(void **)&node);
        out(queue);
        *root = NULL;
        if(node ->left_child){
            in(queue,node ->left_child);
        }
        if(node ->right_child){
            in(queue,node ->right_child);
        }
        free(node);
    }
    destory_queue(&queue);
}

(3)接下来我们讨论关于二叉树的遍历:

      对于二叉树的遍历,我们可以分为两种,第一种采用递归方式进行遍历,第二种则采用非递归的方式进行遍历;我们首先实现递归方式的遍历:


//二叉树的遍历(先序、中序、后序、层序)
void pre_order_print(Bin_tree root)     //先序遍历(递归)
{
    if(root){
        printf("%c ",root->data);
        pre_order_print(root ->left_child);
        pre_order_print(root ->right_child);
    }
}
void mid_order_print(Bin_tree root)     //中序遍历(递归)
{
    if(root){
        mid_order_print(root ->left_child);
        printf("%c ",root->data);
        mid_order_print(root ->right_child);
    }

}
void last_order_print(Bin_tree root)    //后序遍历(递归)
{
    if(root){
        last_order_print(root ->left_child);
        last_order_print(root ->right_child);
        printf("%c ",root->data);
    }

}

递归方式的遍历比较容易理解,接下来我们看非递归方式的遍历,对于非递归的遍历,我们需要借助于栈,首先来看先序遍历的实现:

void pre_order_print_nr(Bin_tree root)     //先序遍历(非递归)
{
    //           A
    //         /   \
    //        B     G
    //       / \   / \
    //      C   D H   J
    //         / \ \
    //        E   F I
    //     先序:ABCDEFGHIJ
    Stack *stack = NULL;
    Tree_node *node = NULL;
    if(root == NULL){
        return;
    }
    stack = init_stack();
    push(stack,root);
    while(!is_stack_empty(stack)){
        get_top(stack,(void **)&node);
        pop(stack);
        printf("%c ",node ->data);
        if(node ->right_child){
            push(stack,node ->right_child);
        }
        if(node ->left_child){
            push(stack,node ->left_child);
        }
    }
    destroy_stack(&stack);
}
中序、后序的非递归遍历代码如下:
void mid_order_print_nr(Bin_tree root)    //中序遍历(非递归)
{
    Stack *stack = NULL;
    Tree_node *node = NULL;
    if(root == NULL){
        return;
    }
    stack = init_stack();
    node = root;
    while(!is_stack_empty(stack) || node != NULL){
        while(node != NULL){
            push(stack,node);
            node = node ->left_child;
        }
        get_top(stack,(void **)&node);
        printf("%c ",node ->data);
        pop(stack);
        node = node ->right_child;
    }
    destroy_stack(&stack);
}
void last_order_print_nr(Bin_tree root)    //后序遍历(非递归)
{
    Stack *stack = NULL;
    Tree_node *node = NULL;
    Tree_node *prev = NULL;
    if(root == NULL){
        return;
    }
    stack = init_stack();
    node = root;
    push(stack,node);
    while(!is_stack_empty(stack)){
        get_top(stack,(void **)&node);
        if((node ->left_child == NULL && node ->right_child == NULL) ||
                            (prev != NULL && (node ->left_child == prev 
                                       || node ->right_child == prev))){
            printf("%c ",node ->data);
            pop(stack);
            prev = node; 
        }else{
            if(node ->left_child){
                push(stack,node ->left_child);
            }
            if(node ->right_child){
                push(stack,node ->right_child);
            }
       }
    }
    destroy_stack(&stack);
}


接下来,我们讨论二叉树的按层遍历:
void level_order_print(Bin_tree root)    //层序遍历
{
    Queue *queue = NULL;
    Tree_node *node = NULL;
    if(root == NULL){
        return;
    }
    queue = init_queue();
    in(queue,root);
    while(!is_queue_empty(queue)){
        get_queue_front(queue,(void **)&node);
        out(queue);
        printf("%c ",node ->data);
        if(node ->left_child){
            in(queue,node ->left_child);
        }
        if(node ->right_child){
            in(queue,node ->right_child);
        }
    }
    destory_queue(&queue);
}
(4)二叉树的性质:

       得到二叉树的高度、叶子节点个数:
   

static int max(int a,int b)
{
    return (a > b) ? a : b;
}
//二叉树的性质(高度、节点个数、叶子节点个数)
int get_binarytree_height(Bin_tree root)    //得到二叉树的高度
{
    if(root == NULL){
        return 0;
    }
    return max(get_binarytree_height(root ->left_child),
               get_binarytree_height(root ->right_child)) + 1;<pre name="code" class="plain">int get_binarytree_leaf_count(Bin_tree root)    //得到二叉树的叶子节点个数
{
    if(root == NULL){
        return 0;
    }else if((!root ->left_child) && (!root ->right_child)){
        return 1;
    }else{
        return get_binarytree_leaf_count(root ->left_child) + 
               get_binarytree_leaf_count(root ->right_child);
    }
}

}

 
 
      得到二叉树节点个数:
  
int get_binarytree_node_count(Bin_tree root)    //得到二叉树的节点个数
{
    if(root == NULL){
        return 0;
    }
    return 1 + get_binarytree_node_count(root ->left_child) +
               get_binarytree_node_count(root ->right_child);
}
     (5)判断二叉树的状态:(两树是否相等、是否是满二叉树、完全二叉树、平衡二叉树)

            判断两树是否相等,其代码如下:

 

Boolean is_binarytree_equal(Bin_tree root1,
                            Bin_tree root2)    //判断两个二叉树是否相等
{
    if(root1 == NULL || root2 == NULL){
        return TRUE;
    }else if(root1 && root2 && root1 ->data == root2 ->data
          && is_binarytree_equal(root1 ->left_child,root2 ->left_child)
          && is_binarytree_equal(root1 ->right_child,root2 ->right_child)){
        return TRUE;
    }else {
        return FALSE;
    }
}
        判断是否是满二叉树,我们可以利用二叉树的性质进行判断,一个高度为h的二叉树,对于满二叉树其节点个数为2 ^ h  - 1
,其代码实现如下:
   
Boolean is_full_binarytree(Bin_tree root)    //是否是满二叉树
{
    int height = 0;
    int node_count = 0;
    if(root == NULL){
        return FALSE;
    }
    height = get_binarytree_height(root);
    node_count = get_binarytree_node_count(root);

    return ((int)pow(2,height) - 1) == node_count;
}

       判断是否是完全二叉树,通过按层遍历,当一个节点的左孩子为NULL,并且该节点的右孩子不为NULL时,则该二叉树一定不是完全二叉树,如果一个节点的左孩子不为NULL时,并且该节点右孩子为空时,那么从该节点以后的节点必须是叶子,其代码的实现如下:

Boolean is_complete_binarytree(Bin_tree root)    //是否是完全二叉树
{
    Boolean find_first = FALSE;
    Queue *queue = NULL;
    Tree_node *node = NULL;
    if(root == NULL){
        return FALSE;
    }
    queue = init_queue();
    in(queue,root);
    while(!is_queue_empty(queue)){
        get_queue_front(queue,(void **)&node);
        out(queue);
        if(find_first == FALSE){
            if(node ->left_child && node ->right_child){
                in(queue,node ->left_child);
                in(queue,node ->right_child);
            }else if(node ->left_child == NULL && node ->right_child){
                return FALSE;
            }else if(node ->left_child && node ->right_child == NULL){
                find_first = TRUE;
                in(queue,node ->left_child);
            }else {
                find_first = TRUE;
            }
        }else{
            if(node ->left_child != NULL || node ->right_child != NULL){
                return FALSE;
            }
        }
    }
    destory_queue(&queue);
    return TRUE;
}

    判断是否为平衡二叉树,可以通过比较左右孩子的二叉树的高度进行判断,其代码实现如下:
   
Boolean is_balance_binarytree(Bin_tree root)    //是否是平衡二叉树
{
    int height_left = 0;
    int height_right = 0;
    Boolean left = FALSE;
    Boolean right = FALSE;
    if(root == NULL){
        return TRUE;
    }
    height_left = get_binarytree_height(root ->left_child);
    height_right = get_binarytree_height(root ->right_child);

    left = is_balance_binarytree(root ->left_child);
    right = is_balance_binarytree(root ->right_child);
   
    return (left && right && abs(height_left - height_right) <= 1) ? TRUE : FALSE;
}

(6)二叉树的其他操作

 
     二叉树的拷贝,代码如下:

Bin_tree copy_binarytree(Bin_tree root)   //二叉树的拷贝
{
    Bin_tree root1 = NULL;
    if(root != NULL){
        root1 = create_tree_node();
        root1 ->data = root ->data;
        root1 ->left_child = copy_binarytree(root ->left_child);
        root1 ->right_child = copy_binarytree(root ->right_child);
    }
    return root1;
}

    找到指定数值的节点:

Tree_node *find_value(Bin_tree root, char value)    //找到指定数值的节点
{
    Tree_node *node = NULL;
    if(root == NULL || root ->data == value){
        return root;
    }
    node = find_value(root ->left_child,value);
    if(node == NULL){
        node = find_value(root ->right_child,value);
    }
    return node;
}
    找到指定节点的双亲节点:
   
Tree_node *find_parent(Bin_tree root, Tree_node *node)    //找到指定节点的双亲节点
{
    Tree_node *p_node = NULL;
    if(root == NULL || root ->left_child == node
                    || root ->right_child == node){
        return root;
    }
    p_node = find_parent(root ->left_child,node);
    if(p_node == NULL){
        p_node = find_parent(root ->right_child,node);
    }
    return p_node;
}

找到两个节点的最近双亲节点:首先处理特殊情况,当一个节点在根节点的左边,并且另一个节点在根节点的右边,或者一个节点在根结点的右边,并且另一个节点在根结点的左边,则根是它们最近的双亲节点;当两个节点存在继承关系时,可以通过得到两个节点的高度,则可以判断出谁继承谁,从而可以找到最近的双亲的节点,当两个节点都在一边,并且没有继承关系时,可以进行递归调用,其代码如下:

static Tree_node *find_common(Bin_tree root,Tree_node *node1,
                                           Tree_node *node2)
{
    if(find_value(root->left_child,node1 ->data)){
        if(find_value(root ->right_child,node2 ->data)){
            return root;
        }else{
            return find_common(root ->left_child,node1,node2);
        }
    }else{
        if(find_value(root ->left_child,node2 ->data)){
            return root;
        }else{
            return find_common(root ->right_child,node1,node2);
        }
    }
}
Tree_node *find_common_parent(Bin_tree root, Tree_node *node1,
                   Tree_node *node2)    //找到两个节点的最近双亲节点
{
    int height1 = 0;
    int height2 = 0;
    if(root == NULL || node1 == NULL || node2 == NULL){
        return NULL;
    }
    height1 = get_binarytree_height(node1);
    height2 = get_binarytree_height(node2);

    if(height1 > height2){
        if(find_value(node1,node2->data)){
            return find_parent(root,node1);
        }
    }else if(height1 < height2){
        if(find_value(node2,node1->data)){
            return find_parent(root,node2);
        }
    
    }else{
        return find_common(root,node1,node2);
    }
}

判断两个二叉树是否包含:

         

static Boolean root1_has_root2(Bin_tree root1,Bin_tree root2)
{
    if(root2 == NULL){
        return TRUE;
    }
    if(root1 == NULL){
        return FALSE;
    }
    if(root1->data != root2 ->data){
        return FALSE;
    }
    return root1_has_root2(root1->left_child,root2 ->left_child)
         && root1_has_root2(root1->right_child,root2->right_child);
}
Boolean is_include_tree(Bin_tree root1,
                        Bin_tree root2)   //判断二叉树是否有包含关系
{
    Boolean ok = FALSE;
    if(root1 != NULL && root2 != NULL){
        if(root1 ->data == root2 ->data){
            ok = root1_has_root2(root1,root2);
        }
        if(ok == FALSE){
            ok = is_include_tree(root1 ->right_child,root2 ->right_child);
        }
        if(ok == FALSE){
            ok = is_include_tree(root1 ->left_child,root2 ->left_child);
        }
    }
    return ok;

测试程序:

      

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

int main(int argc, char **argv)
{
    Bin_tree root = NULL;
    Bin_tree root1 = NULL;
    Bin_tree root2 = NULL;
    Bin_tree root3 = NULL;
    Tree_node *p_node = NULL;
    Tree_node *parent = NULL;
    Tree_node *node1 = NULL;
    Tree_node *node2 = NULL;
    
    char *string = "ABC##DE##F##GH#I##J##";
    char *pre_str = "ABCDEFGHIJ";
    char *mid_str = "CBEDFAHIGJ"; 
    char *last_str = "CEFDBIHJGA"; 
  
    int length = strlen(pre_str);

    root = create_tree(&string);
    #if 1
    printf("pre order:\n");
    pre_order_print(root);
    printf("\n");

    printf("mid order:\n");
    mid_order_print(root);
    printf("\n");

    printf("last order:\n");
    last_order_print(root);
    printf("\n");
    
    printf("level order:\n");
    level_order_print(root);
    printf("\n");
    
    printf("the height of root:%d\n", get_binarytree_height(root));
    printf("the node count of root:%d\n", get_binarytree_node_count(root));

    root1 = create_tree_by_pre_mid(pre_str, mid_str, length);
    printf("root1 level order:\n");
    level_order_print(root1);
    printf("\n");

    root2 = create_tree_by_mid_last(mid_str, last_str, length);
    printf("root2 level order:\n");
    level_order_print(root2);
    printf("\n");
    
    if(is_complete_binarytree(root2)){
        printf("root2 is complate tree!\n");
    }else{
        printf("root2 is not complate tree!\n");
    }

    if(is_balance_binarytree(root2)){
        printf("root2 is balance tree!\n");
    }else{
        printf("root2 not is balance tree!\n");
    }

    root3 = copy_binarytree(root1);
    printf("root3 level order:\n");
    level_order_print(root3);
    printf("\n");

    if(is_binarytree_equal(root2, root3)){ 
        printf("root2 equals root3!\n");
    }

    if((p_node = find_value(root3, 'A'))){
        printf("the value %c was found!\n", p_node->data);
    }else{ 
        printf("the M is not found!\n");
    }
 
    if((parent = find_parent(root3, p_node))){
        printf("%c parent found:%c\n", p_node->data, parent->data);
    }else{
        printf("%c parent not found\n",p_node ->data);


    }
    
    node1 = find_value(root3, 'B');
    node2 = find_value(root3, 'I');

    if((parent = find_common_parent(root3, node1, node2))){
        printf("the common parent of %c and %c is:%c\n",
              node1->data, node2->data, parent->data);
    }else{
        printf("%c and %c has no common parent:\n",node1 ->data,node2 ->data);
    }

    if(is_include_tree(root3, node1)){
        printf("root3 has node1!\n");
    }else{
        printf("root3 has not node1!\n");

    }

    printf("pre order:\n");
    pre_order_print_nr(root);
    printf("\n");
    #endif
    //destroy_tree(&root);
    destroy_tree_nr(&root);
    destroy_tree_nr(&root1);
    destroy_tree_nr(&root2);
    destroy_tree_nr(&root3);
    return 0;
}
 
其测试结果:

   数据结构之二叉树_第3张图片   

至此基本二叉树的操作已经完成,此后还会和大家分享AVL树、b树的一些基本操作,敬请期待!!!!!
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    


   

你可能感兴趣的:(数据结构之二叉树)