二叉查找树(C语言实现 )

本文介绍了二叉查找树的特性,包括左右子树的值域关系。详细讲解了使用C语言实现查找、插入和删除操作的递归过程。Find函数通过比较根节点值实现查找,FindMin和FindMax分别通过递归找到最小和最大值。Insert函数根据值的大小关系进行递归插入,Delete函数处理包括无子节点和有两个子节点的删除情况。PrintTree函数通过先序遍历打印整个树。

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

二叉查找树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉查找树。

在使用递归的时候,假如函数有返回值,记得接收返回值,并且保证函数在每个板块结束后都有return,以防出错。具体见Find、Insert、Delete等函数的实现过程。

Find:通过比较根数据域的值和输入参数的大小递归调用实现。

FindMin:一直往左递归

FindMax:一直往右递归

Insert:通过比较根数据域的值和输入参数的大小关系进行递归,每次递归结束都返回当前根值

Delete:访问方式同Insert,假如要删除的节点有一个或没有子节点,容易删除,不赘述;假如有两个子节点,则先找出其右子树中的最小值,赋给该节点,然后递归删除其右子树中的最小节点。

PrintTree:先序遍历访问节点并打印

#ifndef SEARCHBITREE_H
#define SEARCHBITREE_H

struct SearchBiTree; //二叉查找树结构体
typedef SearchBiTree * SBiTree; //二叉查找树 树节点指针
typedef int ElemType; //数据域数据类型

struct SearchBiTree{
	ElemType elem; //数据域
	SBiTree left;  //左儿子指针,左儿子数据域小于父节点
	SBiTree right; //右儿子指针,右儿子数据域大于父节点
};

//清空树,返回根地址给根节点
SBiTree MakeEmpty(SBiTree B);
//查找树B中有无值为E的数据域,有则返回true
bool Find(ElemType E, SBiTree B);
//返回树B中的最小值,若B为空,返回-1
ElemType FindMin(SBiTree B);
//返回树B中的最大值,若B为空,返回-1
ElemType FindMax(SBiTree B);
//为树B插入E,成功则返回树根地址
SBiTree Insert(ElemType E, SBiTree B);
//删除树B中的E数据域,成功则返回树根地址
SBiTree Delete(ElemType E, SBiTree B);
//先序遍历树B并打印,值域为空则输出0
void PrintTree(SBiTree B);

#endif


#include <stdlib.h>
#include <stdio.h>
#include "SearchBiTree.h"

SBiTree MakeEmpty(SBiTree B)
{
	if (B != NULL){
		MakeEmpty(B->left);
		MakeEmpty(B->right);
		free(B);
	}
	return NULL;
}

bool Find(ElemType E, SBiTree B)
{
	if (B != NULL){
		if (B->elem == E){
			return true;
		}
		else if (B->elem < E){
			return Find(E, B->right); //注意这里Find(E, B->right)前面有return,若果没有return,就会向上级函数返回最后的false
		}
		else{
			return Find(E, B->left);
		}
	}
	return false;
}

ElemType FindMin(SBiTree B)
{
	if (B != NULL){
		if (B->left == NULL){
			return B->elem;
		}
		else{
			return FindMin(B->left);//递归查找左子树的左子树,最小值一定在最左边
		}
	}
	return -1;//树为空,返回-1
}

ElemType FindMax(SBiTree B)
{
	if (B != NULL){
		if (B->left == NULL){
			return B->elem;
		}
		else{
			return FindMax(B->right);//递归查找右子树的右子树,最大值一定在最右边
		}
	}
	return -1;//树为空,返回-1
}

SBiTree Insert(ElemType E, SBiTree B)
{
	if (B != NULL){
		if (E > B->elem){
			B->right = Insert(E, B->right);//父节点的right域 = 父节点的right域,right域可能不变,也可能因为malloc改变
		}
		else if (E < B->elem){
			B->left = Insert(E, B->left);
		}
		else{//E已经存在,不能重复插入
			return B;
		}
	}
	else{
		B = (SBiTree)malloc(sizeof(struct SearchBiTree));
		B->elem = E;
		B->left = NULL;
		B->right = NULL;
		return B;
	}
	return B; //这个必须加,假如不加,函数在运行比如61行之后,会出现没有返回值的情况,会发生什么?
}

SBiTree Delete(ElemType E, SBiTree B)
{
	if (B != NULL){//判断是否为空树
		if (B->elem == E){//如果找到了
			if (B->left == NULL || B->right == NULL){//没有子节点或只有一个子节点
				SBiTree tempPtr = B;
				if (B->right == NULL){//没有子节点或只有左节点
					B = B->left;
					free(tempPtr);
					return B;//将子节点地址返回给父节点
				} 
				else if (B->left == NULL){//只有右节点
					B = B->right;
					free(tempPtr);
					return B;
				}
			}

			else{//有两个儿子,用其右子树中最小的数据代替该节点的数据,然后递归删除
				B->elem = FindMin(B->right);
				B->right = Delete(B->elem, B->right);//相当于用右子树中最小的节点覆盖删除节点,然后删除右子树中的那个节点
				return B;
			}
		}

		else if (B->elem > E){//如果没找到,继续搜索左子树
			B->left = Delete(E, B->left);
			return B;//将子节点地址返回给父节点
		}

		else{//如果没找到,继续搜索右子树
			B->right = Delete(E, B->right);
			return B;
		}
	}

	else{//空树,输出NULL
		return NULL;
	}
}

void PrintTree(SBiTree B)
{
	if (B == NULL){
		printf("0 ");
	}
	else{
		printf("%d ",B->elem);
		PrintTree(B->left);
		PrintTree(B->right);
	}
}


#include <stdio.h>
#include <stdlib.h>
#include "SearchBiTree.h"

int main()
{
	SBiTree testTree = NULL;
	testTree = Insert(6, testTree);
	Insert(2, testTree);
	Insert(1, testTree);
	Insert(5, testTree);
	Insert(3, testTree);
	Insert(4, testTree);
	Insert(8, testTree);

	printf("testTree最开始为:");
	PrintTree(testTree); //结果为621005304000800
	printf("\n");

	printf("树中最大值为:%d\n", FindMax(testTree));
	printf("树中最小值为:%d\n", FindMin(testTree));
	/*三选一单独测试*/
	Delete(4, testTree);
	printf("删除4以后testTree为:"); //结果为6210053000800
	PrintTree(testTree);
	printf("\n");

	//Delete(3, testTree);
	//printf("删除3以后testTree为:"); //结果为6210054000800
	//PrintTree(testTree);
	//printf("\n");

	//Delete(2, testTree);
	//printf("删除2以后testTree为:"); //结果为6310054000800
	//PrintTree(testTree);
	//printf("\n");


	system("pause");
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值