BST(二叉搜索树)
BST
基础芝士
给定一棵二叉树,每个节点有权值,定义“BST 性质”为:
对于树中的任意一个节点
的权值大于 的左子树中任意节点的权值。 的权值小于 的右子树中任意节点的权值。
即
满足上述性质的二叉树即为“二叉搜索树”(BST)。可以发现,二叉搜索树的中序遍历的点权值单调递增。
一般情况下 BST 中无相同权值,当然有相同权值的也可以处理为无相同权值的。如图:
中序遍历结果为
维护操作
建立
为避免越界,一般在 BST 中插入正负无穷。仅由这两个节点构成的 BST 即为空 BST。如图:
建立的操作即为建立一个空 BST:
const int inf=1<<30;
struct bst
{
int l,r,v;
}a[N];
int tot,root;
int New(int v)
{
a[++tot].v=v;
return tot;
}
void build()
{
New(-inf),New(inf);
root=1,a[1].r=2;
}
查找
查找 BST 中是否存在权值为
设当前所在节点为
,则已找到。 ,若 无左儿子,则说明不存在;若 有左儿子,进入左子树继续查找。 ,若 无右儿子,则说明不存在;若 有右儿子,进入右子树继续查找。
用递归实现:
int find(int x,int v)
{
int y=a[x].v;
if(y==v) return x;
if(x==0) return 0; //若x不存在
return y>v ? find(a[x].l,v) : find(a[x].r,v);
}
用 while
实现:
int find(int v)
{
int x=root;
while(x)
{
int y=a[x].v;
if(y==v) break;
x= y>v ? a[x].l : a[x].r;
}
return x;
}
插入
在 BST 中插入一个权值为
类似于查找操作:
设当前所在节点为
,进入左子树继续查找。 ,进入右子树继续查找。- 若接下来进入的点为空,则直接建立。
用递归实现:
int insert(int &x,int v)//使用&,更新其父节点的信息
{
int y=a[x].v;
if(y==v) return ;
if(x==0)
{
x=New(v);
return ;
}
return y>v ? insert(a[x].l,v) : insert(a[x].r,v);
}
求最大/最小值
求以节点
则求最大值就是从
int get_min(int x)
{
while(a[x].l) x=a[x].l;
return x;
}
int get_max(int x)
{
while(a[x].r) x=a[x].r;
return x;
}
求前驱/后继
设节点为
的前驱:指中序遍历 BST 后,位于 前的第一个点,即满足 的最大的 所对应的节点。 的后继:指中序遍历 BST 后,位于 后的第一个点,即满足 的最小的 所对应的节点。
因此,求
int get_pre(int x)
{
return get_max(a[x].l);
}
int get_ne(int x)
{
return get_min(a[x].r);
}
若给出的是
int get_pre(int u,int v)
{
if(u==0) return -inf;
if(a[u].v>=v) return get_pre(a[u].l,v);//先找到左子树
return max(a[u].v,get_pre(a[u].r,v));//再找到最大值
}
int get_ne(int u,int v)
{
if(u==0) return inf;
if(a[u].v<=v) return get_ne(a[u].r,v);//先找到右子树
return min(a[u].v,get_ne(a[u].l,v));//再找最小值
}
删除
从 BST 中删除权值为
思考如何在删除
- 若
的儿子个数小于2,则直接用 的儿子代替 的位置,与 的父节点相连。 - 若
的儿子个数等于2,考虑删除后,应该是 的后继 代替它的位置,也就是要先删除 ,再用 代替 。而且 无左儿子,因为 是 右子树的最小值。所以,用 的右儿子代替 的位置,再用 代替 的位置。
void remove(int v)
{
int &x=root;//同时修改x父节点的信息
while(x)
{
int y=a[x].v;
if(y==v) break;
x= y>v ? a[x].l : a[x].r;
}
if(x==0) return;
if(a[x].l==0) x=a[x].r;
else if(a[x].r==0) x=a[x].l;
else
{
int next=get_ne(x);
remove(a[next].v);
a[next].l=a[x].l,a[next].r=a[x].r;
x=next;
}
}
结语
BST 中每一次操作的期望复杂度为
tips
点权值中需满足“BST性质”的称为“关键码”,平衡二叉树中会区分开。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」