二叉排序树简易版抽象数据类型的.h头文件与.c文件

这两个文件配合下面这篇文章使用
图解二叉排序树的实现 (超详细)

.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);
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值