# 二叉樹的實現與分析(源碼及解析)

/*bitree.h*/
#ifndef BITREE_H
#define BITREE_H
#include <stdlib.h>

/*定義二叉樹結點結構體*/
typedef struct BiTreeNode_
{
void *data;
struct BiTreeNode_ *left;
struct BiTreeNode_ *right;
}BiTreeNode;

/*定義二叉樹結構體*/
typedef struct BiTree_
{
int size;
int (*compare)(const void *key1,const void *key2);
void (*destroy)(void *data);
BiTreeNode *root;
}BiTree;

/*公用介面部分*/
void bitree_init(BiTree *tree,void (*destroy)(void *data));
void bitree_destroy(BiTree *tree);
int bitree_ins_left(BiTree *tree,BiTreeNode *node,const void *data);
int bitree_ins_right(BiTree *tree,BiTreeNode *node,const void *data);
void bitree_rem_left(BiTree *tree,BiTreeNode *node);
void bitree_rem_right(BiTree *tree,BiTreeNode *node);
int bitree_merge(BiTree *merge,BiTree *left,BiTree *right,const void *data);

#define bitree_size(tree)((tree)->size)
#define bitree_root(tree)((tree)->root)
#define bitree_is_eob(node)((node) == NULL)
#define bitree_is_leaf(node)((node)->left == NULL && (node)->right == NULL)
#define bitree_data(node)((node)->data)
#define bitree_left(node)((node)->left)
#define bitree_right(node)((node)->right)

#endif // BITREE_H

#include <stdlib.h>
#include <string.h>
#include "bitree.h"

/*bitree_init  初始化二叉樹*/
void bitree_init(BiTree *tree,void (*destroy)(void *data))
{
tree->size = 0;
tree->destroy = destroy;
tree->root = NULL;

return ;
}

/*bitree_destroy  銷毀二叉樹*/
void bitree_destroy(BiTree *tree)
{
/*移除樹中的所有結點*/
bitree_rem_left(tree,NULL);
/*不再允許其他動作，清除樹結構*/
memset(tree,0,sizeof(BiTree));
return ;
}

/*bitree_ins_left  插入左子結點*/
int bitree_ins_left(BiTree *tree,BiTreeNode *node,const void *data)
{
BiTreeNode *new_node,**position;

/*決定在何處插入結點*/
if(node == NULL)
{
/*允許只在空樹中插入根結點*/
if(bitree_size(tree)>0)
return -1;

position = &tree->root;
}
else
{
/*通常只允許在一個分支的末端進行插入*/
if(bitree_left(node) != NULL)
return -1;

position = &node->left;
}
/*為結點分配空間*/
if((new_node = (BiTreeNode*)malloc(sizeof(BiTreeNode)))==NULL)
return -1;

new_node->data = (void*)data;
new_node->left = NULL;
new_node->right = NULL;
*position = new_node;

tree->size++;

return 0;
}

/*bitree_ins_right  插入右結點*/
int bitree_ins_right(BiTree *tree,BiTreeNode *node,void *data)
{
BiTreeNode *new_node, **position;
/*決定將結點插入哪一位置*/
if(node == NULL)
{
/*僅允許在空樹中插入根結點*/
if(bitree_size(tree)>0)
return -1;

position = &tree->root;
}
else
{
/*通常只允許在一個分支的末端進入插入*/
if(bitree_right(node)!=NULL)
return -1;

position = &node->right;
}

/*為結點分配空間*/
if((new_node = (BiTreeNode*)malloc(sizeof(BiTreeNode)))==NULL)
return -1;

/*將結點插入樹中*/
new_node->data = (void*)data;
new_node->left = NULL;
new_node->right = NULL;
*position = new_node;

tree->size++;
return 0;
}

/*bitree_rem_left  移除以指定結點的左子結點為根的子樹*/
void bitree_rem_left(BiTree *tree,BiTreeNode *node)
{
BiTreeNode **position;

/*從一顆空樹中移除節點是不被允許的*/
if(bitree_size == 0)
return;

/*決定從何處移除分支*/
if(node == NULL)
position = &tree->root;
else
position = &node->left;

/*按後序遍曆的順序移除分支*/
if(*position != NULL)
{
bitree_rem_left(tree,*position);
bitree_rem_right(tree,*position);

if(tree->destroy != NULL)
{
/*調用自訂的解構函式釋放動態空間*/
tree->destroy((*position)->data);
}

free(*position);
*position = NULL;

tree->size--;
}
return;
}

/*bitree_rem_left  移除以指定結點的右子結點為根的子樹*/
void betree_rem_right(BiTree *tree,BiTreeNode *node)
{
BiTreeNode **position;

if(bitree_size(tree) == 0)
return ;

if(node == NULL)
position = &tree->root;
else
position = &node->right;

if(position != NULL)
{
bitree_rem_left(tree,*position);
bitree_rem_right(tree,*position);

if(tree->destroy != NULL)
{
tree->destroy((*position)->data);
}

free(*position);
*position = NULL;

tree->size--;
}
return ;
}

/*bitree_merge  將兩顆二叉樹合并為單顆二叉樹*/
int bitree_merge(BiTree *merge, BiTree *left, BiTree *right, const void *data)
{
/*初始化合并樹*/
bitree_init(merge,left->destroy);

/*將傳入的data插入到新樹的根結點中*/
if(bitree_ins_left(merge,NULL,data) != 0)
{
bitree_destroy(merge);
return -1;
}

/*合并後的樹的左右子結點，分別設定為left和right的根結點*/
bitree_root(merge)->left = bitree_root(left);
bitree_root(merge)->right = bitree_root(right);

/*調整合并後的樹的結點的數量為本身的數量與左右兩顆樹的結點數量之和*/
merge->size = merge->size + bitree->size(left) + bitree_size(right);

/*解除原來樹中的結點關係，並分別將size設定為0*/
left->root = NULL;
left->size = 0;
right->root = NULL;
right->size = 0;

return 0;
}

Tags Index: