[数据结构学习笔记9] 二叉查找树(Binary Search Trees)
二叉查找树,它是一类特殊的二叉树,除了基本的二叉树规则外,还要满足:
1. 左边的子节点要小于父节点值
2. 右边的子节点要大于父节点值
图示:
添加节点:
42
| |
24 99
| | |
15 50 120
|
64
移除节点:
1. 如果移除的是叶子节点,那直接移除
2. 如果移除的是一个节点,它的下面只有一个孩子节点,那这个孩子节点就取代移除节点的位置
3. 步骤2也适用于,只有一个孩子节点,该孩子节点下面还有孩子节点的情况
4. 如果移除的节点下有两个孩子节点,那么就按照中序法,找到移除节点下最接近它的大数,或者是该节点往右,最小的数,替换移除节点
代码实现(javascript)
加节点:
1. 如果树为空,创建一个节点,为根节点
2. 比较要加的新节点,和根节点的大小
3. 如果新节点值小于根节点,重复步骤2,3,往左
4. 如果新节点值大于根节点,重复步骤2,4,往右
5. 如果新节点值等于树中的一个存在节点,返回消息告知这个节点没有被加入
6. 创建一个新节点,往左或右插入
7. 平衡该树,维持二叉查找树的特征
移除节点:
1. 找到要移除的节点,如果没有找到,则返回消息,告知没有找到
2. 如果要移除的是叶子节点,则简单移除
3. 如果要移除的节点有一个孩子节点,用孩子节点替换要移除的节点
4. 如果要移除的节点有两个孩子,那就要找到中序下一个节点
4.1 往右一次,然后一直往左
4.2 用中序下一个节点替换移除节点
5. 平衡该树,维持二叉查找树特征
class Node { constructor(data) { this.data = data; this.left = null; this.right = null; } } class BinarySearchTree { constructor() { this.root = null; } insert(value) { // create a new node with the given value const newNode = new Node(value); // If the tree is empty, the new node becomes the root if (this.root === null) { this.root = newNode; return this; } // Traverse the tree to find the correct position for the new node let currentNode = this.root; while (true) { if (value === currentNode.data) { return undefined; } else if (value < currentNode.data) { if (currentNode.left === null) { currentNode.left = newNode; return this; } currentNode = currentNode.left; } else { if (currentNode.right === null) { currentNode.right = newNode; return this; } currentNode = currentNode.right; } } } remove(value) { let currentNode = this.root; let parentNode = null; while (currentNode !== null) { if (value === currentNode.data) { if (currentNode.left === null && currentNode.right === null) { if (parentNode === null) { this.root = null; } else { if (parentNode.left === currentNode) { parentNode.left = null; } else { parentNode.right = null; } } return true; } else if (currentNode.left !== null && currentNode.right === null) { if (parentNode === null) { this.root = currentNode.left; } else { if (parentNode.left === currentNode) { parentNode.left = currentNode.left; } else { parentNode.right = currentNode.left; } } return true; } else if (currentNode.left === null && currentNode.right === null) { if (parentNode === null) { this.root = currentNode.right; } else { if (parentNode.left === currentNode) { parentNode.left = currentNode.right; } else { parentNode.right = currentNode.right; } } return true; } else { let successor = currentNode.right; let successorParent = currentNode; while (successor.left !== null) { successorParent = successor; successor = successor.left; } if (successorParent.left === successor) { successorParent.left = successor.right; } else { successorParent.right = successor.right; } currentNode.data = successor.data; return true; } } else if (value < currentNode.data) { parentNode = currentNode; currentNode = currentNode.left; } else { parentNode = currentNode; currentNode = currentNode.right; } } return false; } }
使用二叉查找树
let myBST = new BinarySearchTree(); myBST.insert(10); myBST.insert(5); myBST.insert(15); myBST.insert(3); myBST.insert(7); myBST.insert(13); myBST.insert(18); myBST.insert(20);
// remove
myBST.remove(15);
因为二叉查找树的特征,一般时间复杂度是O(log n)。但是也有最坏的情况,二叉查找树可能会退化为链表,这时候时间复杂度可能会达到O(n)。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战