JavaScript中,二叉树的三种遍历,及查找最小/大值,指定值,删除指定节点

本文介绍了如何使用JavaScript实现二叉树的前序、中序和后序遍历,以及查找最小值、最大值和指定值的逻辑。在查找过程中,若值存在则返回true,不存在则返回false。文章还提及了删除节点的复杂性,并强调要保持二叉树的结构。详细代码中包含注释,便于理解递归调用过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们上一篇写了一个简易二叉树的创建。

学习二叉树的创建也是对经典的数据结构又有了一定的了解,而很多数据结构也是从二叉树演化而来的
我们在看一次这种图

在这里插入图片描述

而我们学习创建二叉树的主要目的还是进行遍历,查找,操作这三大点。
那我们这次就先从遍历,查找开始
首先是三种遍历逻辑

重点!递归调用时 一开始传参的node为根节点,后面则会依次传入node.left,node.right !!下面的话语根节点也可能是node.right/left

遍历逻辑(比较抽象,因为是递归调用)
前序遍历从根节点开始,打印当前节点,然后递归遍历左子树,然后打印当前节点,在递归遍历,直到遍历到叶子节点后返回上一层递归,在遍历右子树,
中序遍历从根节点开始,如果有左孩子,则递归调用左孩子,然后没有就返回上一层打印节点,然后遍历右节点,中序遍历最后的输出结果为正序排序。
后序遍历从跟节点开始,首先递归遍历左节点,直到为叶子节点,然后返回上一层在递归调用右节点,直到为叶子节点为止,然后返回上一层输出当前节点。这种方法根节点为最后输出。

最小/大值逻辑

首先我们从二叉树的创建就能看出,小节点在左边,那我们则可以这样,如果有左节点,则用循环一直访问当前节点的左节点,知道为null,此时当前节点的值就是最小值,最大值相反即可。
方法为min/max

查找指定值逻辑

比如我们查找一个在二叉树存在的值:1,

我们则先和根节点的值比较,如果小于当前跟节点则向左遍历,大于当前跟节点则向右遍历,如果等于则返回true,
这个时候我们查找一个不存在的值通过chrome最后可以看到root.node == null的情况,此时我们加个判断return false就可以了

删除节点(这个比较麻烦)还要保证删除节点后还是二叉树的数据结构。

有几种情况

实现逻辑
叶子节点左右节点为空这种就是直接赋值为null就行了
兄弟节点有左边或者右边有节点比如删除的为上图中的10,然后此时左子树为空,我们就此时将14的右子树赋值给根节点。
兄弟节点左右都有节点比如上面的图我们删除节点3的值,然后我们需要从比他大的右子树找一个最小值,赋值给节点3,然后将找到的最小值删除

我们还是直接看代码吧。。。

callback 只是一个函数,作用:输出节点的值;

代码中有注释

看指定的方法时将其方法中的debugger和调用打开在chrome运行即可,主要是看递归调用时root的作为参数传入的变化和递归执行顺序。

       class BinaryNode {
            constructor(node) {
                this.node = node
                this.right = null
                this.left = null
            }
        }

        class BinaryTree { 
            constructor() {
                this.root = null
            }
            insert(newNode) {
                // debugger
                var newNode = new BinaryNode(newNode)
                if (this.root) {
                    this.insertNode(this.root, newNode)
                } else {
                    this.root = newNode
                }
            }
            insertNode(node, newNode) {
                // debugger
                if (node.node > newNode.node) {
                    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)
                    }
                }
            }
         
            // 前序遍历
            preOrderTraverse(callback) {
                debugger
                this.preOrderTraverseNode(this.root, callback);
            }
            preOrderTraverseNode(node, callback) {
                debugger
                if (node !== null) {
                    callback(node.node)
                    this.preOrderTraverseNode(node.left, callback)
                    this.preOrderTraverseNode(node.right, callback)
                }
            }

            // 中序遍历
            inOrderTraverse(callback) {
                // debugger
                this.inOrderTraverseNode(this.root, callback)
            }

            inOrderTraverseNode(node, callback) {
                // debugger
                if (node !== null) {
                    this.inOrderTraverseNode(node.left, callback)
                    callback(node.node)
                    this.inOrderTraverseNode(node.right, callback)
                }
            }
            

            // 后序遍历
            postOrderTraverse(callback) {
                // debugger
                this.postOrderTraverseNode(this.root, callback)
            }
            postOrderTraverseNode(node, callback) {
                // debugger
                if (node !== null) {
                    this.postOrderTraverseNode(node.left, callback) 
                    this.postOrderTraverseNode(node.right, callback)
                    callback(node.node)
                }
            }

            // 最小值
            min() {
                // debugger
                return this.minNode(this.root)
            }
            minNode(root) {
                // debugger
                if (root.left !== null) {
                    // debugger
                    while(root && root.left) {
                        root = root.left
                    }
                    return root.node
                }
                return root.node
            }
            // 最大值
            max() {
                // debugger
                return this.maxNode(this.root)
            }
            maxNode(root) {
                // debugger
                if(root.right !== null) {
                    while(root && root.right) {
                        root = root.right
                    }
                    return root.node
                }
                return root.node
            }
            // 查找一个指定node
            search(node) {
                // debugger
                return this.searchNode(this.root, node)
            }
            searchNode(root, node) {
                // debugger
                if (root === null ) {
                    return false
                }
                if (root.node > node) {
                    return this.searchNode(root.left, node)
                } else if (root.node < node) {
                    return this.searchNode(root.right, node)
                } else {
                    return true
                }
            }
            remove(node) {
                debugger
                this.removeNode(this.root, node)
            }
            removeNode(root, node) {
                debugger
                if (root === null) {
                    return null
                }
                if (root.node > node) {
                    root.left = this.removeNode(root.left, node)
                    return root
                } else if (root.node < node) {
                    root.right = this.removeNode(root.right, node)
                    return root
                } else {
                    if (root.left === null && root.right === null) {
                        root = null
                        return root
                    }
                    if (root.left === null) {
                        root = root.right
                        return root
                    } else if (root.right === null) {
                        root = root.left
                        return root
                    }
                    var aux = this.findMinNode(root.right)
                    root.node = aux.node
                    root.right = this.removeNode(root.right, aux.node)
                    return root
                }
            }
            findMinNode(root) {
                if (root) {
                    while(root && root.left !== null) {
                        root = root.left
                    }
                    return root
                }
                return null
            }
        }
        var nodes = [8, 3,10, 1, 6, 14, 4, 7, 13]
        var binaryTree = new BinaryTree()
        nodes.forEach(node => {
            binaryTree.insert(node)
        })

        console.log(binaryTree.root)
        var callback = function(node) {
            console.log(node)
        }

        // 如果需要哪个代码则打开注释和方法中的debugger即可,打开一个要把不需要看的注释,

        // 先序遍历
        binaryTree.preOrderTraverse(callback) //例如这条打开,这个方法中已经打好的debugger打开, 多看一遍函数的执行顺序和当前值,就好了。
        // 中序遍历
        // binaryTree.inOrderTraverse(callback)
        // 后序遍历
        // binaryTree.postOrderTraverse(callback)
        console.log(
        //     `最小值是:${binaryTree.min()}`,
        //     `最大值是:${binaryTree.max()}`,
        )
        console.log(
            // binaryTree.search(1) ? "search num 1 is fount" : "search num 1 is not found",
            // binaryTree.search(15) ? "search num 15 is fount" : "search num 15 is not found",
        )
        // binaryTree.remove(1)
        // binaryTree.remove(3)
        // binaryTree.remove(10)
        // console.log(binaryTree.root)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值