二叉搜索树,Map,Set,LeetCode刷题

news2024/11/16 9:27:48

二叉搜索树,Map,Set

  • 1. 二叉搜索树
  • 2. 二叉搜索树的模拟实现
    • 1.1 插入操作
    • 1.2 查找操作
    • 1.3 删除操作
  • 3. 二叉搜索树时间复杂度分析
  • 4. TreeMap和TreeSet
  • 5. Map
    • 5.1 Map的常用方法
    • 5.2 Map.Entry<K,V>
  • 6. Set
    • 6.1 Set的常用方法
  • LeetCode刷题
    • 1. 二叉搜索树与双向链表

1. 二叉搜索树

二叉搜索树是一棵特殊的树,它是“有序的”,因此又被叫做二叉排序树,它具有以下的性质:

  • 根节点左子树的任意元素都小于根节点的元素
  • 根节点右子树的任意元素都大于根节点的元素
  • 上述两条性质对于该树的任意子树都成立

2. 二叉搜索树的模拟实现

待实现代码:

public class BinarySearchTree {

    static class TreeNode {
        public int key;
        public TreeNode left;
        public TreeNode right;

        TreeNode(int key) {
            this.key = key;
        }
    }

    public TreeNode root;

    /**
     * 插入一个元素
     * @param key
     */
    public boolean insert(int key) {
        
        return true;
    }
    //查找key是否存在
    public TreeNode search(int key) {
      
        return null;
    }
    //删除key的值
    public boolean remove(int key) {
       
        return false;
    }
}

1.1 插入操作

插入一个新节点,首先要遍历原树,找到一个合适的位置去插入,而插入的节点会成为新树的叶子节点

具体实现如下:

    public boolean insert(int key) {
        if(root == null) {
            root = new TreeNode(key);
            return true;
        }
        TreeNode node = new TreeNode(key);
        TreeNode cur = root;
        TreeNode curParent = null;
        //找插入新节点的合适位置
        while(cur != null) {
            curParent = cur;
            if(cur.key < key) {
                cur = cur.right;
            }else if(cur.key > key) {
                cur = cur.left;
            }else {
                return false;
            }
        }
        //进行插入新节点操作
        if(curParent.key < key) {
            curParent.right = node;
        }else {
            curParent.left = node;
        }
        return true;
    }

1.2 查找操作

    public TreeNode search(int key) {
        TreeNode cur = root;
        while(cur != null) {
            if(cur.key < key) {
                cur = cur.right;
            }else if(cur.key > key) {
                cur = cur.left;
            }else {
                return cur;
            }
        }
        return null;
    }

1.3 删除操作

二叉搜索树的删除操作是三个操作里最难的,难在需要考虑的情况较多,需要不断用测试用例去调试代码,可以用下面这个链接去验证代码是否还有遗漏的情况

题目链接:NC297 删除一个二叉搜索树中的节点

实现代码:

    public boolean remove(int key) {
        TreeNode cur = root;
        TreeNode curParent = root;
        //找到删除节点位置
        while(cur != null) {
            if(cur.key < key) {
                curParent = cur;
                cur = cur.right;
            }else if(cur.key > key) {
                curParent = cur;
                cur = cur.left;
            }else {
                break;
            }
        }
        if(cur == null) {
            return true;//节点不存在
        }
        TreeNode del = cur;//待删除节点
        TreeNode delParent = curParent;//待删除节点的父亲节点
        //找到待删除节点左子树的最大值(即左子树最右边的元素),用来替换法1待删除节点值
        if(del.left == null) {//待删除节点无左子树
            if(del.key > delParent.key) {
                delParent.right = del.right;
            }else if(del.key < delParent.key){
                delParent.left = del.right;
            }else {
                //此时,待删除节点为根节点
                root = root.right;
            }
        }else {
            //找到待删除节点左子树的最大值(即左子树最右边的元素),用来替换待删除节点值
            curParent = cur;
            cur = cur.left;
            while(cur.right != null) {
                curParent = cur;
                cur = cur.right;
            }
            del.key = cur.key;
            if(curParent == del) {
                //此时,待删除节点的左子树根节点无右子树
                curParent.left = cur.left;
            }else {
                curParent.right = cur.left;
            }
        }
        return true;
    }

