这两个文件配合下面这篇文章使用
图解二叉排序树的实现 (超详细)
.h头文件
/* 二叉排序树 */
/* 树中不允许有重复的项 */
#ifndef _TREE_H_
#define _TREE_H_
#include<stdbool.h>
#define SLEN 20
typedef struct item{
char petName[SLEN];
char petKind[SLEN];
} Item;
typedef struct node{
Item item;
struct node * left;
struct node * right;
} Node;
typedef struct tree{
Node * root; //根节点
int size; //树的项数
} Tree;
/*函数原型*/
/*操作: 把树初始化为空*/
/*前提条件: ptree指向一个树*/
/*后置条件: 树被初始化为空*/
void InitializeTree(Tree * ptree);
/*操作: 删除树中的所有内容*/
/*前提条件: ptree指向一个已初始化的树*/
/*后置条件: 树为空*/
void DeleteTree(Tree * ptree);
/*操作: 确定树是否为空*/
/*前提条件: ptree指向一个树*/
/*后置条件: 如果树为空,该函数返回true*/
/* 否则,返回false*/
bool TreeIsEmpty(const Tree *ptree);
/*操作: 确定数的项数*/
/*前提条件: ptree指向一个树*/
/*后置条件: 返回树的项数*/
int TreeItemCount(const Tree *ptree);
/*操作: 在树中查找一个项*/
/*前提条件: pi指向一个项*/
/* ptree指向一个已初始化的树*/
/*后置条件: 如果在树中找到指定项,该函数返回true*/
/* 否则,返回false*/
bool InTree(const Item *pi, const Tree *ptree);
/*操作: 在树中添加一个项*/
/*前提条件: pi是待添加项的地址*/
/* ptree指向一个已初始化的树*/
/*后置条件: 如果可以添加,该函数将在树中添加一个项*/
/* 并返回true;否则,返回false*/
bool AddItem(const Item *pi, Tree * ptree);
/*操作: 从树中删除一个项*/
/*前提条件: pi是删除项的地址*/
/* ptree指向一个已初始化的树*/
/*后置条件: 如果从树中成功删除一个项,该函数返回true*/
bool DeleteItem(const Item *pi, Tree * ptree);
/*操作: 把函数应用于树中的每一项*/
/*前提条件: ptree指向一个树*/
/* pfun指向一个函数,*/
/* 该函数接受一个Item类型的参数,并无返回值*
/*后置条件: pfun指向的这个函数为树中的每一项执行一次*/
void Traverse(const Tree *ptree, void (*pfun)(Item item));
#endif
.c类型实现文件
/* Tree类型实现 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#include "tree.h"
/* 局部数据类型 */
typedef struct pair{
Node * parent;
Node * child;
} Pair;
/* 局部函数原型 */
static Node * MakeNode(const Item *pi);
/*
static bool Toleft(const Item *pi1, const Item *pi2);
static bool ToRight(const Item *pi1, const Item *pi2);
*/
//用下面的Compare函数来代替
static int Compare(const Item *pi1, const Item *pi2);
static void AddNode(Node * new_node, Node * root);
static void InOrder(const Node *root, void(*pfun)(Item item));
static Pair SeekItem(const Item *pi, const Tree *ptree);
static void DeleteNode(Node **ptr);
static void DeleteAllNodes(Node * ptr);
void InitializeTree(Tree * ptree){
ptree->root = NULL;
ptree->size = 0;
}
void DeleteTree(Tree * ptree){
if (ptree->root != NULL)
DeleteAllNodes(ptree->root);
ptree->root = NULL;
ptree->size = 0;
}
bool TreeIsEmpty(const Tree *ptree){
return ptree->root == NULL;
}
int TreeItemCount(const Tree *ptree){
return ptree->size;
}
bool InTree(const Item *pi, const Tree *ptree){
return (SeekItem(pi, ptree).child == NULL) ? false : true;
}
bool AddItem(const Item *pi, Tree * ptree){
Node * new_node;
if (InTree(pi, ptree)){
fprintf(stderr, "Attempted to add duplicate item\n");
return false; //提前返回
}
new_node = MakeNode(pi); //指向新节点
if (new_node == NULL){
fprintf(stderr, "Couldn`t create node\n");
return false; //提前返回
}
/* 成功创建一个新节点 */
ptree->size++;
if (ptree->root == NULL) //情况1:树为空
ptree->root = new_node; //新节点为树的根节点
else //情况2:树不为空
AddNode(new_node, ptree->root); //在树中添加新节点
return true; //成功返回
}
bool DeleteItem(const Item *pi, Tree * ptree){
Pair look;
look = SeekItem(pi, ptree);
if (look.child == NULL)
return false; //没有匹配到节点
if (look.parent == NULL) //删除根节点项
DeleteNode(&(ptree->root));
else if (look.parent->left == look.child)
DeleteNode(&(look.parent->left));
else
DeleteNode(&(look.parent->right));
ptree->size--;
return true;
}
void Traverse(const Tree *ptree, void (*pfun)(Item item)){
if (ptree != NULL)
InOrder(ptree->root, pfun);
}
/* 局部函数 */
static Node * MakeNode(const Item *pi){
Node * new_node;
new_node = (Node *) malloc(sizeof(Node));
if (new_node != NULL){
new_node->item = *pi;
new_node->left = new_node->right = NULL;
}
return new_node;
}
/*
static bool Toleft(const Item *pi1, const Item *pi2){
int comp1;
if ((comp1 = strcmp(pi1->petName, pi2->petName)) < 0)
return true;
else if ((comp1 == 0 && strcmp(pi1->petKind, pi2->petKind)) < 0)
return true;
else
return false;
}
static bool ToRight(const Item *pi1, const Item *pi2){
int comp1;
if ((comp1 = strcmp(pi1->petName, pi2->petName)) > 0)
return true;
else if ((comp1 == 0 && strcmp(pi1->petKind, pi2->petKind)) > 0)
return true;
else
return false;
}
*/
static int Compare(const Item *pi1, const Item *pi2){ //用一个函数来解决
int comp1;
if ((comp1 = strcmp(pi1->petName, pi2->petName)) != 0)
return comp1;
else
return strcmp(pi1->petKind, pi2->petKind);
}
static void AddNode(Node * new_node, Node * root){
/* 递归版 */
/*
if (Toleft(&new_node->item, &root->item)){
if (root->left == NULL) //空子树
root->left = new_node; //把节点添加到此处
else
AddNode(new_node, root->left); //否则处理该子树
}
else if (ToRight(&new_node->item, &root->item)){
if (root->right == NULL)
root->right = new_node;
else
AddNode(new_node, root->right);
}
else{ //不允许有重复项
fprintf(stderr, "location error in AddNote()\n");
exit(1);
}
*/
/* 循环版 */
Node * root_ = root;
while (true){
int cmp_result = Compare(&new_node->item, &root_->item);
if (cmp_result < 0){
if (root_->left == NULL){ //空子树
root_->left = new_node; //把节点添加到此处
break;
}
else
root_ = root_->left;
}
else if (cmp_result > 0){
if (root_->right == NULL){
root_->right = new_node;
break;
}
else
root_ = root_->right;
}
}
}
static void InOrder(const Node *root, void(*pfun)(Item item)){ //中序遍历
if (root != NULL){
InOrder(root->left, pfun);
(*pfun)(root->item);
InOrder(root->right, pfun);
}
}
static Pair SeekItem(const Item *pi, const Tree *ptree){
Pair look;
look.parent = NULL;
look.child = ptree->root;
if (look.child == NULL)
return look; //提前返回
while (look.child != NULL){ //也可以用递归
int cmp_result = Compare(pi, &(look.child->item));
if (cmp_result < 0){
look.parent = look.child;
look.child = look.child->left;
}
else if (cmp_result > 0){
look.parent = look.child;
look.child = look.child->right;
}
else //如果前两种情况都不满足,则必定相等
break; //look.child 目标项的节点
}
return look; //成功返回
}
static void DeleteNode(Node **ptr){
/* ptr 是指向目标节点的父节点指针成员(letf/right)的地址 */
Node * temp;
if ((*ptr)->left == NULL && (*ptr)->right == NULL){ //要释放的节点是叶子节点
free(*ptr);
}
else if ((*ptr)->left == NULL){
temp = *ptr;
*ptr = (*ptr)->right;
free(temp);
}
else if ((*ptr)->right == NULL){
temp = *ptr;
*ptr = (*ptr)->left;
free(temp);
}
else{ //被删除的节点有两个子节点
/* 找到重新连接右子树的位置 */
for (temp = (*ptr)->left; temp->right != NULL; temp = temp->right)
continue;
temp->right = (*ptr)->right;
temp = *ptr;
*ptr = (*ptr)->left;
free(temp);
}
}
/*
static void DeleteAllNodes(Node * ptr){
Node * pright;
if (ptr != NULL){
pright = ptr->right;
DeleteAllNodes(ptr->left);
free(ptr);
DeleteAllNodes(pright);
}
}
*/
/* 修改过后的 */
static void DeleteAllNodes(Node * ptr){
if (ptr != NULL){
DeleteAllNodes(ptr->left);
DeleteAllNodes(ptr->right);
free(ptr);
}
}