C实现二叉树

建立接口

/*tree.h -- 二叉查找树*/
#pragma once                  //只编译一次
#define SLEN 20

/*根据具体情况定义Item*/
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);  //清空树

实现接口

/*function.cpp,实现接口*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"tree.h"

/*局部数据类型*/
typedef struct pair {   /*包含两个指向树节点的指针*/
	Trnode *child;     /*用于SeekItem()函数*/
	Trnode *parent;
}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 DeleteNode(Trnode **ptr);
static Pair SeekItem(const Item *pi, const Tree *ptree);
static void InOrder(const Trnode *root, void(*pfun)(Item item));
static void DeleteAllNodes(Trnode *root);
//

/*为新节点分配内存  MakeNode()函数*/
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;
}

/*添加节点到非空树中   AddNode()函数*/
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, "location error in AddNode()\n");
		exit(1);
	}
}

/*查找项   SeekItem()函数*/
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;
}
/*删除一个节点,用于DeleteItem()*/
static void DeleteNode(Trnode **ptr)
/*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);
	}
}
/*InOrder()用于Traverse()*/
static void InOrder(const Trnode *root, void(*pfun)(Item item))
{
	if (root != NULL)
	{
		InOrder(root->left, pfun);
		(*pfun)(root->item);
		InOrder(root->right, pfun);
	}
}
/*DeleteAllNodes()用于DeleteAll()*/
static void DeleteAllNodes(Trnode *root) //主要作用为释放内存
{
	Trnode *pright;
	if (root != NULL)
	{
		pright = root->right;
	    DeleteAllNodes(root->left);
	    free(root);
	    DeleteAllNodes(pright);
	}
}
//-------------------------------------------------------------------------------

/*$初始化*/
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;
}

使用接口
/*petclub.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()
{
	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("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("alnfdgq", ch) == NULL)
			puts("please enter an a,l,n,f,d,g,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 petkind:");
		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("empty!");
		return;
	}
	puts("Please enter name:");
	s_gets(temp.petname, SLEN);
	puts("And then enter kind:");
	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 members.");
		return;
	}
	puts("Enter the name:");
	s_gets(temp.petname, SLEN);
	puts("Then enter kind:");
	s_gets(temp.petkind, SLEN);
	uppercase(temp.petname);
	uppercase(temp.petkind);
	printf("%s the %s", temp.petname, temp.petkind);
	if (DeleteItem(&temp, pt))
		printf("Done!\n");
	else
		puts("Fault!");
}

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)
			*find = '\0';     //在此处放置一个空字符
		else
			while (getchar() != '\n')
				continue;      //处理输入行的剩余内容
	}
	return ret_val;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值