数据结构小白之二叉树的遍历和查找

2023-10-31

1.存储方式的分析

1.1 数组储存方式的分析

优点: 通过下标的访问,速度快,还可以使用二分法提高检索的速度

缺点: 如果要检索某个值,或者插入值。整个数组就会进行移动,从而造成较低的效率。同时如果需要扩容的话,从底层而言,每一次数组的扩容就要重新进行创建一个新的数组(参考ArrayList,底层维护了一个object类型的数组,所以它的添加操作效率不是很高)

 

1.2 链表存储方式的分析

优点: 在一定程度上对于数组做出优化(可以参考数据结构小白之链表),在进行插入和删除的时候只需要移动一个节点即可

缺点: 在检索具体的值时,效率依然比较低,比如在检索具体的值,需要从头节点进行遍历

 

1.3 树存储方式的分析

可以提高数据存储和读取的效率,比如利用二叉排序树,既可以保证数据的检索速度,也可以保证数据的插入,删除和修改的速度

 

2.二叉树

2.1 二叉树的特征

* 每一个节点最多只能有两个子节点(左子节点和右子节点)

* 如果二叉树的所有叶子节点都在最后一层,节点总数为 2*n-1(n为层数),称为满二叉树

* 如果二叉树的深度为k,除了第k层外,其他(1 到 k-1层节点都达到了最大值,且第k层所有的节点都连续集中在最左边,这样的树就是完全二叉树)

 

2.2 二叉树的遍历(核心在于递归)

二叉树的遍历分为前序,中序和后序遍历

前序遍历: 按照 根节点->左子节点->右子节点的顺序进行遍历

中序遍历: 按照 左子节点->根节点->右子节点的顺序进行遍历

后序遍历: 按照 左子节点->右子节点->根节点的顺序进行遍历


举个栗子

(1) 先去准备pojo(相应的树节点)

package tree_op;

import org.omg.CORBA.NO_IMPLEMENT;

//创建树的节点
public class HeroNode {
    private int no;
    
    private String name;
    private HeroNode left; //默认为null
    private HeroNode right;//默认为null

