从 JavaScrip 中的二叉搜索树中删除所需的节点
问题
假设,我们有以下代码创建一个二叉搜索树DS并为我们提供插入节点的功能-
class Node{
constructor(data) {
this.data= data;
this.left= null;
this.right= null;
};
};
class BinarySearchTree{
constructor(){
//二叉搜索树的根
this.root= null;
}
insert(data){
var newNode = new Node(data);
if(this.root === null){
this.root = newNode;
}else{
this.insertNode(this.root, newNode);
};
};
insertNode(node, newNode){
if(newNode.data < node.data){
if(node.left === null){
node.left= newNode;
}else{
this.insertNode(node.left, newNode);
};
} else {
if(node.right === null){
node.right= newNode;
}else{
this.insertNode(node.right,newNode);
};
};
};
};
const BST = new BinarySearchTree();
BST.insert(5);
BST.insert(3);
BST.insert(6);
BST.insert(2);
BST.insert(4);
BST.insert(7);执行完这段代码后,我们的BST将如下所示-
5 / \ 3 6 / \ \ 2 4 7
我们需要编写另一个函数deleteNode(),它接受任何BST的根作为第一个参数,一个数值作为第二个参数。
如果第二个参数指定的值存在于树中,我们的函数应该删除保存该值的节点,否则我们的函数什么都不做。在这两种情况下,我们的函数都应该返回BST的更新根。
示例
此代码将是-
class Node{
constructor(data) {
this.data= data;
this.left= null;
this.right= null;
};
};
class BinarySearchTree{
constructor(){
//二叉搜索树的根
this.root= null;
}
insert(data){
var newNode = new Node(data);
if(this.root === null){
this.root = newNode;
}else{
this.insertNode(this.root, newNode);
};
};
insertNode(node, newNode){
if(newNode.data < node.data){
if(node.left === null){
node.left= newNode;
}else{
this.insertNode(node.left, newNode);
};
} else {
if(node.right === null){
node.right= newNode;
}else{
this.insertNode(node.right,newNode);
};
};
};
};
const BST = new BinarySearchTree();
BST.insert(5);
BST.insert(3);
BST.insert(6);
BST.insert(2);
BST.insert(4);
BST.insert(7);
const printTree = (node) => {
if(node !== null) {
printTree(node.left);
console.log(node.data);
printTree(node.right);
};
};
const deleteNode = function(root, key) {
if(!root){
return null;
};
if(root.data > key){
if(!root.left){
return root;
}else{
root.left = deleteNode(root.left, key);
};
} else if(root.data < key){
if(!root.right) return root;
elseroot.right= deleteNode(root.right, key);
} else {
if(!root.left || !root.right){
returnroot.left|| root.right;
} else {
let nd = new TreeNode();
let right = root.right;
nd.left = root.left;
while(right.left){
right = right.left;
}
nd.data = right.data;
nd.right = deleteNode(root.right, right.data);
return nd;
}
}
return root;
};
console.log('Before Deleting any node');
printTree(BST.root);
console.log('After deleting node with data 4');
printTree(deleteNode(BST.root, 4));代码说明:
一旦找到目标节点,我们总共需要考虑三个条件。
一片叶子(没有左,没有右);
有左,无右;没有左有右;
左右都有。
1和2很简单,我们只需要返回null或我们拥有的任何东西(左或右);
而对于最后一个条件,我们需要知道在我们删除目标节点后,将用什么来替换它。如果我们简单地向左或向右拖动它,BST将无效。所以我们必须从右子树中找到最小的,或者从左子树中找到最大的。
输出结果
控制台中的输出将是-
Before Deleting any node 2 3 4 5 6 7 After deleting node with data 4 2 3 5 6 7