JavaScript数据结构(二叉搜索树)

JavaScript数据结构(二叉搜索树)

二叉搜索树

二叉搜索树是一棵二叉树,可以为空。

如果不为空,则满足以下性质:

  • 条件 1:非空左子树的所有键值小于其根节点的键值;
  • 条件 2:非空右子树的所有键值大于其根节点的键值;
  • 条件 3:左、右子树本身也都是二叉搜索树;

二叉搜索树的封装

在这里插入图片描述

二叉搜索树的常见操作

  • insert(key) 向树中插入一个新的键。
  • search(key) 在树中查找一个键,如果节点存在,则返回 true;如果不存在,则返回 false
  • preOrderTraverse 通过先序遍历方式遍历所有节点。
  • inOrderTraverse 通过中序遍历方式遍历所有节点。
  • postOrderTraverse 通过后序遍历方式遍历所有节点。
  • min 返回树中最小的值/键。
  • max 返回树中最大的值/键。
  • remove(key) 从树中移除某个键。

Node节点类

class Node {
    constructor(key, value) {
        this.key = key;
        this.value = value;
        this.left = null;
        this.right = null;
    }
}

二叉搜索树封装类

class SearchTree {
    constructor() {
            this.root = null;
        }
        // 插入代码
    insert(key, value) {
        const node = new Node(key, value);
        // 插入分为两种情况,当根节点为空时;
        if (this.root == null) {
            this.root = node;
        } else {
            this.insertSearch(this.root, node)
        }
    }
    insertSearch(oldNode, node) {
            if (oldNode.key > node.key) {
                if (oldNode.left == null) {
                    oldNode.left = node;
                } else {
                    this.insertSearch(oldNode.left, node);
                }
            } else if (oldNode.key < node.key) {
                if (oldNode.right == null) {
                    oldNode.right = node;
                } else {
                    this.insertSearch(oldNode.right, node);
                }
            } else {
                return false;
            }
        }
        //遍历代码
    PreOrder() {
        if (this.root == null) {
            return;
        } else {
            this.PreOrderNode(this.root)
        }
    }
    PreOrderNode(node) {
            if (node != null) {
                console.log(node.key);
                this.PreOrderNode(node.left);
                this.PreOrderNode(node.right);
            }
        }
        //中序遍历
    InOrder() {
        if (this.root == null) {
            return
        } else {
            this.InOrderNode(this.root)
        }
    }
    InOrderNode(node) {
            if (node != null) {
                this.InOrderNode(node.left);
                console.log(node.key);
                this.InOrderNode(node.right);
            }
        }
        // 后序遍历
    PostOrder() {
        if (this.root == null) {
            return
        } else {
            this.PostOrderNode(this.root);
        }
    }
    PostOrderNode(node) {
            if (node != null) {
                this.PostOrderNode(node.left);
                this.PostOrderNode(node.right);
                console.log(node.key);
            }
        }
        //`min`z最小值
    min() {
            if (!this.root) return
            let node = this.root;
            while (node.left != null) {
                node = node.left;
            }
            return node;
        }
        //`max`z最小值
    max() {
        if (!this.root) return
        let node = this.root;
        while (node.right != null) {
            node = node.right;
        }
        return node;
    }
    remove(key) {
        if (this.root == null) {
            return;
        } else {
            let currentNode = this.root;
            let prevNode = currentNode;
            while (currentNode && (currentNode.left || currentNode.right)) {
                if (currentNode.key > key) {
                    prevNode = currentNode;
                    currentNode = currentNode.left;
                } else if (currentNode.key < key) {
                    prevNode = currentNode;
                    currentNode = currentNode.right;
                } else {
                    break;
                }
            }
            // 如果找到的是叶节点
            if (!currentNode.left && !currentNode.right) { // 页节点
                if (prevNode.left == currentNode) prevNode.left = null;
                if (prevNode.right == currentNode) prevNode.right = null;
                return
            } else if (!currentNode.left || !currentNode.right) { //只有一个子节点的节点
                if (prevNode.left == currentNode) {
                    if (currentNode.left) {
                        prevNode.left = currentNode.left;
                    } else {
                        prevNode.left = currentNode.right;
                    }

                } else {
                    if (currentNode.right) {
                        prevNode.right = currentNode.right;
                    } else {
                        prevNode.right = currentNode.left;
                    }
                }
                return
            } else {
                console.log(prevNode);
                console.log(currentNode);

                let successNode = currentNode.right;
                let headNode = successNode;
                while (successNode && successNode.left) {
                    headNode = successNode;
                    successNode = successNode.left;
                }
                // 后继节点的父节点 headNode
                // successNode 后继节点
                if (headNode == successNode) {
                    if (successNode.right) {
                        currentNode.right = successNode.right;
                        if (prevNode.left == currentNode) {
                            prevNode.left = successNode;
                        }
                        if (prevNode.right == currentNode) {
                            prevNode.right = successNode;
                        }

                        successNode.left = currentNode.left;
                        successNode.right = currentNode.right;
                    } else {
                        if (prevNode.left == currentNode) {
                            prevNode.left = successNode;
                        }
                        if (prevNode.right == currentNode) {
                            prevNode.right = successNode;
                        }

                        successNode.left = currentNode.left;
                    }
                } else {
                    if (successNode.right) {
                        headNode.left = successNode.right;
                        if (prevNode.left == currentNode) {
                            prevNode.left = successNode;
                        }
                        if (prevNode.right == currentNode) {
                            prevNode.right = successNode;
                        }
                        successNode.left = currentNode.left;
                        successNode.right = currentNode.right;
                    } else {
                        headNode.left = null
                        if (prevNode.left == currentNode) {
                            prevNode.left = successNode;
                        }
                        if (prevNode.right == currentNode) {
                            prevNode.right = successNode;
                        }
                        successNode.left = currentNode.left;
                        successNode.right = currentNode.right;
                    }
                }
                if (currentNode == this.root) {
                    this.root = successNode
                }
            }
        }
    }
}