    //建立构造器
    public HeroNode(int no, String name) {
        this.no = no;
        this.name = name;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public HeroNode getLeft() {
        return left;
    }

    public void setLeft(HeroNode left) {
        this.left = left;
    }

    public HeroNode getRight() {
        return right;
    }

    public void setRight(HeroNode right) {
        this.right = right;
    }

    @Override
    public String toString() {
        return "HeroNode[" +
                "no=" + no +
                ", name='" + name + '\'' +
                ']';
    }

    

 

(2)开始进行前序遍历(根->左->右)

 //编写前序遍历的方法 根->左->右
    public void preOrder() {
        //输出父节点
        System.out.println(this);
        //递归向左
        if (this.left != null) {

            this.left.preOrder();
        }
        //递归向右子树遍历
        if (this.right != null) {
            this.right.preOrder();
        }
    }

(3)开始进行中序遍历(左->根->右)

 //编写中序遍历的方法 左->根->右
    public void infixOrder() {
        //递归向左
        if (this.left != null) {
            this.left.infixOrder();
        }
        //输出父节点
        System.out.println(this);
        //递归向右
        if (this.right != null) {
            this.right.infixOrder();
        }
    }

(4) 开始进行后序遍历(左->右->根)

 //编写后序遍历的方法 左->右->根
    public void postOrder() {
        //遍历向左
        if (this.left != null) {
            this.left.postOrder();
        }
        //遍历向右
        if (this.right != null) {
            this.right.postOrder();
        }
        //中
        System.out.println(this);
    }

注: 二叉树的三种遍历操作逻辑上而言非常简单,就是按照遍历顺序给出相应的代码即可,代码的重复度也很高(如果愿意的话可以把对左子树 根 右子树的操作抽离出来,然后在这使用的就是三个方法的排列...)

//对于左节点的操作(1)
     if(this.left != null) {
          this.left.postOrder();
        }

//对于右节点的操作(2)
 
     if(this.right != null) {
         this.right.postOrder();
     }

//对于根的操作(3)
System.out.println(this);



前序遍历 3-1-2

中序遍历 1-3-2

后序遍历 1-2-3

2.3 二叉树的查找(核心在于递归)

(1) 开始进行前序查找

  //编写前序查找方法
    //比较->左递归->右递归
    //如果找到了就返回该node,如果没有找到返回null
    public HeroNode preOrderSearch(int no) {
        HeroNode resNode = null;
        //比较当前节点是不是
        if (this.no == no) {
            return this;
        }
        //判断当前节点的左节点是否为空,如果不为空则进行左递归

        if (this.left != null) {
            resNode = this.left.preOrderSearch(no);
        }
        if (resNode != null) {
            return resNode;
        }
        //如果resNode为空,则判断右子节点情况
        if (this.right != null) {
            resNode = this.right.preOrderSearch(no);
        }
        return resNode;
    }

(2) 开始进行中序查找

//编写中序查找算法
    //左递归->比较->右递归
    public HeroNode infixOrderSearch(int no) {
        HeroNode resNode = null;
        //开始进左递归查找
        if (this.left != null) {
            resNode = this.left.infixOrderSearch(no);
        }
        if (resNode != null) {
            return resNode;
        }
        //如果找到,则返回,如果没有找到,就和当前节点比较
        if (this.no == no) {
            return this;
        }
        //否则进行继续向右进行中序查找
        if (this.right != null) {
            resNode = this.right.infixOrderSearch(no);
        }
        return resNode;
    }

(3)开始进行后序查找

 //后序遍历查找
    //左递归->右递归->中
    public HeroNode postOrderSearch(int no){
        //左递归
        HeroNode resNode=null;
        if(this.left!=null){
            resNode=this.left.postOrderSearch(no);
        }
        if(resNode!=null){
            return resNode;
        }
        //右递归
        if(this.right!=null){
            resNode=this.right.postOrderSearch(no);
        }
        if(resNode!=null){
            return resNode;
        }
        //中
        if(this.no==no){
            return this;
        }
        return resNode;
    }

注: 二叉树的查找算法也是几个小方法的重复使用,依旧按照前序,中序,后序的不同,控制方法的调用时机

        //根节点操作 1

        if (this.no == no) {
            return this;
        }

        
        //左子节点操作 2
        
         if (this.left != null) {
            resNode = this.left.preOrderSearch(no);
        }
       

        //右子节点操作 3
        
         //如果resNode为空,则判断右子节点情况
        if (this.right != null) {
            resNode = this.right.preOrderSearch(no);
        }
       
        
        //判断resNode是否为null 4
         if (resNode != null) {
            return resNode;
        }
        
        //直接返回resNode (用于最后一轮判断) 5
        return resNode;

则 对于查找操作而言

1.前序查找: 1 2 4 3 5

2.中序查找: 2 4 1 3 5

3.后序查找  2 4 3 1 5

注: 这里仅仅给出了关于遍历和查找的核心代码,欢迎大家来我的github取完整代码:

https://github.com/Lzin/tree_structure/tree/master/src/tree_op

 

测试结果:

D:\lock\java\jdk\bin\java.exe -javaagent:D:\JetBrains\apps\IDEA-U\ch-0\183.5429.30\lib\idea_rt.jar=4988:D:\JetBrains\apps\IDEA-U\ch-0\183.5429.30\bin -Dfile.encoding=UTF-8 -classpath D:\lock\java\jdk\jre\lib\charsets.jar;D:\lock\java\jdk\jre\lib\deploy.jar;D:\lock\java\jdk\jre\lib\ext\access-bridge-64.jar;D:\lock\java\jdk\jre\lib\ext\cldrdata.jar;D:\lock\java\jdk\jre\lib\ext\dnsns.jar;D:\lock\java\jdk\jre\lib\ext\jaccess.jar;D:\lock\java\jdk\jre\lib\ext\jfxrt.jar;D:\lock\java\jdk\jre\lib\ext\localedata.jar;D:\lock\java\jdk\jre\lib\ext\nashorn.jar;D:\lock\java\jdk\jre\lib\ext\sunec.jar;D:\lock\java\jdk\jre\lib\ext\sunjce_provider.jar;D:\lock\java\jdk\jre\lib\ext\sunmscapi.jar;D:\lock\java\jdk\jre\lib\ext\sunpkcs11.jar;D:\lock\java\jdk\jre\lib\ext\zipfs.jar;D:\lock\java\jdk\jre\lib\javaws.jar;D:\lock\java\jdk\jre\lib\jce.jar;D:\lock\java\jdk\jre\lib\jfr.jar;D:\lock\java\jdk\jre\lib\jfxswt.jar;D:\lock\java\jdk\jre\lib\jsse.jar;D:\lock\java\jdk\jre\lib\management-agent.jar;D:\lock\java\jdk\jre\lib\plugin.jar;D:\lock\java\jdk\jre\lib\resources.jar;D:\lock\java\jdk\jre\lib\rt.jar;D:\java_algorithm\structure_code\tree_structure\out\production\tree_structure tree_op.BinaryTreeDemo
前序遍历:
HeroNode[no=1, name='p1']
HeroNode[no=2, name='p2']
HeroNode[no=3, name='p3']
HeroNode[no=5, name='p5']
HeroNode[no=4, name='p4']
========================
中序遍历:
HeroNode[no=2, name='p2']
HeroNode[no=1, name='p1']
HeroNode[no=5, name='p5']
HeroNode[no=3, name='p3']
HeroNode[no=4, name='p4']
========================
后序遍历:
HeroNode[no=2, name='p2']
HeroNode[no=5, name='p5']
HeroNode[no=4, name='p4']
HeroNode[no=3, name='p3']
HeroNode[no=1, name='p1']
========================
前序查找
查询到该节点的编号为5 该节点的名称为p5
========================
中序查找
查询到该节点的编号为4 该节点的名称为p4
========================
后序查找
未找到该结点

Process finished with exit code 0


 

 

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构小白之二叉树的遍历和查找 的相关文章

  • 算法:双指针

    双指针 双指针是一种思想或一种技巧并不是特别具体的算法 具体就是用两个变量动态存储两个结点 来方便我们进行一些操作 通常用在线性的数据结构中 特别是链表类的题目 经常需要用到两个或多个指针配合来记忆链表上的节点 完成某些操作 常见的双指针方
  • 数据库多维迭代算法

    关键词 数据库 迭代 递归 多维 一 两种传统的数据库迭代结构算法 对于数据库的迭代结构 有两种传统的算法 递归算法和边界算法 比如对于下面图1的结构 图1 递归算法的数据结构如表1所示 节点id 节点值 父节点id 1 1111 2 3
  • 数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)

