(1)bitree.h
/*****************************************************************************
* *
* ------------------------------- bitree.h ------------------------------- *
* *
*****************************************************************************/
#ifndef BITREE_H
#define BITREE_H
#include <stdlib.h>
#include <string.h>
#include "bitree.h"
/*****************************************************************************
* *
* Define a structure for binary tree nodes. *
* *
*****************************************************************************/
typedef struct BiTreeNode_ {
void *data; // 非明确数据类型,保存的是数据的地址
struct BiTreeNode_ *left; // 左孩子
struct BiTreeNode_ *right; // 右孩子
} BiTreeNode;
/*****************************************************************************
* *
* Define a structure for binary trees. *
* *
*****************************************************************************/
typedef struct BiTree_ {
int size; // 结点大小
int (*compare)(const void *key1, const void *key2);
void (*destroy)(void *data);
BiTreeNode *root; // 根结点指针
} BiTree;
/*****************************************************************************
* *
* --------------------------- Public Interface --------------------------- *
* *
*****************************************************************************/
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)
/*****************************************************************************
* *
* ------------------------------- bitree.c ------------------------------- *
* *
*****************************************************************************/
/*****************************************************************************
* *
* ------------------------------ bitree_init ----------------------------- *
* *
*****************************************************************************/
void bitree_init(BiTree *tree, void (*destroy)(void *data)) {
/*****************************************************************************
* *
* Initialize the binary tree. *
* *
*****************************************************************************/
tree->size = 0;
tree->destroy = destroy;
tree->root = NULL;
return;
}
/*****************************************************************************
* *
* ---------------------------- bitree_destroy ---------------------------- *
* *
*****************************************************************************/
void bitree_destroy(BiTree *tree) {
/*****************************************************************************
* *
* Remove all the nodes from the tree. *
* *
*****************************************************************************/
bitree_rem_left(tree, NULL);
/*****************************************************************************
* *
* No operations are allowed now, but clear the structure as a precaution. *
* *
*****************************************************************************/
memset(tree, 0, sizeof(BiTree));
return;
}
/*****************************************************************************
* *
* ---------------------------- bitree_ins_left --------------------------- *
* *
*****************************************************************************/
int bitree_ins_left(BiTree *tree, BiTreeNode *node, const void *data) {
// 插入该结点的左孩子位置
BiTreeNode *new_node,
**position;
/*****************************************************************************
* *
* Determine where to insert the node. *
* *
*****************************************************************************/
if (node == NULL) { // 这个表示的是该结点是否为空
/**************************************************************************
* *
* Allow insertion at the root only in an empty tree. *
* *
**************************************************************************/
if (bitree_size(tree) > 0) // 空才可以插入根结点的位置
return -1;
position = &tree->root;
}
else {
/**************************************************************************
* *
* Normally allow insertion only at the end of a branch. *
* *
**************************************************************************/
if (bitree_left(node) != NULL) // 该结点左孩子不为空 插入失败
return -1;
position = &node->left;
}
/*****************************************************************************
* *
* Allocate storage for the node. *
* *
*****************************************************************************/
// 为新结点分配内存
if ((new_node = (BiTreeNode *)malloc(sizeof(BiTreeNode))) == NULL)
return -1;
/*****************************************************************************
* *
* Insert the node into the tree. *
* *
*****************************************************************************/
new_node->data = (void *)data;
new_node->left = NULL;
new_node->right = NULL;
*position = new_node; // position为双指针,可确保插入的结点位于正确的位置
/*****************************************************************************
* *
* Adjust the size of the tree to account for the inserted node. *
* *
*****************************************************************************/
tree->size++; // 数量加一
return 0;
}
/*****************************************************************************
* *
* --------------------------- bitree_ins_right --------------------------- *
* *
*****************************************************************************/
int bitree_ins_right(BiTree *tree, BiTreeNode *node, const void *data) {
// 插入该结点的右孩子位置
BiTreeNode *new_node,
**position;
/*****************************************************************************
* *
* Determine where to insert the node. *
* *
*****************************************************************************/
if (node == NULL) { // 这个表示的是该结点是否为空
/**************************************************************************
* *
* Allow insertion at the root only in an empty tree. *
* *
**************************************************************************/
if (bitree_size(tree) > 0) // 空才可以插入根结点的位置
return -1;
position = &tree->root;
}
else {
/**************************************************************************
* *
* Normally allow insertion only at the end of a branch. *
* *
**************************************************************************/
if (bitree_right(node) != NULL) // 该结点左孩子不为空 插入失败
return -1;
position = &node->right;
}
/*****************************************************************************
* *
* Allocate storage for the node. *
* *
*****************************************************************************/
if ((new_node = (BiTreeNode *)malloc(sizeof(BiTreeNode))) == NULL)
return -1;
/*****************************************************************************
* *
* Insert the node into the tree. *
* *
*****************************************************************************/
new_node->data = (void *)data;
new_node->left = NULL;
new_node->right = NULL;
*position = new_node; // position为双指针,可确保插入的结点位于正确的位置
/*****************************************************************************
* *
* Adjust the size of the tree to account for the inserted node. *
* *
*****************************************************************************/
tree->size++; // 结点数加一
return 0;
}
/*****************************************************************************
* *
* ---------------------------- bitree_rem_left --------------------------- *
* *
*****************************************************************************/
void bitree_rem_left(BiTree *tree, BiTreeNode *node) {
// 删除node结点的左子树
BiTreeNode **position;
/*****************************************************************************
* *
* Do not allow removal from an empty tree. *
* *
*****************************************************************************/
if (bitree_size(tree) == 0) // 空树无需删除
return;
/*****************************************************************************
* *
* Determine where to remove nodes. *
* *
*****************************************************************************/
if (node == NULL) // 删除整棵子树
position = &tree->root;
else
position = &node->left; // 左子树的根结点
/*****************************************************************************
* *
* Remove the nodes. *
* *
*****************************************************************************/
if (*position != NULL) { // 递归删除
bitree_rem_left(tree, *position);
bitree_rem_right(tree, *position);
if (tree->destroy != NULL) {
/***********************************************************************
* *
* Call a user-defined function to free dynamically allocated data. *
* *
***********************************************************************/
tree->destroy((*position)->data);
}
free(*position);
*position = NULL;
/**************************************************************************
* *
* Adjust the size of the tree to account for the removed node. *
* *
**************************************************************************/
tree->size--;
}
return;
}
/*****************************************************************************
* *
* --------------------------- bitree_rem_right --------------------------- *
* *
*****************************************************************************/
void bitree_rem_right(BiTree *tree, BiTreeNode *node) {
// 删除node结点的右子树
BiTreeNode **position;
/*****************************************************************************
* *
* Do not allow removal from an empty tree. *
* *
*****************************************************************************/
if (bitree_size(tree) == 0) // 空树无需删除
return;
/*****************************************************************************
* *
* Determine where to remove nodes. *
* *
*****************************************************************************/
if (node == NULL) // 删除整棵子树
position = &tree->root;
else
position = &node->right; // 右子树的根结点
/*****************************************************************************
* *
* Remove the nodes. *
* *
*****************************************************************************/
if (*position != NULL) { // 递归删除
bitree_rem_left(tree, *position);
bitree_rem_right(tree, *position);
if (tree->destroy != NULL) {
/***********************************************************************
* *
* Call a user-defined function to free dynamically allocated data. *
* *
***********************************************************************/
tree->destroy((*position)->data);
}
free(*position);
*position = NULL;
/**************************************************************************
* *
* Adjust the size of the tree to account for the removed node. *
* *
**************************************************************************/
tree->size--;
}
return;
}
/*****************************************************************************
* *
* ----------------------------- bitree_merge ----------------------------- *
* *
*****************************************************************************/
int bitree_merge(BiTree *merge, BiTree *left, BiTree *right, const void
*data) {
// 合并二叉树,merge为根结点,left,right分别表示左右子树的根结点
/*****************************************************************************
* *
* Initialize the merged tree. *
* *
*****************************************************************************/
bitree_init(merge, left->destroy);
/*****************************************************************************
* *
* Insert the data for the root node of the merged tree. *
* *
*****************************************************************************/
if (bitree_ins_left(merge, NULL, data) != 0) {
bitree_destroy(merge);
return -1;
}
/*****************************************************************************
* *
* Merge the two binary trees into a single binary tree. *
* *
*****************************************************************************/
bitree_root(merge)->left = bitree_root(left);
bitree_root(merge)->right = bitree_root(right);
/*****************************************************************************
* *
* Adjust the size of the new binary tree. *
* *
*****************************************************************************/
merge->size = merge->size + bitree_size(left) + bitree_size(right); // 合并大小
/*****************************************************************************
* *
* Do not let the original trees access the merged nodes. *
* *
*****************************************************************************/
// 合并后的树 只能通过merge中的根结点访问
left->root = NULL;
left->size = 0;
right->root = NULL;
right->size = 0;
return 0;
}
#endif
(2)ex-1.c
/*****************************************************************************
* *
* ex-1.c *
* ====== *
* *
* Description: Illustrates using a binary tree (see Chapter 9). *
* *
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "bitree.h"
#include "traverse.h"
/*****************************************************************************
* *
* ---------------------------- print_preorder ---------------------------- *
* *
*****************************************************************************/
static void print_preorder(const BiTreeNode *node) {
/*****************************************************************************
* *
* Display the binary tree rooted at the specified node in preorder. *
* *
*****************************************************************************/
if (!bitree_is_eob(node)) {
fprintf(stdout, "Node=%03d\n", *(int *)bitree_data(node));
if (!bitree_is_eob(bitree_left(node)))
print_preorder(bitree_left(node));
if (!bitree_is_eob(bitree_right(node)))
print_preorder(bitree_right(node));
}
return;
}
/*****************************************************************************
* *
* ----------------------------- print_inorder ---------------------------- *
* *
*****************************************************************************/
static void print_inorder(const BiTreeNode *node) {
/*****************************************************************************
* *
* Display the binary tree rooted at the specified node in inorder. *
* *
*****************************************************************************/
if (!bitree_is_eob(node)) {
if (!bitree_is_eob(bitree_left(node)))
print_inorder(bitree_left(node));
fprintf(stdout, "Node=%03d\n", *(int *)bitree_data(node));
if (!bitree_is_eob(bitree_right(node)))
print_inorder(bitree_right(node));
}
return;
}
/*****************************************************************************
* *
* ---------------------------- print_postorder --------------------------- *
* *
*****************************************************************************/
static void print_postorder(const BiTreeNode *node) {
/*****************************************************************************
* *
* Display the binary tree rooted at the specified node in postorder. *
* *
*****************************************************************************/
if (!bitree_is_eob(node)) {
if (!bitree_is_eob(bitree_left(node)))
print_postorder(bitree_left(node));
if (!bitree_is_eob(bitree_right(node)))
print_postorder(bitree_right(node));
fprintf(stdout, "Node=%03d\n", *(int *)bitree_data(node));
}
return;
}
/*****************************************************************************
* *
* ------------------------------ insert_int ------------------------------ *
* *
*****************************************************************************/
static int insert_int(BiTree *tree, int i) {
BiTreeNode *node,
*prev;
int direction,
*data;
/*****************************************************************************
* *
* Insert i assuming a binary tree organized as a binary search tree. *
* *
*****************************************************************************/
node = tree->root;
direction = 0;
while (!bitree_is_eob(node)) {
prev = node;
if (i == *(int *)bitree_data(node)) {
return -1;
}
else if (i < *(int *)bitree_data(node)) {
node = bitree_left(node);
direction = 1;
}
else {
node = bitree_right(node);
direction = 2;
}
}
if ((data = (int *)malloc(sizeof(int))) == NULL)
return -1;
*data = i;
if (direction == 0)
return bitree_ins_left(tree, NULL, data);
if (direction == 1)
return bitree_ins_left(tree, prev, data);
if (direction == 2)
return bitree_ins_right(tree, prev, data);
return -1;
}
/*****************************************************************************
* *
* ------------------------------ search_int ------------------------------ *
* *
*****************************************************************************/
static BiTreeNode *search_int(BiTree *tree, int i) {
BiTreeNode *node;
/*****************************************************************************
* *
* Look up i assuming a binary tree organized as a binary search tree. *
* *
*****************************************************************************/
node = bitree_root(tree);
while (!bitree_is_eob(node)) {
if (i == *(int *)bitree_data(node)) {
return node;
}
else if (i < *(int *)bitree_data(node)) {
node = bitree_left(node);
}
else {
node = bitree_right(node);
}
}
return NULL;
}
/*****************************************************************************
* *
* --------------------------------- main --------------------------------- *
* *
*****************************************************************************/
int main(int argc, char **argv) {
BiTree tree;
BiTreeNode *node;
int i;
/*****************************************************************************
* *
* Initialize the binary tree. *
* *
*****************************************************************************/
bitree_init(&tree, free);
/*****************************************************************************
* *
* Perform some binary tree operations. *
* *
*****************************************************************************/
fprintf(stdout, "Inserting some nodes\n");
if (insert_int(&tree, 20) != 0)
return 1;
if (insert_int(&tree, 10) != 0)
return 1;
if (insert_int(&tree, 30) != 0)
return 1;
if (insert_int(&tree, 15) != 0)
return 1;
if (insert_int(&tree, 25) != 0)
return 1;
if (insert_int(&tree, 70) != 0)
return 1;
if (insert_int(&tree, 80) != 0)
return 1;
if (insert_int(&tree, 23) != 0)
return 1;
if (insert_int(&tree, 26) != 0)
return 1;
if (insert_int(&tree, 5) != 0)
return 1;
fprintf(stdout, "Tree size is %d\n", bitree_size(&tree));
fprintf(stdout, "(Preorder traversal)\n");
print_preorder(bitree_root(&tree));
i = 30;
if ((node = search_int(&tree, i)) == NULL) {
fprintf(stdout, "Could not find %03d\n", i);
}
else {
fprintf(stdout, "Found %03d...Removing the left tree below it\n", i);
bitree_rem_left(&tree, node);
fprintf(stdout, "Tree size is %d\n", bitree_size(&tree));
fprintf(stdout, "(Preorder traversal)\n");
print_preorder(bitree_root(&tree));
}
i = 99;
if ((node = search_int(&tree, i)) == NULL) {
fprintf(stdout, "Could not find %03d\n", i);
}
else {
fprintf(stdout, "Found %03d...Removing the right tree below it\n", i);
bitree_rem_right(&tree, node);
fprintf(stdout, "Tree size is %d\n", bitree_size(&tree));
fprintf(stdout, "(Preorder traversal)\n");
print_preorder(bitree_root(&tree));
}
i = 20;
if ((node = search_int(&tree, i)) == NULL) {
fprintf(stdout, "Could not find %03d\n", i);
}
else {
fprintf(stdout, "Found %03d...Removing the right tree below it\n", i);
bitree_rem_right(&tree, node);
fprintf(stdout, "Tree size is %d\n", bitree_size(&tree));
fprintf(stdout, "(Preorder traversal)\n");
print_preorder(bitree_root(&tree));
}
i = bitree_is_leaf(bitree_root(&tree));
fprintf(stdout, "Testing bitree_is_leaf...Value=%d (0=OK)\n", i);
i = bitree_is_leaf(bitree_left((bitree_root(&tree))));
fprintf(stdout, "Testing bitree_is_leaf...Value=%d (0=OK)\n", i);
i = bitree_is_leaf(bitree_left(bitree_left((bitree_root(&tree)))));
fprintf(stdout, "Testing bitree_is_leaf...Value=%d (1=OK)\n", i);
i = bitree_is_leaf(bitree_right(bitree_left((bitree_root(&tree)))));
fprintf(stdout, "Testing bitree_is_leaf...Value=%d (1=OK)\n", i);
fprintf(stdout, "Inserting some nodes\n");
if (insert_int(&tree, 55) != 0)
return 1;
if (insert_int(&tree, 44) != 0)
return 1;
if (insert_int(&tree, 77) != 0)
return 1;
if (insert_int(&tree, 11) != 0)
return 1;
fprintf(stdout, "Tree size is %d\n", bitree_size(&tree));
fprintf(stdout, "(Preorder traversal)\n");
print_preorder(bitree_root(&tree));
fprintf(stdout, "(Inorder traversal)\n");
print_inorder(bitree_root(&tree));
fprintf(stdout, "(Postorder traversal)\n");
print_postorder(bitree_root(&tree));
/*****************************************************************************
* *
* Destroy the binary tree. *
* *
*****************************************************************************/
fprintf(stdout, "Destroying the tree\n");
bitree_destroy(&tree);
return 0;
}