今天和大家讨论的是二叉树,在讨论二叉树之前,我们在之前也接触了一维的线性存储结构,比如数组,双端链表,以及对双端的链表的封装形成栈和队列,之后又将数组和双端链表的结合形成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##
则其对应的二叉树如下图所示:
二叉树图
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;
}使用遍历结果创建二叉树:我们都知道二叉树的遍历包括先序遍历、中序遍历、后序遍历。先序遍历的访问顺序为访根、访左、访右。中序遍历的访问顺序:访左、访根、访右。后序遍历的访问顺序为:访左、访右、访根。如果我们知道先序和后序,则可以唯一确定一颗二叉树。
先序: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;
}
其测试结果:
至此基本二叉树的操作已经完成,此后还会和大家分享AVL树、b树的一些基本操作,敬请期待!!!!!

421

被折叠的 条评论
为什么被折叠?



