搜索树

在此以链式存储的方式实现,为平衡树做铺垫,实现搜索树的:插入(构建)、删除、查找、遍历操作,在此以纯C语言编写(以后有上机考试为纯C,在此适应),使用黑盒测试进行了少量数据验证,欢迎指正。

Code(C)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define null NULL
#define bool int

const int true = 1;
const int false = 0;

typedef struct BTNode {
	char data;
	struct BTNode *lchild, *rchild;
} BTNode;
/* 
 * 插入节点 
 */
void insertBTNode(BTNode **root, char val)
{
	BTNode *node = null;
	BTNode *pt = null, *pre = null;
	if (!(*root)) {
		node = (BTNode*)malloc(sizeof(BTNode));
		node->data = val;
		node->lchild = node->rchild = null;
		*root = node;
		return ;
	}
	pt = *root;
	while (pt) {
		pre = pt;
		if (val == pt->data)
			return ;
		if (val > pt->data)
			pt = pt->rchild;
		else 
			pt = pt->lchild;
	}
	node = (BTNode*)malloc(sizeof(BTNode));
	node->data = val;
	node->lchild = node->rchild = null;
	if (val > pre->data)
		pre->rchild = node;
	else 
		pre->lchild = node;
}
/* 
 * 查找某节点值 
 */
bool searchInTree(BTNode *root, char val)
{
	BTNode *pt = root;
	while (pt) {
		if (pt->data == val)
			return true;
		if (val > pt->data)
			pt = pt->rchild;
		else
			pt = pt->lchild;
	}
	return false;
}
/* 
 * 中序遍历输出 
 */
void inorder(const BTNode *node)
{
	if (node == null)
		return ;
	inorder(node->lchild);
	printf("%c ", node->data);
	inorder(node->rchild);
}
/* 
 * 删除操作 
 */
int deleteNode(BTNode **root, BTNode *pre, BTNode *pt)
{
	BTNode *forpt = null, *prept = null; 
	if (!pt->lchild && !pt->rchild) //没有左子树也没有右子树,妥妥的叶子节点 
	{
		if (!pre) { //要删除的是根节点 
			*root = null;
		} else {
			//删除非根节点 
			if (pt->data > pre->data)
				pre->rchild = null;
			else 
				pre->lchild = null;
		} 
		free(pt);
		//pt = null; //这不多余不? 
	}
	else if (!pt->lchild && pt->rchild) //没有左子树,存在右子树
	{
		if (!pre) { //要删除的是根节点 
			*root = pt->rchild;
		} else {
			//删除非根节点 
			if (pt->data > pre->data)
				pre->rchild = pt->rchild;
			else 
				pre->lchild = pt->rchild;
		} 
		free(pt);
	}
	else if (pt->lchild && !pt->rchild) //有左子树,没有右子树
	{
		if (!pre) { //要删除的是根节点 
			*root = pt->lchild;	
		} else {
			//删除非根节点 
			if (pt->data > pre->data)
				pre->rchild = pt->lchild;
			else 
				pre->lchild = pt->lchild;
		} 
		free(pt);
	}
	else if (pt->lchild && pt->rchild) //两边的子树都存在
	{
		//去找左子树的最右节点 
		forpt = pt->lchild;
		prept = pt;
		while (forpt->lchild || forpt->rchild) {
			prept = forpt;
			if (forpt->rchild)
				forpt = forpt->rchild;
			else 
				forpt = forpt->lchild;
		} 
		if (forpt->data > prept->data)
			prept->rchild = null;
		else 
			prept->lchild = null;
		pt->data = forpt->data;
		free(forpt);
	}
}
/*
 * 删除树节点 
 */
int deleteBTNode(BTNode **root, char val)
{
	BTNode *pt = *root, *pre = null;
	int status = 0;
	while (pt) {
		if (val == pt->data) {
			//找到了删除节点,对要删除的节点进行种类判定(4种不同的删除方式-叶子、左右子树存在一个、左右子树都存在、左右子树都不存在) 
			deleteNode(root, pre, pt);
			status = 1;
			break;
		}
		pre = pt;
		if (val > pt->data)
			pt = pt->rchild;
		else 
			pt = pt->lchild;
	}
	return status;
}
/* 
 * 纯C语言输出char很麻烦,自定义输出 
 */
int scanfAInt()
{
	int n;
	scanf("%d", &n);
	getchar();
	return n;
}
char scanfAChar()
{
	char c;
	scanf("%c", &c);
	getchar();
	return c;
}
int main()
{
	BTNode *root = null;
	int n, i;
	char val;
	bool flag = false;
	n = scanfAInt();
	for (i = 0; i < n; i++) {
		val = scanfAChar();
		insertBTNode(&root, val);
	}
	inorder(root);
	printf("\n");
	if (!deleteBTNode(&root, 'g')) {
		printf("No the val!\n");
	} else {
		printf("Ans:");
		inorder(root);
		printf("\n");
	}
	return 0;
}

测试数据

/* 测试数据 

1
g
//

2
g a
//a 

5
g d a b e
//a b d e 

3
g a j
//a j

9
g d a b e f l k m
//a b d e f k l m

2
g j
//j

6
g j h i l k
//h i j k l

8
o g c a d k h m
//a c d h k m o

11
u y o q g c a d k h m
//a c d h k m o q u y


4
o g c k
//c k o


3
o g c
//c o

3
o g k 
//k o

*/

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水能zai舟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值