    原文 http blog csdn net sup heaven article details 39313731 数据结构中常见的树 BST二叉搜索树 AVL平衡二叉树 RBT红黑树 B 树 B 树 B 树 转载 2014年09月16日
  • 50个c/c++源代码网站

    C C 是最主要的编程语言 这里列出了50名优秀网站和网页清单 这些网站提供c c 源代码 这份清单提供了源代码的链接以及它们的小说明 我已尽力包括最佳的C C 源代码的网站 这不是一个完整的清单 您有建议可以联系我 我将欢迎您的建 议 以
  • (笔试前准备)字符串匹配算法总结

    我想说一句 我日 我讨厌KMP KMP虽然经典 但是理解起来极其复杂 好不容易理解好了 便起码来巨麻烦 老子就是今天图书馆在写了几个小时才勉强写了一个有bug的 效率不高的KMP 特别是计算next数组的部分 其实 比KMP算法速度快的算法
  • Hash table and application in java

    查找的效率取决于在查找是比较的次数 次数越少效率越高 反之越低 最理想的情况是无需比较 一次存取便能找到所查找的记录 根据对应关系f找到给定值K的像f K hash function 应运而生 由此思想建的表称为hash table 集合h
  • 链表和线性表的优缺点

    链表和线性表的优缺点 作为我们最先接触的两个数据结构 链表和线性表的优缺点都较为明显 并且二者互相补足 文章目录 链表和线性表的优缺点 线性表 线性表的组成 线性表的缺点 线性表的优点 链表 链表的组成 链表的优点 链表的缺点 总结 线性表
  • 常用的十种算法--马踏棋盘算法