代码测试

console.log(searchTree);
//
//SearchTree {
//  root: Node {
//    key: 11,
//    value: { name: '小付1' },
//    left: Node { key: 7, value: [Object], left: [Node], right: [Node] },
//    right: Node { key: 15, value: [Object], left: [Node], right: [Node] }
//  }
//}
searchTree.PreOrder();
// 11 7 5 3 9 8 15 13 12 14 20 18 19 25
searchTree.InOrder();
// 3 5 7 8 9 10 11 12 13 14 15 18 19 20 25
searchTree.PostOrder()
//3 5 8 10 9 7 12 14 13 19 18 25 20 15 11
console.log(searchTree.min());
// Node { key: 3, value: { name: '小付6' }, left: null, right: null }
console.log(searchTree.max());
// Node { key: 25, value: { name: '小付14' }, left: null, right: null }
searchTree.remove(10);
searchTree.PreOrder();
//11 7 5 3 9 8 15 13 12 14 20 18 19 25
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
排序是一种特殊的二,它满足以下条件: 1. 对于每个节点,它的左子中的所有节点的值都小于该节点的值; 2. 对于每个节点,它的右子中的所有节点的值都大于该节点的值; 3. 左右子也都是二排序。 为了实现二排序的查找,我们需要以下步骤: 1. 从根节点开始,比较要查找的值与当前节点的值的大小关系; 2. 如果要查找的值比当前节点的值小,则进入左子继续查找; 3. 如果要查找的值比当前节点的值大,则进入右子继续查找; 4. 如果要查找的值与当前节点的值相等,则找到目标节点,返回该节点。 下面是使用javascript语言实现二排序查找的代码示例: ```javascript class TreeNode { constructor(val) { this.val = val this.left = null this.right = null } } class BinarySearchTree { constructor() { this.root = null } insert(val) { const node = new TreeNode(val) if (!this.root) { this.root = node } else { let curr = this.root while (true) { if (val < curr.val) { if (!curr.left) { curr.left = node break } else { curr = curr.left } } else if (val > curr.val) { if (!curr.right) { curr.right = node break } else { curr = curr.right } } else { break // 值已存在,不插入 } } } } search(val) { let curr = this.root while (curr) { if (val === curr.val) { return curr } else if (val < curr.val) { curr = curr.left } else { curr = curr.right } } return null } } // 示例 const bst = new BinarySearchTree() bst.insert(5) bst.insert(3) bst.insert(7) bst.insert(2) bst.insert(4) bst.insert(6) bst.insert(8) console.log(bst.search(6)) // TreeNode { val: 6, left: null, right: null } console.log(bst.search(9)) // null ``` 上面的代码中,使用了 `TreeNode` 类表示节点,使用 `BinarySearchTree` 类表示二排序。在插入节点时,如果插入的值已存在,则不插入。在查找节点时,如果找到则返回目标节点,否则返回 `null`。可以通过示例测试查找的正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值