常用方法:
- insert(key) 插入数据
- insertNode(node, newNode) 插入节点
- preOrderTraversal() 先序遍历
- midOrderTraversal() 中序遍历
- postOrderTraversal() 后续遍历
- 最值: min() / max()
- search(key) 搜索节点
- remove(key) 删除节点
// 封装二叉搜索树
function BinarySerachTree () {
function Node (key) {
this.key = key;
this.rigth = null;
this.left = null;
}
// 属性
this.root = null;
// 方法
// 1 插入数据:1.1对外暴露
BinarySerachTree.prototype.insert = function (key) {
let newNode = new Node (key);
// 判断根节点是否有值
if (this.root == null) {
this.root = newNode
} else {
this.insertNode(this.root, newNode)
}
}
// 1.2 封装递归比较
BinarySerachTree.prototype.insertNode = function (node, newNode) {
if (node.key > newNode.key) {
// 向左查找
if (node.left == null) {
node.left = newNode
} else {
this.insertNode(node.left, newNode)
}
} else {
// 向右查找
if (node.rigth == null) {
node.rigth = newNode
} else {
this.insertNode(node.rigth, newNode)
}
}
}
// 2 先序遍历
// handler为遍历处理函数
BinarySerachTree.prototype.preOrderTraversal = function (handler) {
// 传入回调函数
this.preOrderTraversalNode(this.root, handler);
}
// 2.1 先序遍历的回调函数
BinarySerachTree.prototype.preOrderTraversalNode = function (node, handler) {
// 节点不为空,则进行递归遍历处理
if (node != null) {
handler(node.key);
// 递归处理左子节点
this.preOrderTraversalNode(node.left, handler)
// 递归处理右子节点
this.preOrderTraversalNode(node.rigth, handler)
}
}
// 3 中序遍历
BinarySerachTree.prototype.midOrderTraversal = function (handler) {
// 传入回调函数
this.midOrderTraversalNode(this.root, handler)
}
BinarySerachTree.prototype.midOrderTraversalNode = function (node, handler) {
// 判断左节点是否为空
if (node != null) {
// 传入左节点递归
this.midOrderTraversalNode (node.left, handler);
// 中间节点
handler(node.key);
// 右边节点递归
this.midOrderTraversalNode (node.rigth, handler)
}
}
// 4 后序遍历
BinarySerachTree.prototype.postOrderTraversal = function (handler) {
this.postOrderTraversalNode(this.root, handler);
}
BinarySerachTree.prototype.postOrderTraversalNode = function (node, handler) {
// 判断是否为空
if (node != null) {
// 递归左节点
this.postOrderTraversalNode(node.left, handler);
// 递归右节点
this.postOrderTraversalNode(node.rigth, handler);
// 提取节点
handler(node.key)
}
}
// 5 寻找最值
BinarySerachTree.prototype.min = function () {
let minNode = this.root;
while (minNode.left != null) {
minNode = minNode.left
}
return minNode.key
}
BinarySerachTree.prototype.max = function () {
let maxNode = this.root;
while (maxNode.rigth != null) {
maxNode = maxNode.rigth
}
return maxNode.key
}
// 6 搜索某一个key
BinarySerachTree.prototype.search = function (key) {
// 获取根节点
let node = this.root;
// 循环搜索
while (node != null) {
if (key == node.key) {
return node
}
else if (key > node.key) {
node = node.rigth;
}else {
node = node.left
}
}
return false
}
// 7 * 二叉搜索树的删除
BinarySerachTree.prototype.remove = function (key) {
// 定义属性遍量
let current = this.root;
let parentNode = null;
let isLeftChild = false;
// 判断是否存在
if (current == null) {
return false
}
// 7.1 搜索删除节点
while (current.key != key) {
parentNode = current;
if (key > current.key) {
isLeftChild = false;
current = current.rigth;
} else {
isLeftChild = true;
current = current.left;
}
}
// 7.2 没有找到,不删除
if (current == null) {
return false
}
// 7.3 删除叶子节点
if (current.left == null && current.rigth == null) {
// 如果是根节点
if (current == this.root) {
this.root = null
} else if (isLeftChild) {
parentNode.left = null
} else {
parentNode.rigth = null
}
}
// 7.4 删除有一个子节点的节点
else if (current.left == null) {
// 判断是否为根节点
if (current == this.root) {
this.root = current.rigth;
}
else if (isLeftChild) {
parentNode.left = current.rigth;
} else {
parentNode.rigth = current.rigth;
}
} else if (current.rigth == null) {
if (current == this.root) {
this.root = current.left
}
else if (isLeftChild) {
parentNode.left = current.left;
} else {
parentNode.rigth = current.left;
}
}
// 7.5 删除有2个子节点的节点
else {
// 获取后继节点
let successor = this.getsuccessor(current);
// 判断是否为根节点
if (current == this.root) {
this.root = successor;
} else if(isLeftChild) {
parentNode.left = successor;
} else {
parentNode.rigth = successor;
}
// 将删除节点的左子树 等于 current.left
successor.left = current.left;
}
}
// 7.6 找后继的方法
BinarySerachTree.prototype.getsuccessor = function (delNode) {
// 定义属性
let current = delNode.rigth;
let successor = delNode;
let successorParent = delNode;
// 向右进行后继查找
while (current != null) {
successorParent = successor;
successor = current;
current = current.left;
}
// 判断寻找的后继节点是否直接就是delNode.rigth
if (successor != delNode.rigth) {
successorParent.left = successor.rigth;
successor.rigth = delNode.rigth
}
return successor
}
}
// 测试代码
let bst = new BinarySerachTree();
bst.insert(11);
bst.insert(7);
bst.insert(15);
bst.insert(5);
bst.insert(3);
bst.insert(9);
bst.insert(8);
bst.insert(10);
bst.insert(13);
bst.insert(12);
bst.insert(25);
bst.insert(18);
bst.insert(20);
bst.insert(14);
bst.insert(6);
// 测试先序遍历
let resultSearch = "先序遍历: ";
bst.preOrderTraversal(function (key) {
resultSearch += key + " ";
})
console.log(resultSearch);
// 测试中序遍历
resultSearch = "中序遍历: ";
bst.midOrderTraversal(function (key) {
resultSearch += key + " ";
})
console.log(resultSearch);
// 测试后序遍历
resultSearch = "后序遍历: ";
bst.postOrderTraversal(function (key) {
resultSearch += key + " ";
})
console.log(resultSearch);
// 测试最值
console.log(bst.min());
console.log(bst.max());
// 测试搜索
console.log(bst.search(6));
console.log(bst.search(999));
console.log("--------------------------------------");
// 测试删除节点
bst.remove(9);
bst.remove(7);
bst.remove(15);
// 测试后序遍历2.0
resultSearch = "后序遍历2.0: ";
bst.postOrderTraversal(function (key) {
resultSearch += key + " ";
})
console.log(resultSearch);