3. 二叉搜索树时间复杂度分析

  • 在最优情况下,即二叉搜索树是一棵完全二叉树,时间复杂度是O(log2N)
  • 在最坏情况下,即二叉搜索树是一棵单支二叉树,时间复杂度是O(N)

最优情况:
在这里插入图片描述
最坏情况:
在这里插入图片描述

4. TreeMap和TreeSet

TreeMap和TreeSet底层都是一棵红黑树,而红黑树是一棵近似平衡的二叉搜索树。TreeMap是Map接口的一个实现类,TreeSet是Set接口的一个实现类

5. Map

Map是一个接口,其实现需要依靠TreeMap类或者HashMap类。Map里存储的是<K,V>结构的键值对,并且K一定是唯一的,不能重复。这就类比于一个集合,这个集合里放的都是具有两个元素的集合,例如:{{“abc”, 2}, {“cde”, 3}}

5.1 Map的常用方法

  1. V put (K key, V value)
    用于往map中存放键值对

演示1:

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("fbc",2);
        map.put("cde",3);
        map.put("abc",5);
        map.put("grh",8);
        System.out.println(map);//Map类可以直接输出
    }
}

输出结果:
在这里插入图片描述
演示2:
在这里插入图片描述
map类存储的key是不能重复的,但往map里put同一个key,是可以的,只是在key里依然只会保存一个key,只是key对应的value会发生更新

  • 如果key不存在,会将key-value的键值对插入到map中,返回null
  • 如果key存在,会使用value替换原来key所对应的value,返回旧value
  • put(key,value): 注意key不能为空,但是value可以为空。 key如果为空,会抛出空指针异常
  1. V get(Object key)
    用于得到key对应的value

演示:

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("fbc",2);
        map.put("cde",3);
        map.put("abc",5);
        map.put("grh",8);
        Integer val = map.get("cde");
        System.out.println(val);
    }
}

输出结果为:3

注意: 该方法接收返回值时,建议使用包装类而不是基本数据类型,因为使用基本数据类型会发生自动拆箱,会调用intValue方法,假如该key不存在,就会返回null,这时如果进行拆箱的话,就会出现空指针异常
在这里插入图片描述
在这里插入图片描述
3. V getOrDefault(Object key, V defaltValue)
该方法与get方法的不同之处在于有一个默认值,如果key存在,则返回key对应的value值;如果key不存在,就会返回这个默认值

演示:

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("fbc",2);
        map.put("cde",3);
        map.put("abc",5);
        map.put("grh",8);
        Integer val = map.getOrDefault("cde2",-1);
        System.out.println(val);
    }
}

输出结果为:-1

  1. V remove(Object key)
    删除key对应的映射关系

演示:

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("fbc",2);
        map.put("cde",3);
        map.put("abc",5);
        map.put("grh",8);
        System.out.println("删除前:" + map);
        map.remove("abc");
        System.out.println("删除后:" +map);
    }
}

输出结果:
在这里插入图片描述

  1. Set<K> keySet()
    返回所有的key的不重复集合,keySet()是将map中的key放在set中返回的

演示:

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("fbc",2);
        map.put("cde",3);
        map.put("abc",5);
        map.put("grh",8);
        // 打印所有的key
        Set<String> set = map.keySet();
        System.out.println(set);
        for(String s : set) {
            System.out.print(s + " ");
        }
    }
}

输出结果:
在这里插入图片描述

  1. Collection<V> values()
    返回所有value的可重复集合,values()是将map中的value放在collect的一个集合中返回的

