• 算法框架之二叉树扩展&二叉搜索树


    二叉树基础遍历 在上一章以解释过 算法框架之数组&链表&二叉树

    二叉树扩展

    【如何判断两棵二叉树是否完全相同?

    先来道开胃菜 应该很好理解 一共会出现三种情况【空的情况(都空+一个空)+非空情况+递归】

    /**
     * Definition for ListNode.
     * function ListNode (val) {
     *     this.val = val;
     *     this.next= null;
     * }
     */
    /**
     * @param {ListNode } root1
     * @param {ListNode } root2
     */
     */
    function issame(root1,root2){
    //如果两结点都为空 必然相同
        if(root1 == nul l&& root2 == null)
            return true
    //【经过上一个条件 没有return的话 说明至少一个不为空,因此还得排除 一个空一个不空的情况】
    //如果一个空一个不空 则必不同
        if(root1 != null || root2 != null)
            return false
    // 【上两个条件排除掉空的情况 因此接下来必然有值】
    //遇到值不同时 也是表明是不同的树
        if(root1.val != root2.val)
            return false
        return issame(root1.left,root2.left)&&issame(root1.right,root2.right)
    }

    二叉搜索树

    1.在谈论写法前 先必须知道其定义吧

    二叉搜索树(Binary Search Tree,简称 BST)是一种很常用的的二叉树。它的定义是:一个二叉树中,任意节点的值要大于等于左子树所有节点的值,且要小于等于右边子树的所有节点的值。

    【下图就是一个二叉搜索树】

     2.在书写判定二叉搜索树时,很容易进入一个误区

    可能想通过上面的【二叉树框架】+【二叉搜索树定义】依葫芦画瓢 搞一个出来 代码如下

    function isValidBST(root) {
        if (root == null) return true;
        if (root.left != null && root.val <= root.left.val) return false;
        if (root.right != null && root.val >= root.right.val) return false;
    
        return isValidBST(root.left)&& isValidBST(root.right);
    }

    看似十分正确!满足【每一个子树】 左<根<右 的要求 下图即满足写的这个算法 但明显不满足【二叉搜索树的定义】! (右侧的子树应该也都大于结点 但6与根10不满足)

     是否是框架不适用了?亦或者是开头就想错了? 并不!!只需稍作修改即可

    先分析为什么不满足情况?

    因为 只考虑了子树结点情况 ,并没考虑之前的根节点情况  因此只需 将其记录 每一项的【最大值/最小值】即可

    /**
     * Definition for a binary tree node.
    * function TreeNode(val) {
    * this.val = val;
    * this.left = this.right = null;
    * }
    */ /** * @param {TreeNode} root */ function isValidBST(root) { return isValidBST(root, null, null); } function isValidBST(root, min, max) { if (root == null) return true; if (min != null && root.val <= min.val) return false; if (max != null && root.val >= max.val) return false; return isValidBST(root.left, min, root)&& isValidBST(root.right, root, max); }

     

    3.二叉搜索树找值

     先来看看普通的树如何找值呢?

    function find(root,target) {
        if(root==null)
           return false
        if(root.val==target)
    //找到的操作 
           return true
        return find(root.left,target)||find(root.right,target)
    }

     那在对二叉搜索树找值时 是否有好的方法呢? 或者说利用【二叉树的特性】

    function find(root, target) {
        if (root == null) 
            return false;
        if (root.val == target)
            return true;
        if (root.val < target) 
            return find(root.right, target);
        if (root.val > target)
            return find(root.left, target);
    }

    4. 二叉搜索树之查 框架

    由上述2,3点+【二叉搜索树定义】可得框架

    /**
     * Definition for a binary tree node.
     * function TreeNode(val) {
     *     this.val = val;
     *     this.left = this.right = null;
     * }
     */
    /**
     * @param {TreeNode} root
     * @param {Number} target
     */
    function BST(root, target) {
        if (root.val == target)
            // 找到目标,做点什么
        if (root.val < target) 
            BST(root.right, target);
        if (root.val > target)
            BST(root.left, target);
    }

    5. 二叉搜索树之增 框架

    说到底 就是【二叉搜索树之查】的修改版 => 先查到位置 再新建结点 加入即可

    注:一般增加操作要求返回根结点

    function insertIntoBST(root, val) {
        // 找到空位置插入新节点
        if (root == null) 
            return new TreeNode(val);
        // if (root.val == val)
        //     BST 中一般不会插入已存在元素
        if (root.val < val) 
            root.right = insertIntoBST(root.right, val);
        if (root.val > val) 
            root.left = insertIntoBST(root.left, val);
        return root;
    }

    6. 二叉搜索树之删 框架

    删除是最麻烦的一个操作 要分三种情况【无孩子】【有一个孩子】【有左右孩子】

    1、无孩子

    十分方便 只需将其删除即可

    if (root.left == null && root.right == null)
        return null;

    2、有一个孩子

    将其替代之前的位置

     

    // 排除了情况 1 之后
    if (root.left == null) return root.right;
    if (root.right == null) return root.left;

    3、有两个孩子

    此种情况最为麻烦:

      1.删除本值,寻找左子树的最大值/右子树的最小值,替换位置

     由于只需替换一种 此处用替换左子树最大值为例:

    if (root.left != null && root.right != null) {
        // 找到左子树的最大节点
        var maxNode = getMax(root.left);
        // 把 root 改成 maxNode 
        root.val = maxNode .val;
        // 转而去删除 maxNode 
        root.left= deleteNode(root.left, maxNode.val);
    }

    4、 整体【二叉搜索树之删】框架

    function deleteNode(root, int key) {
        if (root == null) return null;
        if (root.val == key) {
            // 这两个 if 把情况 1 和 2 都正确处理了
            if (root.left == null) 
                 return root.right;
            if (root.right == null) 
                 return root.left;
            // 处理情况 3
            var maxNode = getMax(root.left);
            root.val = maxNode.val;
            root.left= deleteNode(root.left, maxNode .val);
        } else if (root.val > key) {
            root.left = deleteNode(root.left, key);
        } else if (root.val < key) {
            root.right = deleteNode(root.right, key);
        }
        return root;
    }
    //找左子树中的最大值【找左子树的最右下角的值】
    function getMax(node) {
        while (node.right!= null) 
            node = node.right;
        return node;
    }    
  • 相关阅读:
    <a>與<link>的區別
    103_linux如何安装mysql数据库?
    102_Centos7在虚拟机上开机时出现黑屏,怎么解决?
    101_war和war exploded的区别
    100_linux中passwd文件的用户解析
    099_linux基础命令三
    098_linux基本操作命令二
    097_linux如何配置jdk路径
    096_如何将linux的IP地址转换成静态ip地址?
    078_ip地址.DNS,子网掩码,网关分别是什么,又有什么作用?
  • 原文地址:https://www.cnblogs.com/cc123nice/p/12813777.html
Copyright © 2020-2023  润新知