// remove(key): 删除某个键
BST.prototype.remove = function (key) {
let cur = this.root
let parent = null
let isLeftChild = true
while (cur.key !== key) {
parent = cur
if (cur.key > key) {
isLeftChild = true
cur = cur.left
} else {
isLeftChild = false
cur = cur.right
}
if (!cur) return false
}
if (!cur.left && !cur.right) {
if (cur === this.root) {
this.root = null
} else {
if (isLeftChild) {
parent.left = null
} else {
parent.right = null
}
}
} else if (cur.right === null) {
if (cur === this.root) {
this.root = cur.left
} else if (isLeftChild) {
parent.left = cur.left
} else {
parent.right = cur.left
}
} else if (cur.left === null) {
if (cur === this.root) {
this.root = cur.right
} else if (isLeftChild) {
parent.left = cur.right
} else {
parent.right = cur.right
}
} else {
let success = this.back(cur)
if (cur === this.root) {
this.root = success
} else if (isLeftChild) {
parent.left = success
} else {
parent.right = success
}
success.left = cur.left
}
}
// 找后继
BST.prototype.back = function (deNode) {
let success = deNode
let cur = deNode.right
let successParent = null
while (cur) {
successParent = cur
success = cur
cur = cur.left
}
if (success !== deNode.right) {
successParent.left = success.right
success.right = deNode.right
}
return success
}
// 找前驱 (因为这里我用的是删除元素的后继,所有没有写全)
BST.prototype.front = function (deNode) {
let success = deNode
let cur = deNode.left
while (cur) {
success = cur
cur = cur.right
}
return success
}
}
// handrle对遍历的每个元素做一些处理
let string = ''
const handler = function (node) {
string += node.key + ' '
}
下面是对封装代码进行测试
const T = new BST()
T.insert(10)
T.insert(16)
T.insert(6)
T.insert(15)
T.insert(3)
T.insert(20)
T.insert(5)
T.insert(1)T.insert(9)
T.insert(8)
T.insert(9.5)
T.remove(9)
// console.log(T.search(18))
// console.log('t', T.root.left.left)
// console.log(T.min())
// console.log(T.max())
T.preOrderTraverse(handler)
// T.inorderTraverse(handler)
// T.postOrderTraverse(handler)
console.log(string)
## 3.测试后发现先序、后序、中序遍历中存在问题:
当进行删除操作时,如果删除的元素的后继不是删除元素的右子节点的时候,使用先序、后序、中序遍历会出现问题,但是我在控制台打印,输出的搜索二叉树没有问题,麻烦各位大佬帮忙看一下究竟是哪里出现了问题。
## 4.总结:
除了删除操作复杂一点外其余操作都比较简单,所以我提供一下删除操作的思路:
首先思考我们需要用到哪些变量:
1. 要删除的元素、要删除元素的父节点、判断要删除元素是父节点的左子节点还是右子节点这样一个标记、以及要删除元素的后继;
2. 2. 删除的节点没有子节点:
直接找到删除的元素,和他的父节点,直接让其父节点指向null;
3. 要删除的元素有一个子节点:
直接让其父节点指向要删除元素的子节点;
4. 要删除的元素有两个子节点:
(1)要删除元素的后继是他的右子节点:
让其父元素先指向这个后继,再让后继指向他的左子节点;
(2)要删除的元素的后继不是他的右子节点:
这里我们就还需要1个变量:后继的父节点;
1.1让其后继父节点.left指向后继的.right;
1.2后继.right指向要删除元素的右子节点;
1.3要删除元素的父节点指向后继;1.4后继.left指向要删除元素的左子节点。 5. 另外每种情况还要都考虑一下要删除的元素是否为根节点。