/* tree.h--二叉查找树*/
/*树中不允许有重复的项*/
#ifndef _TREE_H_
#define _TREE_H_
#include <stdbool.h>
/*根据具体情况重新定义Item*/
#define SLEN 20
typedef struct item
{
char petname[SLEN];
char petkind[SLEN];
}Item;
#define MAXITEMS 10
typedef struct trnode
{
Item item;
struct trnode *left;//指向左分支的指针
struct trnode *right;//指向右分支的指针
}Trnode;
typedef struct tree
{
Trnode *root;//指向根节点的指针
int size; //树的项数
}Tree;
void InitializeTree(Tree *ptree);
bool TreeIsEmpty(const Tree *ptree);
bool TreeISFull(const Tree *ptree);
int TreeItemCount(const Tree *ptree);
bool AddItem(const Item *pi, Tree *ptree);
bool InTree(const Item *pi, const Tree *ptree);
bool DeleteItem(const Item *pi, Tree *ptree);
void Traverse(const Tree *ptree, void(*pfun)(Item item));
void DeleteAll(Tree *ptree);
#endif // _TREE_H_
/*tree.c --树的支持函数*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "tree.h"
#include <ctype.h>
//局部数据类型
typedef struct pair
{
Trnode *parent;
Trnode *child;
}Pair;
//局部函数的原型
static Trnode* MakeNode(const Item *pi);
static bool ToLeft(const Item *i1, const Item *i2);
static bool ToRight(const Item *i1, const Item *i2);
static void AddNode(Trnode *new_node, Trnode *root);
static void InOrder(const Trnode* root, void(*pfun)(Item item));
static Pair SeekItem(const Item *pi, const Tree *ptree);
static Pair SeekItem(const Item *pi, const Tree *ptree);
static void DeleteNode(Trnode **ptr);
static void DeleteAllNodes(Trnode *ptr);
//函数定义
void InitializeTree(Tree *ptree)
{
ptree->root = NULL;
ptree->size = 0;
}
bool TreeIsEmpty(const Tree *ptree)
{
if(ptree->root == NULL)
{
return true;
}
else
{
return false;
}
}
bool TreeISFull(const Tree *ptree)
{
if(ptree->size == MAXITEMS)
{
return true;
}
else
{
return false;
}
}
int TreeItemCount(const Tree *ptree)
{
return ptree->size;
}
bool AddItem(const Item *pi, Tree *ptree)
{
Trnode *new_node;
if(TreeISFull(ptree))
{
fprintf(stderr, "Tree is full\n");
return false;
}
if(SeekItem(pi, ptree).child != NULL)
{
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 InTree(const Item *pi, const Tree *ptree)
{
return (SeekItem(pi, ptree).child == NULL) ? false : 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);
}
}
void DeleteAll(Tree *ptree)
{
if(ptree != NULL)
{
DeleteAllNodes(ptree->root);
}
ptree->root = NULL;
ptree->size = 0;
}
//局部函数
static void InOrder(const Trnode *root, void(*pfun)(Item item))
{
if(root != NULL)
{
InOrder(root->left, pfun);
(*pfun)(root->item);
InOrder(root->right, pfun);
}
}
static void DeleteAllNodes(Trnode *root)
{
Trnode *pright;
if(root != NULL)
{
pright = root->right;
DeleteAllNodes(root->left);
free(root);
DeleteAllNodes(pright);
}
}
static void AddNode(Trnode *new_node, Trnode *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()");
exit(1);
}
}
static bool ToLeft(const Item *i1, const Item *i2)
{
int comp1;
if((comp1 = strcmp(i1->petname, i2->petname)) < 0)
{
return true;
}
else if(comp1 == 0 && strcmp(i1->petkind, i2->petkind) < 0)
{
return true;
}
else
{
return false;
}
}
static bool ToRight(const Item *i1, const Item *i2)
{
int comp1;
if((comp1 = strcmp(i1->petname, i2->petname)) > 0)
{
return true;
}
else if(comp1 == 0 && strcmp(i1->petkind, i2->petkind) > 0)
{
return true;
}
else
{
return false;
}
}
static Trnode* MakeNode(const Item *pi)
{
Trnode *new_node;
new_node = (Trnode*)malloc(sizeof(Trnode));
if(new_node != NULL)
{
new_node->item = *pi;
new_node->left = NULL;
new_node->right = NULL;
}
return new_node;
}
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)
{
if(ToLeft(pi, &(look.child->item)))
{
look.parent = look.child;
look.child = look.child->left;
}
else if(ToRight(pi, &(look.child->item)))
{
look.parent = look.child;
look.child = look.child->right;
}
else //如果前两种情况都不满足,则必定是相等的情况
{
break;//look.child目标项的节点
}
}
return look;
}
static void DeleteNode(Trnode **ptr)
{
Trnode *temp;
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);
}
}
通过二叉查找树结构实现一个宠物俱乐部的程序:
可以向俱乐部成员花名册添加宠物 显示成员列表 报告成员数量 核实成员并退出
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tree.h"
char menu(void);
void addpet(Tree *pt);
void droppet(Tree *pt);
void showpets(const Tree *pt);
void findpet(const Tree *pt);
void printitem(Item item);
void uppercase(char *str);
char* s_gets(char *st, int n);
int main()
{
Tree pets;
char choice;
InitializeTree(&pets);
while((choice = menu()) != 'q')
{
switch(choice)
{
case 'a':
{
addpet(&pets);
break;
}
case 'l':
{
showpets(&pets);
break;
}
case 'f':
{
findpet(&pets);
break;
}
case 'n':
{
printf("%d pets in club\n", TreeItemCount(&pets));
break;
}
case 'd':
{
droppet(&pets);
break;
}
default:
puts("switching error");
}
}
DeleteAll(&pets);
puts("Bye");
return 0;
}
char menu(void)
{
int ch;
puts("Nerfville Pet Club Membership Program");
puts("Enter the letter corresponding to your choice:");
puts("a) add a pet l) show list of pets");
puts("n) number of pets f) find pets");
puts("d) delete a pet q) quit");
while((ch = getchar()) != EOF)
{
while(getchar() != '\n')//处理输入行的剩余内容
{
continue;
}
ch = tolower(ch);
if(strchr("alfndq", ch) == NULL)
{
puts("please enter an a, l, f, n, d, or q:");
}
else
{
break;
}
}
if(ch == EOF)
{
ch = 'q';
}
return ch;
}
void addpet(Tree *pt)
{
Item temp;
if(TreeISFull(pt))
{
puts("No room in the club!");
}
else
{
puts("Please enter name of pet:");
s_gets(temp.petname, SLEN);
puts("Please enter pet kind:");
s_gets(temp.petkind, SLEN);
uppercase(temp.petname);
uppercase(temp.petkind);
AddItem(&temp, pt);
}
}
void showpets(const Tree *pt)
{
if(TreeIsEmpty(pt))
{
puts("No entries!");
}
else
{
Traverse(pt, printitem);
}
}
void printitem(Item item)
{
printf("Pet: %-19s Kind: %-19s\n", item.petname, item.petkind);
}
void findpet(const Tree *pt)
{
Item temp;
if(TreeIsEmpty(pt))
{
puts("No entries");
return;
}
puts("Please enter name of pet you wish to find:");
s_gets(temp.petname, SLEN);
puts("Please enter kind of pet you wish to find:");
s_gets(temp.petkind, SLEN);
uppercase(temp.petname);
uppercase(temp.petkind);
printf("%s the %s ", temp.petname, temp.petkind);
if(InTree(&temp, pt))
{
printf("is a member.\n");
}
else
{
printf("is not a member.\n");
}
}
void droppet(Tree *pt)
{
Item temp;
if(TreeIsEmpty(pt))
{
puts("No entries");
return;
}
puts("Please enter name of pet you wish to delete:");
s_gets(temp.petname, SLEN);
puts("Please enter kind of pet you wish to delete:");
s_gets(temp.petkind, SLEN);
uppercase(temp.petname);
uppercase(temp.petkind);
printf("%s the %s ", temp.petname, temp.petkind);
if(DeleteItem(&temp, pt))
{
printf("is dropped from the club.\n");
}
else
{
printf("is not a member.\n");
}
}
void uppercase(char *str)
{
while(*str)
{
*str = toupper(*str);
str++;
}
}
char* s_gets(char *st, int n)
{
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if(ret_val)
{
find = strchr(st, '\n');//查找换行符
if(find) //如果地址不是NUNLL,在此处放置一个空字符
{
*find = '\0';
}
else
{
while(getchar() != '\n')
{
continue;//处理输入行的剩余内容
}
}
}
return ret_val;
}
运行结果:
Nerfville Pet Club Membership Program
Enter the letter corresponding to your choice:
a) add a pet l) show list of pets
n) number of pets f) find pets
d) delete a pet q) quit
a
Please enter name of pet:
wanzi
Please enter pet kind:
dog
Nerfville Pet Club Membership Program
Enter the letter corresponding to your choice:
a) add a pet l) show list of pets
n) number of pets f) find pets
d) delete a pet q) quit
kitty
please enter an a, l, f, n, d, or q:
cat
please enter an a, l, f, n, d, or q:
a
Please enter name of pet:
kitty
Please enter pet kind:
cat
Nerfville Pet Club Membership Program
Enter the letter corresponding to your choice:
a) add a pet l) show list of pets
n) number of pets f) find pets
d) delete a pet q) quit
a
Please enter name of pet:
quincy
Please enter pet kind:
pig
Nerfville Pet Club Membership Program
Enter the letter corresponding to your choice:
a) add a pet l) show list of pets
n) number of pets f) find pets
d) delete a pet q) quit
l
Pet: KITTY Kind: CAT
Pet: QUINCY Kind: PIG
Pet: WANZI Kind: DOG
Nerfville Pet Club Membership Program
Enter the letter corresponding to your choice:
a) add a pet l) show list of pets
n) number of pets f) find pets
d) delete a pet q) quit
n
3 pets in club
Nerfville Pet Club Membership Program
Enter the letter corresponding to your choice:
a) add a pet l) show list of pets
n) number of pets f) find pets
d) delete a pet q) quit
q
Bye