C数据结构-二叉查找树

该博客介绍了通过二叉查找树结构实现宠物俱乐部程序,此程序具备向俱乐部成员花名册添加宠物、显示成员列表、报告成员数量、核实成员并退出等功能,还给出了运行结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/* 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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值