    1 马踏棋盘算法介绍 马踏棋盘算法也被称为骑士周游问题 将马随机放在国际象棋的 8 8 棋盘 Board 0 7 0 7 的某个方格中 马按走棋规则 马走日字 进行移动 要求每个方格只进入一次 走遍棋盘上全部 64 个方格 2 马踏棋盘算法
  • 亚利桑那州立大学周纵苇:研习 U-Net ——现有的分割网络创新

    雷锋网AI研习社按 经典的 Encoder Decoder 结构在目标分割问题中展现出了举足轻重的作用 然而这样一个相对固定的框架使得模型在感受野大小和边界分割精度两方面很难达到兼顾 本次公开课 讲者以 U Net 为案例分析 总结现有的分
  • 以太坊系列之十五: 以太坊数据库

    以太坊数据库中都存了什么 以太坊使用的数据库是一个NOSQL数据库 是谷歌提供的开源数据leveldb 这里尝试通过分析以太坊数据库存储了什么来分析以太坊可能为我们提供哪些关于区块链的API 存储内容 NOSQL是一个key value数据
  • 字符串09--表示数值的字符串

    字符串09 表示数值的字符串 jz53 题目概述 解析 参考答案 注意事项 说明 题目概述 算法说明 请实现一个函数用来判断字符串是否表示数值 包括整数和小数 例如 字符串 100 5e2 123 3 1416 和 1E 16 都表示数值
  • JavaScript系列——数组元素左右移动N位算法实现

    引言 在自己刚刚毕业不久的时候 去了一家公司面试 面试官现场考了我这道题 我记忆深刻 当时没有想到思路 毫无疑问被面试官当成菜鸟了 最近刚好在研究数组的各种算法实现 就想到这道题 可以拿来实现一下 纪念自己逝去的青春 需求 假设有这样一个数
  • 图 - Java实现无向带权图的邻接矩阵表示法

    图 Java实现无向带权图的邻接矩阵表示法 1 图 1 1 图的介绍 图 Graph 是一种复杂的非线性表结构 图中的元素我们就叫做顶点 vertex 图中的一个顶点可以与任意其他顶点建立连接关系 我们把这种建立的关系叫做边 edge 跟顶
  • 数据结构与算法-列表(双向链表)设计及其排序算法

    0 概述 本文主要涵盖列表 双向链表 的设计及其排序算法的总结 列表是一种典型的动态存储结构 其中的数据 分散为一系列称作节点 node 的单位 节点之间通过指针相互索引和访问 为了引入新节点或删除原有节点 只需在局部调整少量相关节点之间的
  • 数理统计知识整理——回归分析与方差分析

    题记 时值我的北科研究生第一年下 选学 统计优化 课程 备考促学 成此笔记 以谨记 1 线性回归 1 1 原理分析 要研究最大积雪深度x与灌溉面积y之间的关系 测试得到近10年的数据如下表 使用线性回归的方法可以估计x与y之间的线性关系 线
  • 用两个栈实现队列

