数据结构-二叉搜索树

二叉搜索树:BST(Binary Search Tree)

二叉搜索树是二叉树,可以为空,如果不为空,满足以下性质:

  • 非空左子树的所有键值小于其根节点的键值
  • 非空右子树的所有键值大于其根节点的键值
  • 左、右字数本身也都是二叉搜索树

二叉搜索树的特点:

  • 二叉搜索树的特点就是相对较小的值总是保存在左节点上,相对较大的值总是保存在右节点上
  • 查找效率非常高

二叉搜索树常见的操作:

  • insert(key, value):向树中插入数据
  • search(key):在树中查找
  • remove(key):从树中移除
  • update(key,value):修改节点数据
  • inOrderTraverse:通过中序遍历方式遍历所有节点
  • preOrderTraverse:通过先序遍历方式遍历所有节点
  • postOrderTraverse:通过后序遍历方式遍历所有节点
  • min:返回树中最小的键/值
  • max:返回树中最大的键/值
javascript 复制代码
class Node {
    constructor(key) {
        this._key = key;
        this._left = null;
        this._right = null;
    }
}
class BinarySearchTree {
    constructor() {
        this._root = null;
    }
    
    insert(key) {
        const insertNode = (node, newNode) => {
            if(newNode._key <= node._key) {
                if(node._left === null) {
                    node._left = newNode;
                } else {
                    insertNode(node._left, newNode);
                }
            } 
            else {
                if(node._right === null) {
                    node._right = newNode;
                } else {
                    insertNode(node._right, newNode);
                }
            }
        }
        const newNode = new Node(key)
        if (this._root === null) {
            this._root = newNode
        } else {
            insertNode(this._root, newNode)   
        }

    }

    preOrderTraverse(handler = (value) => {console.log(value)}) {
        const preOrderTraverseNode = (node) => {
            if (node === null) {
                return 
            }
            handler(node._key)
            preOrderTraverseNode(node._left)
            preOrderTraverseNode(node._right)
            
        }
        preOrderTraverseNode(this._root)
    }

    midOrderTraverse(handler = (value) => {console.log(value)}) {
        const midOrderTraverseNode = (node) => {
            if (node === null) {
                return 
            }
            midOrderTraverseNode(node._left)
            handler(node._key)
            midOrderTraverseNode(node._right)
            
        }
        midOrderTraverseNode(this._root)
    }

    postOrderTraverse(handler = (value) => {console.log(value)}) {
        const postOrderTraverseNode = (node) => {
            if (node === null) {
                return 
            }
            postOrderTraverseNode(node._left)
            postOrderTraverseNode(node._right)
            handler(node._key)
            
        }
        postOrderTraverseNode(this._root)
    }

    min() {
        if (this._root === null) {
            return null
        }
        let node = this._root
        while(true) {
            if (node._left === null) {
                return node._key
            }
            node = node._left
        }
    }

    max() {
        if (this._root === null) {
            return null
        }
        let node = this._root
        while(true) {
            if (node._right === null) {
                return node._key
            }
            node = node._right
        }
    }

    search(key) {
        const searchNode = (node, key) => {
            if (node === null) {
                return false
            }

            if (node._key === key) {
                return true
            }

            if (key < node._key) {
                return searchNode(node._left, key)
            } else {
                return searchNode(node._right, key)
            }
        }

        return searchNode(this._root, key)
    }

    remove(key) {
        if (this._root === null) {
            return false
        }
        let current = this._root
        let parent = null
        let isLeftChild = true
        while (current._key !== key) {
            parent = current
            if (key < current._key) {
                isLeftChild = true
                current = current._left
            } else {
                isLeftChild = false
                current = current._right
            }
            if (current === null) {
                return false
            }
        }

        

        // 删除叶子节点
        if (current._left === null && current._right === null) {
            if (current === this._root) {
                this._root = null
            } else {
                if (isLeftChild) {
                    parent._left = null
                } else {
                    parent._right = null
                }
            }
        }

        // 删除有一个子节点

        else if (current._left === null ) {
            if (current === this._root) {
                this._root = current._right
            } else if (isLeftChild) {
                parent._left = current._right
            } else {
                parent._right = current._right
            }

        } else if (current._right === null) {
            if (current === this._root) {
                this._root = current._left
            } else if (isLeftChild) {
                parent._left = current._left
            } else {
                parent._right = current._left
            }
        } 


        else {
            const getExChangeTargetNode = (current) => {
                let node = current._right
                let parentNode = current
                let isRightClick = true
                while(true) {
                    if (node._left === null) {
                        if (isRightClick)  {
                            parentNode._right = node._right
                        } else  {
                            parentNode._left = node._right
                        }
                        return node
                    }
                    isRightClick = false
                    parentNode = node
                    node = node._left
                }
            }

            const targetNode = getExChangeTargetNode(current);
            if (current !== this._root) {
                if (isLeftChild)  {
                    parent._left = targetNode
                } else  {
                    parent._right = targetNode
                }
            } else {
                this._root = targetNode
            }

            targetNode._right = current._right
            targetNode._left = current._left
            
        }

        return true
    }

}
相关推荐
kyriewen1 小时前
你的前端滤镜慢得像PPT?用Rust+WebAssembly,一秒处理4K图
前端·rust·webassembly
kyriewen111 小时前
你等的Babel编译,够喝三杯咖啡了——用Rust重写的SWC,只需眨个眼
开发语言·前端·javascript·后端·性能优化·rust·前端框架
IT_陈寒1 小时前
SpringBoot自动配置坑了我,原来要这样绕过去
前端·人工智能·后端
东方小月2 小时前
Claude Code 完整上手指南:MCP、Skills、第三方模型配置一次搞定
前端·人工智能·后端
XZ探长2 小时前
基于 Trae Solo 移动办公修复 Vue3 前端服务问题
前端
逍遥德2 小时前
AI时代,计算机专业大学生学习指南
java·javascript·人工智能·学习·ai编程
蝎子莱莱爱打怪2 小时前
Claude Code 省 Token 小妙招:RTK + Caveman 组合拳
前端·人工智能·后端
Rkgua2 小时前
JS中模拟函数重载的使用
javascript·jquery
竹林8182 小时前
用 wagmi v2 和 Next.js 14 硬扛 NFT 市场前端:从合约调用失败到批量上架,我踩了这些坑
javascript·next.js
Momo__3 小时前
Vue 3.6 Vapor Mode:跳过虚拟 DOM,性能极致优化
前端·vue.js