1、结构体的定义
typedef struct item
{
char petname[SLEN];
char petkind[SLEN];
} Item;
typedef struct trnode
{
Item item;
struct trnode* left;
struct trnode* right;
} Trnode;
typedef struct tree
{
Trnode* root;
int size;
} Tree;
2、函数的接口:tree.h
#ifndef _TREE_H_
#define _TREE_H_
#include <stdbool.h>
/* 根据具体情况重新定义Item */
#define SLEN 20
#define MAXITEMS 10
typedef struct item
{
char petname[SLEN];
char petkind[SLEN];
} Item;
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 TreeIremCount(const Tree* ptree);
/* 在树中添加一个项 */
bool AddItem(const Item* ip, 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
3、函数的定义:tree.cpp
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "tree.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);
/*被AddItem调用添加项 */
static void AddNode(Trnode* new_node, Trnode* root);
/*被Traverse调用,遍历数*/
static void InOrder(const Trnode* root, void(*pfun)(Item item));
/*寻找项 */
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 TreeIremCount(const Tree* ptree)
{
return ptree->size;
}
bool AddItem(const Item* pi, Tree* ptree)
{
Trnode* new_node;
if (TreeIsFull(ptree))
{
fprintf(stderr, "树以满!\n");
return false;
}
if (SeekItem(pi, ptree).child != NULL)
{
fprintf(stderr, "添加重复项目!\n");
return false;
}
new_node = MakeNode(pi); //指向新节点
if (new_node == NULL)
{
fprintf(stderr, "不能创建节点!\n");
return false;
}
ptree->size++;
if (ptree->root == NULL)
ptree->root = new_node;
else
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 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 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 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, "没有添加节点的位置!");
exit(1);
}
}
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 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;
}
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);
}
}
static void DeleteAllNodes(Trnode* root)
{
Trnode* pright;
if (root != NULL)
{
pright = root->right;
DeleteAllNodes(root->left);
free(root);
DeleteAllNodes(pright);
}
}
4、运行程序:use.cpp
#include <stdio.h>
#include <string.h>
#include <ctype.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(void)
{
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", TreeIremCount(&pets));
break;
case 'd': droppet(&pets);
break;
default: puts("输入错误!");
}
}
DeleteAll(&pets);
puts("退出!");
return 0;
}
char menu(void)
{
int ch;
puts("输入选择:");
puts("a: 添加宠物 l: 罗列所以宠物");
puts("n: 宠物数量 f: 寻找宠物");
puts("d: 删除宠物 q: 退出");
while ((ch = getchar()) != EOF)
{
while (getchar() != '\n')
continue;
ch = tolower(ch);
if (strchr("alrfndq", ch) == NULL)
puts("输入:a, l, f, n, d, q");
else
break;
}
if (ch == EOF)
ch = 'q';
return ch;
}
void addpet(Tree* pt)
{
Item temp{};
if (TreeIsFull(pt))
puts("无成员!");
else
{
puts("输入宠物名字:");
s_gets(temp.petname, SLEN);
puts("输入宠物种类:");
s_gets(temp.petkind, SLEN);
uppercase(temp.petname);
uppercase(temp.petkind);
AddItem(&temp, pt);
}
}
void droppet(Tree* pt)
{
Item temp;
if (TreeIsEmpty(pt))
{
puts("无成员!");
return;
}
puts("输入删除的名称:");
s_gets(temp.petname, SLEN);
puts("输入删除的种类:");
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 dorpped from the club.\n");
else
printf("is not a number.\n");
}
void showpets(const Tree* pt)
{
if (TreeIsEmpty(pt))
puts("无成员!");
else
Traverse(pt, printitem);
}
void findpet(const Tree* pt)
{
Item temp{};
if (TreeIsEmpty(pt))
{
puts("无成员!");
return;
}
puts("输入查找宠物的名字:");
s_gets(temp.petname, SLEN);
puts("输入查找宠物的种类:");
s_gets(temp.petkind, SLEN);
uppercase(temp.petname);
uppercase(temp.petkind);
printf("%s the %s ", temp.petname, temp.petkind);
if (InTree(&temp, pt))
printf("是成员!\n");
else
printf("不是成员!\n");
}
void printitem(Item item)
{
printf("Pet: %-19s Kind: %-19s\n", item.petname, item.petkind);
}
void uppercase(char* str)
{
while (*str)
{
*str = toupper(*str);
str++;
}
}
char* s_gets(char* st, int n)
{
char* ret_val = nullptr;
char* find = nullptr;
ret_val = fgets(st, n, stdin);
if (ret_val)
{
find = strchr(st, '\n');
if (find)
*find = '\0';
else
while (getchar() != '\n')
continue;
}
return ret_val;
}
5、运行结果
Don't watch the clock. Do what it does. Keep doing.
不要只看时钟,要效仿时钟一直前行!