    目录 一 栈的基本结构及其接口 二 我的队列结构定义 三 我的队列创建及其初始化 四 我的队列入队 五 我的队列出队 六 我的队列取队头元素 七 我的队列判空 八 我的队列销毁 一 栈的基本结构及其接口 栈的结构定义 typedef int
  • Leetcode2661. 找出叠涂元素

    Every day a Leetcode 题目来源 2661 找出叠涂元素 解法1 哈希 题目很绕 理解题意后就很简单 由于矩阵 mat 中每一个元素都不同 并且都在数组 arr 中 所以首先我们用一个哈希表 hash 来存储 mat 中每
  • 牛客剑指offer刷题其他算法篇

    文章目录 构建乘积数组 题目 思路 代码实现 第一个只出现一次的字符
  • 【数据结构】双链表的定义和操作

    目录 1 双链表的定义 2 双链表的创建和初始化 3 双链表的插入节点操作 4 双链表的删除节点操作 5 双链表的查找节点操作 6 双链表的更新节点操作 7 完整代码 嗨 我是 Filotimo 很高兴与大家相识 希望我的博客能对你有所帮助
  • C++ AVL树(四种旋转,插入)

    C AVL树 四种旋转 插入 一 AVL树的概念及性质 二 我们要实现的大致框架 1 AVL树的节点定义 2 AVL树的大致框架 三 插入 1 插入逻辑跟BST相同的那一部分 2 修改平衡因子

随机推荐

  • Nginx的配置(转载)

    虚拟主机与域名解析 虚拟主机是使用特殊的软硬件技术 把一台运行在因特网上的服务器主机分成一台台 虚拟 的主机 每一台虚拟主机都具有独立的域名 具有完整的Internet服务器 WWW FTP Email等 功能 虚拟主机之间完全独立 并可由
  • CVPR 2023|3D模型分割新方法!不用人工标注,只需一次训练,未标注类别也能识别

    不需要人工标注 只需要一次训练 就能让3D模型理解语言并识别未标注过的类别 比如看下面这个例子 未标注的 unannotated 黑板和显示器 3D模型经过这个方法训练之后 就能很快 抓准 目标进行划分 再比如 给它分别输入sofa cou
  • python selenium 常用断言的使用方法

    assertEqual a b msg 测试失败时打印的信息 断言a和b是否相等 相等则测试用例通过 assertNotEqual a b msg 测试失败时打印的信息 断言a和b是否相等 不相等则测试用例通过 assertTrue x m
  • 蒙特卡洛模拟入门的几个小例子(R语言实现)

    嗯 第一个例子是怎么用蒙特卡洛模拟求pi的值 第二个是用蒙特卡洛模拟求解定积分 第三个是用蒙特卡洛模拟证券市场求解其收益 第四个是用蒙特卡洛模拟验证OLS的参数的无偏性 然后还要R是如何求导 计算导数的 R的点的形状的集合 以便于查看 转载
  • Python学习——捕获异常

    根据B站 黑马程序员 的python教程记录笔记 一 基本了解 看了标题之后可能会有疑惑 什么是捕获异常 为什么要捕获异常呢 如果在开发中 对某些代码的执行不能确定是否正确 可以增加 try 尝试 来 捕获异常 捕获异常最简单的语法格式 t
  • 在Windows中,开机自启动

    在Windows中 你可以按照以下步骤设置程序的开机自启动 1 使用快捷键 Win R 打开运行对话框 2 输入 shell startup 并点击 确定 这将打开当前用户的启动文件夹 3在启动文件夹中创建一个程序的快捷方式 可以右键点击文
  • 翻转数字,例如输入123 输出321 输入-12300 输出-321,输入1300 输出31,输入0 输出0。

    str1 input 请任意输入一串数字 第一种方法 if int str1 gt 0 判断大于0 print int str1 1 此处用int 避免str1是以0结尾字符串 int 后 0自然去除 elif int str1 lt 0
  • 【计算机网络】TCP详解

