数据结构之二叉搜索树(BST)

版权声明:Oreo https://blog.csdn.net/weixin_43154931/article/details/82822704

JavaScript实现二叉搜索树(BST)

  • 二叉搜索树定义
  • 二叉搜索树JavaScript代码实现

1. 二叉搜索树
二叉查找树(英语:Binary Search Tree),也称为二叉搜索树、有序二叉树(ordered binary tree)或排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树:

  1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
  2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
  3. 任意节点的左、右子树也分别为二叉查找树;
  4. 没有键值相等的节点。
    –(wiki百科)

2. 二叉搜索树代码实现

const BinarySearchTree = function() {

    let Node = function(key) {
        this.key = key;
        this.left = null;
        this.rigth = null;
    };
    let root = null;

    this.insert = function(key) {
        // 向树中插入一个新的键

        let newNode = new Node(key);

        if (root === null) {
            root = new Node(key);
        } else {
            insertNode(root, newNode);
        };

        const insertNode = function(node, newNode) {
            if (newNode.key < node.key) {
                if (node.left === null) {
                    node.left = newNode;
                } else {
                    // 递归
                    insertNode(node.left, newNode);
                }
            } else {
                if (node.rigth === null) {
                    node.rigth = newNode;
                } else {
                    insertNode(node.rigth, newNode);
                }
            }
        };
    };

    const inOrderTraverseNode = function(node, callback) {
        if (node !== null) {
            inOrderTraverseNode(node.left, callback);
            callback(node.key);
            inOrderTraverseNode(node.rigth, callback);
        }
    };

    this.inOrderTraverse = function(callback) {
        // 通过中序遍历遍历所有节点, 即从小到大顺序访问节点
        inOrderTraverseNode(root, callback);
    };

    const preOrderTraverseNode = function(node, callback) {
        if (node !== null) {
            callback(node.key);
            preOrderTraverseNode(node.left, callback);
            preOrderTraverseNode(node.rigth, callback);
        }
    };

    this.preOrderTraverse = function(callback) {
        // 先序遍历,即优先于后代节点的顺序访问每个节点。
        preOrderTraverseNode(root, callback)

    };

    const postOrderTraverseNode = function(node, callback) {
        if (node !== null) {
            preOrderTraverseNode(node.left, callback);
            preOrderTraverseNode(node.rigth, callback);
            callback(node.key);
        }
    };

    this.postOrderTraverse = function(callback) {
        // 后序遍历,即先访问节点的后代节点再访问节点本身。
        postOrderTraverseNode(root, callback);
    };
    const minNode = function(node) {
        if(node) {
            while(node && node.left !== null) {
                node = node.left;
            }
            return node.key;
        }
        return null;
    };

    this.min = function() {
        // 搜索最小值
        return minNode(root);
    };

    const maxNode = function(node) {
        if(node) {
            while(node && node.rigth !== null) {
                node = node.right;
            }
            return node.key;
        }
        return null;
    };

    this.max = function() {
        // 搜索最大值
        return maxNode(root);
    };

    const searchNode = function(node, key) {
        if (node === null) {
            return false;
        }
        if (key < node.key) {
            return searchNode(node.left, key);
        } else if (key > node.key) {
            return searchNode(node.right, key);
        } else {
            return true;
        }
    };

    this.search = function(key) {
        // 在树中查找一个键,如果节点存在,返回true,不存在,返回false
        return searchNode(root, key);
    };

    const findMinNode = function(node) {
        while (node && node.left !== null) {
            node = node.left;
        }
        return node;
    };

    const removeNode = function(node, key) {
        if (node === null) {
            return null;
        }
        if (key < node.key) {
            node.left = removeNode(node.left, key);
            return node;
        } else if (key > node.key) {
            node.right = removeNode(node.right, key);
            return node;
        } else {
            // key == node.key
            if (node.left === null && node.right ===null) {
                // 该节点是叶节点(没有子节点)
                node = null;
                return node;
            } else if (node.left === null) {
                // 该节点有一个右节点
                node = node.rigth;
                return node;
            } else if (node.right === null) {
                node = node.left;
                return node;
            } else {
                // 有两个子节点
                let aux = findMinNode(node.right);
                node.key = aux.key;
                node.right = removeNode(node.right, aux.key);
                return node;
            }            
        }
    };

    this.remove = function(key) {
        // 移除某个键
        root = removeNode(root, key);

    };

}

二叉搜索树缺点:取决于添加的节点,树的一条边可能会非常深。为了解决这个问题可以使用Adelson-Velskii-landi树(AVL树)即自平衡二叉搜索树。

猜你喜欢

转载自blog.csdn.net/weixin_43154931/article/details/82822704