演示:

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("fbc",2);
        map.put("cde",3);
        map.put("abc",5);
        map.put("grh",8);
        // 打印所有的value
        Collection<Integer> collection = map.values();
        System.out.println(collection);
        for(Integer x: collection) {
            System.out.print(x + " ");
        }
    }
}

输出结果:
在这里插入图片描述

  1. boolean containsKey(Object key)
    判断是否包含key

演示:

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("fbc",2);
        map.put("cde",3);
        map.put("abc",5);
        map.put("grh",8);
        boolean flg1 = map.containsKey("abc");
        boolean flg2 = map.containsKey("cba");
        System.out.println(flg1);
        System.out.println(flg2);
    }
}

输出结果:
在这里插入图片描述

  1. boolean containsValue(Object value)
    判断是否包含value

演示:

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("fbc",2);
        map.put("cde",3);
        map.put("abc",5);
        map.put("grh",8);
        boolean flg1 = map.containsValue(1);
        boolean flg2 = map.containsValue(3);
        System.out.println(flg1);
        System.out.println(flg2);
    }
}

输出结果:
在这里插入图片描述

  1. Set<Map.Entry<K, V>> entrySet()
    返回所有的 key-value 映射关系,entrySet()将Map中的键值对放在Set中返回了

注意:

  • Map中键值对的Key不能直接修改,value可以修改,如果要修改key,只能先将该key删除掉,然后再来进行重新插入
  • 在TreeMap中插入键值对时,key不能为空,否则就会抛NullPointerException异常,因为插入键值对时,会在二叉搜索树里进行比较(因此插入的key元素类型要可比,或者在key类中实现了比较方式),将新节点插入到合适位置,而value可以为空。但是HashMap的key和value都可以为空,因为插入时不涉及比较。因此,输出时,如果是TreeMap实现的,则是有序的;若是HashMap实现的,则是无序的

5.2 Map.Entry<K,V>

Map.Entry<K, V> 是Map内部实现的用来存放<key, value>键值对映射关系的内部类,该内部类中主要提供了<key, value>的获取,value的设置以及Key的比较方式

  1. K getKey()
    返回entry中的key

  2. V getValue()
    返回entry中的value

  3. V setValue(V value)
    将键值对中的value值替换成指定value

通过该方法转化,既可以获取key,也可以获取value;而Map中的get方法只能获取key所对应的value值

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("fbc",2);
        map.put("cde",3);
        map.put("abc",5);
        map.put("grh",8);
         打印所有的键值对
        Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
        System.out.println(entrySet);
        System.out.println("========");
        for (Map.Entry<String,Integer> entry:entrySet) {
            System.out.println("key:" + entry.getKey()+" val:" + entry.getValue());
        }
    }
}

输出结果:
在这里插入图片描述

6. Set

Set与Map主要的不同有两点:Set是继承自Collection的接口类,Set中只存储了Key,且Key唯一。Set类似于一个集合,具有互异性,最大的作用就是去重。Set的实现依靠TreeSet、HashSet,还有一个LinkedHashSet,LinkedHashSet是在HashSet的基础上维护了一个双向链表来记录元素的插入次序。

6.1 Set的常用方法

  1. boolean add(E e)
    用来给集合添加元素,但不会添加重复元素

演示1:

    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<>();
        set.add(4);
        set.add(7);
        set.add(1);
        set.add(3);
        System.out.println(set);
    }

输出结果:
在这里插入图片描述

演示2:

    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<>();
        set.add(1);
        set.add(7);
        set.add(1);
        set.add(3);
        System.out.println(set);
    }

输出结果

在这里插入图片描述
和Map类似,Set也可以add集合中已有的元素,但不会将其加入集合中,从而达到去重的效果

  1. void clear()
    清空集合中的元素
    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<>();
        set.add(4);
        set.add(7);
        set.add(1);
        set.add(3);
        System.out.println(set);
        set.clear();
        System.out.println(set);
    }

