呈接BST

120 阅读2分钟
// 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. 另外每种情况还要都考虑一下要删除的元素是否为根节点。