    计算机网络 传输层 TCP详解 传输层 TCP和UDP区别 优缺点 应用 用户数据报协议 UDP User Datagram Protocol 传输控制协议 TCP Transmission Control Protocol 无连接 面向连
  • vim插件3--dict

    vim插件3 dict 功能 vim dict插件主要用于从本地或者特定服务器查找相关数据 此功能正常情况下用不上 vim dict有一个不错的功能为从特定的字典文件中补全文本或单词 此外可以用 dict文件来实现不同类型代码的自动补全功能
  • HTML 展开收起

    1 授课老师教的展开收起的实现 Html部分 1 div class cont div class tab box2 table class caozuo cellspacing 0 tr th 操作详情 th th 操作人 th th 环
  • Redis学习0 -介绍及安装

    Redis 介绍 Redis是一个key value存储系统 数据库 redis支持存储的value类型有很多种 如string 字符串 list 链表 set 集合 zset 有序集合 和hash 哈希类型 安装redis库 因为我是用u
  • 简单易懂!如何制作系统启动盘(win7/win10/win11...),利用u盘重装系统!

    一 制作启动盘 1 准备一个空u盘 2 在电脑上下载光盘刻录工具 最新UltraISO官方免费下载 UltraISO软碟通中文官方网站 3 在电脑上下载光盘镜像文件 操作系统 选择自己需要的系统进行下载MSDN 我告诉你 做一个安静的工具站
  • 使用Docker容器搭建Kafka集群的详细过程讲解

    一 Kafka集群的搭建 1 拉取相关镜像 docker pull wurstmeister kafka docker pull zookeeper 2 运行zookeeper docker run d name zookeeper p 2
  • java--多态的转型

    java中的多态中的语法转换 只有在是继承关系的前提下才可以进行转型 子 gt 父 向上转型 自动转型 父 gt 子 向下转型 强制转换 以下为例子 public class duotai public static void main S
  • 打工人都在用的AI工具

    随着ChatGPT的问世 AI也算迎来了高光时刻 下文是技术宅整理的一些和ChatGPT相关的工具应用 排名不分先后 也不代表个人推荐 但真心真心好好用 主打的就是一个纯粹 本文将先分享10个有趣的AI小工具 最后3个小工具 是我们搬砖人心
  • 将纯黑的arcgis语义分割标签(单类别)(tif、png格式)转为黑白

    做建筑物分割 用arcgis做出来的标签 tif 为纯黑 转为png格式后也是纯黑 虽然在arcgis中可以正常显示 且不影响模型训练 但是的确有那么点不好看 参考其他数据集 单类别表标签均为黑白二值图 0 255 arcgis做的标签为纯
  • 【pygame入门】pygame游戏实例入门级教程,如有不懂欢迎随时补充留言。

    开发环境 pycharm anconda3 第三方库 pygame 从标题看这句略显多余 第三方库安装 方法一 直接在pycharm里面安装 files gt seting gt project gt python Interpreter
  • 如何才能成为一个成熟的投资者?

    股市从来不缺少一年十倍 百倍的故事 但是真的能够长年稳定盈利的人 其实少之又少 所以很多人都称之为赌场 在赌场暴富是有可能的 但是能够笑着离开的人确少之又少 笔者自己也经历过很多大起大落 如今慢慢觉得摸到了一些门道 在这里和大家一起探讨 如
  • AS 添加AAR 文件 Gradle 7.0+ 设置aar路径失败问题

    https blog csdn net a940659387 article details 120514674
  • 数据结构小白之二叉树的遍历和查找

    1 存储方式的分析 1 1 数组储存方式的分析 优点 通过下标的访问 速度快 还可以使用二分法提高检索的速度 缺点 如果要检索某个值 或者插入值 整个数组就会进行移动 从而造成较低的效率 同时如果需要扩容的话 从底层而言 每一次数组的扩容就