输出结果:
在这里插入图片描述

  1. boolean contains(Object o)
    判断o是否在集合中
    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<>();
        set.add(4);
        set.add(7);
        set.add(1);
        set.add(3);
        System.out.println(set);
        System.out.println(set.contains(4));
        System.out.println(set.contains(5));
    }

输出结果:
在这里插入图片描述

  1. Iterator iterator()
    返回迭代器
    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<>();
        set.add(4);
        set.add(7);
        set.add(1);
        set.add(3);
        Iterator<Integer> it = set.iterator();
        while(it.hasNext()) {
            System.out.print(it.next()+" ");
        }
    }

输出结果:
在这里插入图片描述

  1. boolean remove(Object o)
    删除集合中的o
    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<>();
        set.add(4);
        set.add(7);
        set.add(1);
        set.add(3);
        System.out.println(set);
        set.remove(4);
        System.out.println(set);
    }

输出结果:
在这里插入图片描述

  1. int size()
    返回set中的元素个数
    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<>();
        set.add(4);
        set.add(7);
        set.add(1);
        set.add(3);
        System.out.println(set.size());
    }

在这里插入图片描述

  1. boolean isEmpty()
    判断集合set是否为空,为空则返回true,反之返回false
    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<>();
        System.out.println(set.isEmpty());
        set.add(4);
        set.add(7);
        set.add(1);
        set.add(3);
        System.out.println(set.isEmpty());
    }

输出结果:
在这里插入图片描述

  1. Object[] toArray()
    将set中的元素转换为数组返回
    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<>();
        set.add(4);
        set.add(7);
        set.add(1);
        set.add(3);
        System.out.println(Arrays.toString(set.toArray()));
        System.out.println("========");
        Object[] arr = set.toArray();
        for (Object o : arr) {
            System.out.print(o + " ");
        }
    }

输出结果:
在这里插入图片描述

  1. boolean containsAll(Collection<?> c)
    检查集合c中的元素是否在set中全部存在,是则返回true,否则返回false
    public static void main(String[] args) {
        Collection<Integer> c = new ArrayList<>();
        c.add(1);
        c.add(2);
        c.add(3);
        Set<Integer> set = new TreeSet<>();
        set.add(1);
        set.add(2);
        System.out.println(set.containsAll(c));
        set.add(3);
        System.out.println(set.containsAll(c));
    }

输出结果:
在这里插入图片描述

  1. boolean addAll(Collection<?extends E> c)
    将集合c中的元素添加到set中,可以达到去重的效果
    public static void main(String[] args) {
        Collection<Integer> c = new ArrayList<>();
        c.add(1);
        c.add(2);
        c.add(1);
        c.add(3);
        c.add(2);
        c.add(4);
        System.out.println(c);
        Set<Integer> set = new TreeSet<>();
        set.addAll(c);
        System.out.println(set);
    }

输出结果:
在这里插入图片描述

注意:

  • Set中的Key不能修改,如果要修改,先将原来的删除掉,然后再重新插入
  • TreeSet中不能插入null的key,若插入null,则会抛出空指针异常;而HashSet可以

LeetCode刷题

1. 二叉搜索树与双向链表

题目链接:将二叉搜索树转化为排序的双向链表

解题思路:

  1. 对该二叉搜索树采取中序遍历,先找到二叉搜索树最左边的节点
  2. 定义两个引用prev和head,prev用来引用当前pRootOfTree的前一个节点,head始终引用原二叉搜索树最左边的节点,用于返回转化成的双向链表

代码如下:

