二分搜索树介绍
二分搜索树:Binary Search Tree
二分搜索树有着高效的插入、删除、查询操作。
平均时间的时间复杂度为 O(log n),最差情况为 O(n)。二分搜索树与堆不同,不一定是完全二叉树,底层不容易直接用数组表示故采用链表来实现二分搜索树
数基本结构
class Node {
constructor(val) {
this.val = val;
this.left = null;
this.right = null;
}
}
实现一个二分搜索树
1. 构造函数
class BST {
constructor() {
this.root = null;
this.size = 0;
}
}
2. 向二分搜索树中添加新的元素val
class BST {
// ...
// 向二分搜索树中添加新的元素val
add(val) {
this.root = this.addNode(this.root, val)
}
addNode(node, val) {
if (node === null) {
this.size ++;
return new Node(val)
}
if (this.compareTo(node.val, val) < 0) {
node.left = this.addNode(node.left, val)
} else if (this.compareTo(node.val, val) > 0) {
node.right = this.addNode(node.right, val)
}
return node;
}
// 针对整数进行简单比较
compareTo(a, b) {
return b - a;
}
}
3. 查看二分搜索树中是否包含元素val
class BST {
// ...
// 针对整数进行简单比较
compareTo(a, b) {
return a - b;
}
// 看二分搜索树中是否包含元素e
contains(val) {
return this.containsNode(this.root, val);
}
containsNode(node, val) {
if(node === null) {
return false;
}
if (this.compareTo(node.val, val) === 0) {
return true;
} else if (this.compareTo(node.val, val) > 0) {
return this.containsNode(node.left, val)
} else {
return this.containsNode(node.right, val)
}
}
}
4. 寻找找二分搜索树的最小元素和最大元素,并返回该元素对应的值
class BST {
// ...
// 寻找找二分搜索树的最小元素
minimum() {
return this.minimumNode(this.root).val
}
// 返回以node为根的二分搜索树的最小值所在的节点
minimumNode(node) {
if (node.left === null) {
return node
}
return this.minimumNode(node.left)
}
// 寻找二分搜索树的最大元素
maximum() {
return this.maximumNode(this.root).val
}
// 返回以node为根的二分搜索树的最大值所在的节点
maximumNode(node) {
if(node.right === null) {
return node
}
return this.maximumNode(node.right)
}
}
5. 从二分搜索树中删除最小值所在节点和最大节点,并返回该节点
class BST {
// ...
// 从二分搜索树中删除最小值所在节点, 返回最小值
removeMin() {
let ret = this.minimum()
this.root = this.removeMinNode(this.root)
return ret;
}
removeMinNode(node) {
if(node.left === null) {
let rightNode = node.right
node.right = null
this.size --;
return rightNode
}
node.left = this.removeMinNode(node.left)
return node
}
// 从二分搜索树中删除最大值所在节点
removeMax(){
let ret = this.maximum()
this.root = this.removeMaxNode(this.root)
return ret
}
removeMaxNode(node) {
if(node.right === null) {
let leftNode = node.left
node.left = null
this.size --;
return leftNode
}
node.right = this.removeMaxNode(node.right)
return node;
}
}
6. 从二分搜索树中删除元素为val的节点
class BST {
// ...
// 从二分搜索树中删除元素为val的节点
remove(val) {
this.root = this.removeNode(this.root, val)
}
// 删除掉以node为根的二分搜索树中值为val的节点, 递归算法
// 返回删除节点后新的二分搜索树的根
removeNode(node, val) {
if(node === null) {
return null;
}
if (this.compareTo(node.val, val) === 0) {
// 待删除节点左子树为空的情况
if(node.left === null) {
let rightNode = node.right
node.right = null
this.size --;
return rightNode
}
// 待删除节点右子树为空的情况
if (node.right === null) {
let leftNode = node.left
node.left = null
this.size --;
return leftNode
}
// 如果左右子树都不为空时,寻找该节点的后继successor
// 后继: 比待删除节点大的最小节点, 即待删除节点右子树的最小节点
// 用这个节点顶替待删除节点的位置
let successor = this.minimumNode(node.right)
let rightNode = this.removeMinNode(node.right)
successor.left = node.left
successor.right = rightNode
node.left = null
node.right = null
return successor
} else if (this.compareTo(node.val, val) > 0) {
node.left = this.removeNode(node.left, val)
return node
} else {
node.right = this.removeNode(node.right, val)
return node
}
}
}
7. 二分搜索树的前序遍历
class BST {
// ...
// 二分搜索树的前序遍历
preOrder() {
this.preOrderNode(this.root)
}
preOrderNode(node) {
if(node === null) {
return;
}
// 重点是这个 console 的位置
console.log(node.val)
this.preOrderNode(node.left)
this.preOrderNode(node.right)
}
}
8. 二分搜索树的中序遍历
二分搜索树的中序遍历结果时顺序的
class BST {
// ...
// 二分搜索树的中序遍历
inOrder() {
this.inOrderNode(this.root)
}
inOrderNode(node) {
if(node === null) {
return;
}
this.inOrderNode(node.left)
console.log(node.val)
this.inOrderNode(node.right)
}
}
9. 二分搜索树的后序遍历
class BST {
// ...
// 二分搜索树的后序遍历
postOrder() {
this.postOrderNode(this.root)
}
postOrderNode(node) {
if(node === null) {
return;
}
this.postOrderNode(node.left)
this.postOrderNode(node.right)
console.log(node.val)
}
}