二叉查找树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉查找树。
在使用递归的时候,假如函数有返回值,记得接收返回值,并且保证函数在每个板块结束后都有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;
}