public class Solution {
    public TreeNode prev;
    public TreeNode head;
    public TreeNode Convert(TreeNode pRootOfTree) {
        if (pRootOfTree == null) {
            return null;
        }
        Convert(pRootOfTree.left);
        if (prev == null) {
            prev = pRootOfTree;
            head = pRootOfTree;
        } else{
            prev.right = pRootOfTree;
            pRootOfTree.left = prev;
            prev = pRootOfTree;
        }
        Convert(pRootOfTree.right);
        return head;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1967082.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Total Eclipse 挑战赛:在以太坊首个 SVM L2 上开发应用

摘要&#xff1a;Eclipse 基金会宣布了其首届黑客马拉松计划&#xff0c;即"The Total Eclipse Challenge"&#xff0c;作为一场独一无二的黑客松活动 &#xff0c;邀请了优秀的开发者们在链上开发创新的应用。 "The Total Eclipse 挑战赛" 是一项为期两周…

如何更好地做出判断?

笛卡尔有句名言&#xff1a;无法下判断的人&#xff0c;不是欲望太奢侈&#xff0c;就是觉悟还不够。 这里说的判断&#xff0c;其实也就是选择。我们人生面临着各种维度的选择&#xff0c;大到人生方向&#xff0c;小到一顿饭吃什么&#xff0c;可以说&#xff0c;选择伴随着我…

全志T113i移植LAN8720指南

1、根据硬件修改设备树 gmac0_pins_a: gmac0 {allwinner,pins "PG0", "PG1", "PG2", "PG3", "PG4","PG5", "PG11", "PG12", "PG13", "PG14", "PG15";allwin…

vue3+TS+nest+mysql实现网站访问统计系统

网站采用了vue3tsnestmysql的技术选型&#xff0c;目前初步实现第一版开发 访问地址&#xff1a;点我进入网站 网站访问统计 主要通过插入script来调用上传接口来实现数据统计,目前仅存储了用户的ip和访问时间&#xff0c;后期也可根据ip来获取用户的城市信息 async pageUplo…

探索TinyDB的轻量级魅力:Python中的微型数据库

文章目录 探索TinyDB的轻量级魅力&#xff1a;Python中的微型数据库背景&#xff1a;为何选择TinyDB&#xff1f;什么是TinyDB&#xff1f;如何安装TinyDB&#xff1f;5个简单的库函数使用方法3个场景下的应用实例常见问题与解决方案总结 探索TinyDB的轻量级魅力&#xff1a;Py…

社区志愿服务管理平台小程序/社区志愿者管理系统

获取源码联系方式请查看文章结尾&#x1f345; 摘 要 随着当今网络的发展&#xff0c;时代的进步&#xff0c;各行各业也在发生着变化&#xff0c;于是小程序也逐步进入人们的生活&#xff0c;给我们生活或者工作提供了新的方向新的可能。 本毕业设计的内容是设计实现一个基…

芯片解密技术可以应用在哪些领域?

芯片解密技术可以在以下一些领域得到应用&#xff1a; 电子产品维修&#xff1a;对于一些老旧或难以获取原厂技术支持的设备&#xff0c;通过解密芯片获取程序代码可以更有效地进行故障诊断和维修。技术研究和学习&#xff1a;帮助科研机构和技术人员深入了解先进芯片的设计和工…

python绘图 | 横坐标是日期,纵坐标是数值

需求 profit_value [0.084, 0.225, 0.234, 0.264, 0.328] time_stamp [20221111, 20230511, 20230704, 20231212, 20240315] 横坐标是日期&#xff0c;纵坐标是数值&#xff0c;我想绘图的时候&#xff0c;横坐标是按日期格式来 代码 from matplotlib import pyplot as pl…

黄水与酿好酒有啥关系?

执笔 | 敏 敏 编辑 | 古利特 上个世纪&#xff0c;白酒泰斗周恒刚先生曾到四川考察&#xff0c;不禁感慨四川生产浓香型白酒占尽天时、地利、人和&#xff0c;其中“黄水”尤为特别。 “黄水”与酿好酒有何关系&#xff1f;,长江酒道,4分钟 近期&#xff0c;五粮液科研团队联…

word预览方式---插件,vue-office-docx、docx-preview、mammoth.js

提示&#xff1a;word预览方式—插件 文章目录 [TOC](文章目录) 前言一、vue-office-docx二、docx-preview三、mammoth.js总结 前言 word预览 一、vue-office-docx npm install vue-office-docx -S-DofficeDocx.vue <template><div class"preview_box">…

前端面试题整理-HTML

1. 从用户输入 url 到页面展示发生了什么&#xff1f; &#xff08;1&#xff09;首先进行url合法性校验&#xff1a;包括协议域名端口号 &#xff08;2&#xff09;进行强缓存判断&#xff0c;判断本地缓存是否已经存在需要的资源文件&#xff0c;存在直接使用本地缓存即可 &…

无捆绑软件!Windows7纯净版镜像等你来下载!

在电脑操作中&#xff0c;很多用户都喜欢纯净版操作系统&#xff0c;但不知道在哪里可以下载到没有捆绑软件的Windows7纯净版系统&#xff1f;接下来系统之家小编给大家带来最新的Windows7纯净版镜像&#xff0c;这些镜像文件经过优化&#xff0c;不包含捆绑软件&#xff0c;安…

零基础学习【Mybatis】这一篇就够了

Mybatis 查询resultType使用resultMap使用单条件查询多条件查询模糊查询返回主键 动态SQLifchoosesetforeachsql片段 配置文件注解增删改查结果映射 查询 resultType使用 当数据库返回的结果集中的字段和实体类中的属性名一一对应时, resultType可以自动将结果封装到实体中 r…

react高级组件ProForm实现输入框搜索

实现界面 <Col span{12}><ProForm.Itemname"name"label"推荐用户"><AutoCompleteclassName"pro-field pro-field-md"placeholder"请输入用户名"options{NameArr}onSearch{debounce(searchUser, 500)}onSelect{onSelect…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第四篇 嵌入式Linux系统移植篇-第七十三章内核添加网卡驱动

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

有趣的PHP小游戏——猜数字

猜数字 这个游戏会随机生成一个1到100之间的数字&#xff0c;然后你需要猜测这个数字是什么。每次你输入一个数字后&#xff0c;程序会告诉你这个数字是“高了”还是“低了”&#xff0c;直到你猜对为止&#xff01; 使用指南&#xff1a; 代码如下&#xff0c;保存到一个p…

大模型卷入医学图像!PFPs:使用大型视觉和语言模型的提示引导灵活病理分割,用于多样化潜在结果

PS&#xff1a;写在前面&#xff0c;近期感谢很多小伙伴关注到我写的论文解读&#xff0c;我也会持续更新吖~同时希望大家多多支持本人的公主号~ 想了解更多医学图像论文资料请移步公主&#x1f478;号哦~~~后期将持续更新&#xff01;&#xff01; 关注我&#xff0c;让我们一…

【嵌入式】STM3212864点阵屏使用SimpleGUI单色屏接口库——(2)精简字库

一 开源库简介与移植 最近一个项目需要用12864屏幕呈现一组较为复杂的菜单界面&#xff0c;本着不重复造轮子的原则找到了SimpleGUI开源库。 开源地址&#xff1a;SimpleGUI: 一个面向单色显示屏的开源GUI接口库。 SimpleGUI是一款针对单色显示屏设计的接口库。相比于传统的GUI…

kali里面的vulhub靶场搭建

第一步&#xff1a;安装docker镜像容器 sudo apt install docker.io 第二步&#xff1a;开启docker镜像容器 先查看一下docker有没有下载成功 docker -v 再查看一下docker的运行状态 systemctl status docker 第三步&#xff1a;下载docker-compose环境 apt install do…

94 二叉树的中序遍历

解题思路&#xff1a; \qquad 首先理解中序遍历&#xff1a;left node——root——right node。 \qquad 中序遍历的起始点为该树最左边的非空元素。本题可以使用递归、DFS&#xff08;迭代&#xff09;解决。 递归法&#xff1a; \qquad 重复的基础操作&#xff1a;输出roo…