二叉搜索树是什么?为什么需要它?
类似于二分查找,只要我们先将元素按从大到小或从小到大的顺序进行排列,那么我们在查找起来的时候就会很方便,二叉搜索树的存在也是为了快速找到某个元素。
二叉搜索树也叫二叉排列树或二叉查找树,为了快速找到某个结点而设立的 ,类似二分查找
,它是一棵二叉树,可以为空,如果不为空,要满足以下性质
//1.非空左子树的所有键值小于其根节点的键值
//2.非空右子树的所有键值大于其根节点的键值
//3.左,右子树都是二叉搜索树
这里记录二叉搜索树 建立(可以理解为插入),查找和删除。
#include <stdio.h>
#include <malloc.h>
typedef struct TreeNode *BinTree;
typedef BinTree Position;
struct TreeNode
{
ElementType Data;//节点信息
BinTree Left;//左儿子指针
BinTree Right;//右儿子指针
}
//二叉搜索树的建立或者说插入(从空树开始插入就是建立)
BinTree Insert(ElementType X,BinTree lbd)
{
if(!lbd)//如果树为空,生成并返回一个结点的二叉搜索树
{
lbd= malloc(sizeof(struct TreeNode));
lbd->Data=X;
lbd->Left=lbd->Right=NULL;
}else if(X<lbd->Data){
lbd->Left=Insert(X,lbd->Left);//递归进左子树
}else if(X>lbd->Data){
lbd->Right=Insert(X,lbd->Right);
}
return lbd;
}
//二叉搜索树的查找操作
//1.递归实现
Position Find(ElementType X,BinTree lbd)//X为要查找的元素,lbd为该二叉搜索树指针
{
if(!lbd) return NULL;//树空,查找失败
if(X>lbd->Data)
return Find(X,lbd->Right);//去右子树那边继续查找
else if(X<lbd->Data)
return Find(X,lbd->Left);
else{
return lbd;//查找成功,返回结点地址
}
}
//2.非递归实现(执行效率更高)
Position IterFind(ElementType X,BinTree lbd)
{
while(lbd){
if(X>lbd->Data)
lbd=lbd->Right;//去右子树那边接着找
else if(X<lbd->Data)
lbd=lbd->Left;//去左子树那边找
else
return lbd;//找到了,返回找到的结点的地址
}
return NULL;//查找失败
}
//3.查找二叉搜索树里的最大元素和最小元素
//根据搜索树结构,最大元素在树的最右分枝的结点上,最小元素在最左分枝结点上
Position FindMin(BinTree lbd){
if(!lbd) return NULL//这是空的二叉搜索树,返回NULL
else if(!lbd->Left)
return lbd;//找到最左结点了
else
return FindMin(lbd->Left);//递归,继续沿左分支找
}
Position FindMax(BinTree lbd){
if(lbd)
{
while(lbd->Right) lbd=lbd->Right;
}
return lbd;
}
//二叉搜索树的删除
//要删除的结点有3种情况
//1.是叶结点 ,可以直接删除
//2.只有一个子节点,将要删除结点的父节点指向该子节点
//3.有左右两子树, 用被删除结点的右子树的最小元素或左子树的最大元素替代被删除结点
BinTree Delete(ElementType X,BinTree BST)
{
Position Tmp;//临时变量
if(!BST) printf("要删除的元素未找到");//树空
else if(X<BST->Data)
BST->Left=Delete(X,BST->Left);//没找到,去左子树找
else if(X>BST->Data)
BST->Right=Delete(X,BST->Right);//没找到,去右子树找
else/*找到要删除的结点*/
if(BST->Left&&BST->Right)//要删除的结点有左右两子树
{
Tmp=FindMin(BST->Right);//去要删除的结点的右子树找最小结点替代它
BST->Data=Tmp->Data;
BST->Right=Delete(BST->Data,BST->Right);//由于最小节点已被用来替代,所以要删掉它
} else//被删除结点有一个或无子结点
{
Tmp=BST;
if(!BST->Left)//有右结点或无子结点
BST=BST->Right;
else if(!BST->Right)//有左孩子或无子结点
{
BST=BST->Left;
}
free(Tmp);
}
return BST;
}