javascript 二分搜索树bst 封装

1,227 阅读3分钟

发现其实二叉树也挺简单的。

1 二叉树是什么 以及 二分搜索树是什么

答 : 二叉树应该不用解释了。二分搜索树,就是每个父节点都大于他的左子节点并且小于他的右子节点。就如下图所示:

2 javascript怎么实现上述一个二分搜索树

function BinarySerachTree() {
    // 创建节点构造函数
    function Node(key) {
        this.key = key
        this.left = null
        this.right = null
    }

    // 保存根的属性
    this.root = null
    
    BinarySerachTree.prototype.insert = function (key) {
        // 1.根据key创建对应的node
        var newNode = new Node(key)

        // 2.判断根节点是否有值
        if (this.root === null) {
            this.root = newNode
        } else {
            this.insertNode(this.root, newNode)
        }
    }
    
     BinarySerachTree.prototype.insertNode = function (node, newNode) {
        if (newNode.key < node.key) {
            if (node.left === null) {
                node.left = newNode
            } else { 
                this.insertNode(node.left, newNode)
            }
        } else {
            if (node.right === null) {
                node.right = newNode
            } else {
                this.insertNode(node.right, newNode)
            }
        }
    }
}

var bst = new BinarySerachTree()

// 插入数据
bst.insert(18)
bst.insert(9)
bst.insert(24)
bst.insert(6)
bst.insert(7)
bst.insert(3)
bst.insert(14)
bst.insert(10)
bst.insert(15)
bst.insert(26)
bst.insert(25)

3测试结果

console.log(bst)

打印结果如下列图:

再展开一些:

可以看出 根节点是18 ,第一层左节点是9 右节点是24 ,9节点左右节点分别为6 14,接下来再展开6和14两个节点,看看是不是左右分别为3 7 , 10 15

再把根节点的右子树全部展开看看

由此可见,与最顶部的图是一致的。

4 解析代码

  • 定义root属性,第一个插入的节点作为二分搜索树的根。
  • 再插入节点时候,与根节点对比,比根节点小就作为根节点的左节点,反之为右节点。
  • 之后再插入节点时候,先是与根节点对比,比如第三次插入的是6 比根节点18小,然后就与18的左子节点9对比,发现也比9小,就成为了9的左子节点。总结规律:(1)对比大小(2)小就成为左子节点,大就成为右子节点(3)成为子节点的前提是,原父节点并没有左或右子节点
  • 把上述规律抽象一下,就是递归了。递归的结束条件是,父节点的左或者右子节点为空。

5 递归

总有人说递归很难想明白是怎么调用的。也有人说,递归的真谛就是,不要去想他是怎么调用的。不过我在之前看函数调用栈的说明后,有点恍然大悟的感觉,我要把函数调用栈记录一下。

函数a内部调用函数b,函数b内部调用函数c,函数c内部调用函数d。 问,怎么样算是a执行完毕? 这里不妨用简单的数据结构,栈,来说明一下。

  • 1 函数a执行,把函数a压入到执行栈中。如下图

  • 2 a执行过程,内部又有函数b,那么函数b又会压入到执行栈中。如下图

  • 3 同理 ,b函数执行时候,又会c压栈,函数d同理 最后是这样

  • 4 函数a怎么才算执行完? 当然是bcd都执行完才是a执行完。d最后压入栈,d不执行完不会出栈,d不出栈,c不会称为执行完。只有bdc都出栈了,最后才算作a执行完。
  • 5 不知道这么来想递归,是不是直观了一点。