二叉树(三): 二叉查找树

什么是二叉查找树

二叉查找树(英语:Binary Search Tree),也称为二叉查找树、有序二叉树(ordered binary tree)或排序二叉树(sorted binary tree)

他拥有以下性质:

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

图中的二叉树就是一颗二叉查找树

const nodes = {
value: 6,
left: {
value: 3,
left: {
value: 1,
left: {
value: 0
},
right: {
value: 2
}
},
right: {
value: 5
}
},
right: {
value: 8,
left: {
value: 7
},
right: {
value: 9
}
}
}

查找节点

在二叉查找树b中查找x的过程为:

  1. 若b是空树,则搜索失败,否则:
  2. 若x等于b的根节点的数据域之值,则查找成功;否则:
  3. 若x小于b的根节点的数据域之值,则搜索左子树;否则:
  4. 查找右子树。
const SearchBST = (tree, value) => {
if (!tree) {
return false
}
if (value === tree.value) {
return tree
}
if (value < tree.value) {
return SearchBST(tree.left, value)
}
return SearchBST(tree.right, value)
}

插入节点

向一个二叉查找树b中插入一个节点s的算法,过程为:

  1. 若b是空树,则将s所指节点作为根节点插入,否则:
  2. 若s->data等于b的根节点的数据域之值,则返回,否则:
  3. 若s->data小于b的根节点的数据域之值,则把s所指节点插入到左子树中,否则:
  4. 把s所指节点插入到右子树中。(新插入节点总是叶子节点)
const InsertBST = (tree, value, parent, key) => {
if (!tree) {
parent[key] = {
value
}
return true
}
if (tree.value === value) {
return false
}
if (tree.value > value) {
return InsertBST(tree.left, value, tree, 'left')
}
return InsertBST(tree.right, value, tree, 'right')
}

相比较其他算法, JS 的实现感觉有些不足

删除节点

二叉搜索树的节点删除包括两个过程,查找和删除。

在二叉查找树删去一个结点,分三种情况讨论:

  • 待删除节点度为零;
  • 待删除节点度为一;
  • 待删除节点度为二。

节点度可以看成分支数

const DeleteBST = (root, value) => {
if (!root) {
return false
}
if (root.value === value) {
return DELETE(root)
}
if (root.value > value) {
return DeleteBST(root.left, value, root, 'left')
}
return DeleteBST(root.right, value, root, 'left')
}
const DELETE = (root, parent, key) => {
// 在这里实现三种情况
// 情况 1 没有左右子节点 可直接删除
if (!root.left && !root.right) {
parent[key] = null
return true
}
// 情况 2 只有一个子节点 重新连接即可
if (!root.right) {
const q = root.left
root.value = q.value
root.left = q.left
root.right = q.right
return true
}
if (!root.left) {
const p = root.right
root.value = p.value
root.left = p.left
root.right = p.right
return true
}
// 情况 3
// 删除节点后,为了维持二叉搜索树的结构特性,需要从其左子树中选出一个最大值的节点,“上移”到删除的节点位置上
let temp = root
let l = root.left
while (l.right) {
temp = l
l = l.right
}
root.value = l.value
if (root != temp) {
temp.right = l.left
} else {
temp.left = l.left
}
return true
}

复杂度

虽然二叉查找树的最坏效率是O(n),但它支持动态查询,且有很多改进版的二叉查找树可以使树高为O(log n),从而将最坏效率降至O(log n),如AVL树、红黑树等。

结语

二叉查找树它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势,应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作

仓库地址: https://github.com/Grewer/notes

参考:

相关系列

posted @   Grewer  阅读(209)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
历史上的今天:
2020-06-17 OC 语法快速入门
点击右上角即可分享
微信分享提示