二叉树的创建和遍历(java)

news2024/11/29 8:36:14

简介

二叉树是一种常见的树形数据结构,它由节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。这些节点以层次结构的方式组织在一起,每个节点都有一个父节点,除了根节点外,每个节点都有一个唯一的父节点。

二叉树具有以下特性:

  1. 每个节点最多有两个子节点,分别为左子节点和右子节点。
  2. 左子节点和右子节点的顺序不能颠倒,即左子节点必须在右子节点之前。
  3. 二叉树的子树也是二叉树。

常见的二叉树类型包括:

  • 二叉搜索树(Binary Search Tree,BST):一种特殊的二叉树,其中每个节点的值都大于其左子树中的任何节点的值,且小于其右子树中的任何节点的值。
  • 完全二叉树(Complete Binary Tree):除了最后一层外,其他层的节点都被完全填充,并且最后一层的节点都集中在左侧。
  • 平衡二叉树(Balanced Binary Tree):树中任何节点的两个子树的高度差不超过1。

二叉树常用于实现搜索、排序和数据组织等算法。

创建

首先定义一个类来代表树中的结点,属性包括节点的值,它的左节点和右节点。

    /**
     * 定义二叉树
     */
    public static class TreeNode {
         int val;
         TreeNode left;
         TreeNode right;
         TreeNode() {}
         TreeNode(int val) { this.val = val; }
         TreeNode(int val, TreeNode left, TreeNode right) {
             this.val = val;
             this.left = left;
             this.right = right;
         }
    }

在主方法中创建几个节点,并将其连接起来。

    public static void main(String[] args) {
        TreeNode treeNode6 = new TreeNode(6);
        TreeNode treeNode5 = new TreeNode(5);
        TreeNode treeNode4 = new TreeNode(4);
        TreeNode treeNode3 = new TreeNode(3);
        TreeNode treeNode2 = new TreeNode(2);
        TreeNode treeNode1 = new TreeNode(1);

        treeNode1.left=treeNode2;
        treeNode1.right=treeNode3;
        treeNode2.left=treeNode4;
        treeNode2.right=treeNode5;
        treeNode3.left=treeNode6;
    }

现在我们就得到了下图中的二叉树

广度优先搜索

上面二叉树广度优先搜索的结果为 1 2 3 4 5 6

所谓广度优先就是一层一层地遍历二叉树,在此不多做解释,具体解释可以查看我的另一篇博客

树的广度优先搜索(java实现)

深度优先搜索

树的深度优先搜索通常有三种方式,分别为先序,中序和后序。这三种方式都可以使用递归的方式实现和非递归的方式实现。

先序遍历

先序遍历(Pre-order Traversal)其遍历顺序为先访问根节点,然后依次递归地遍历左子树和右子树。

使用先序遍历上面二叉树得到的顺序为:1 2 4 5 3 6 

递归实现:

    /**
     * 递归实现先序遍历
     * @param root
     */
    public static void preOrder(TreeNode root){
        if(root==null) return;
        System.out.print(root.val+" ");
        preOrder(root.left);
        preOrder(root.right);
    }

非递归实现:

使用非递归主要时通过栈来实现,先将根节点放入栈中,随后进入循环,循环停止条件为栈空。在循环中,将刚放入栈的节点弹出,再将其左右节点压入栈,直到再无节点被压入栈,栈为空。这样就实现了先访问根节点,然后依次遍历左子树和右子树。

    /**
     * 非递归实现先序遍历
     * @param root
     */
    public static void preOrder2(TreeNode root){
        if (root == null)
            return;
        TreeNode c = new TreeNode();
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            c = stack.pop();
            System.out.print(c.val + " ");
            if (c.right != null)
                stack.push(c.right);
            if (c.left != null)
                stack.push(c.left);
        }
    }

中序遍历

中序遍历(In-order Traversal)其遍历顺序为先递归地遍历左子树,然后访问根节点,最后递归地遍历右子树。

使用中序遍历上面二叉树得到的顺序为:4 2 5 1 6 3 

递归实现:

    /**
     * 递归实现中序遍历
     * @param root
     */
    public static void inOrder(TreeNode root){
        if(root==null) return;
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }

非递归实现:

非递归实现中序遍历的方式也是使用栈,先将根节点压入栈,随后开始遍历,将其左子树压入栈,再将左子树的左子树压入栈,直到没有左子树为止。随后开始将刚才压入的节点弹出,每弹出一个,就去寻找其有物右子树,如果有右子树,就继续去遍历右子树的左子树。按照这样的规律一直遍历到栈为空就实现了中序遍历,先访问左子树,然后访问根节点,最后递归地遍历右子树。

    /**
     * 非递归实现中序遍历
     * @param root
     */
    public static void inOrder2(TreeNode root){
        TreeNode current = root;
        Stack<TreeNode> stack = new Stack<>();
        while (current != null || !stack.isEmpty()) {
            while (current != null) {
                stack.push(current);
                current = current.left;
            }
            if (!stack.isEmpty()) {
                current = stack.pop();
                System.out.print(current.val + " ");
                current = current.right;
            }
        }
    }

后序遍历

后序遍历(Post-order Traversal)其遍历顺序为先递归地遍历左子树,然后递归地遍历右子树,最后访问根节点。

使用后序遍历上面二叉树得到的顺序为:4 5 2 6 3 1 

递归实现:

    /**
     * 递归实现后序遍历
     * @param root
     */
    public static void postOrder(TreeNode root){
        if(root==null) return;
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val+" ");
    }

非递归实现:

非递归实现后续遍历依旧是使用栈来实现。但是想要实现需要两个栈来实现,一个栈用来改变记录改变当前的位置,一个栈用于记录下要遍历的结果。

先从根节点开始,一直遍历寻找其右子树,并将其压入两个栈中,当寻找到最下方时,将第一个栈中的节点弹出,弹出后会继续寻找该弹出节点的左子树,如果有继续压入两个栈中,如果没有则继续弹出。这样就最后的结果就存在第二个栈中,最后只需要将第二个栈中的节点依次弹出就得到了后续遍历的顺序,就实现了先递归地遍历左子树,然后递归地遍历右子树,最后访问根节点。

    /**
     * 非递归实现后续遍历
     * @param root
     */
    public static void postOrder2(TreeNode root){
        TreeNode current = root;
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<TreeNode> stack2 = new Stack<>();
        while (current != null || !stack1.isEmpty()) {
            while (current != null) {
                stack1.push(current);
                stack2.push(current);
                current = current.right;
            }
            if (!stack1.isEmpty()) {
                current = stack1.pop();
                current = current.left;
            }
        }
        while (!stack2.isEmpty()) {
            System.out.print(stack2.pop().val + " ");
        }
    }

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

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

相关文章

SpringBoot配置profile

一、profile简介 我们在开发Spring Boot应用时&#xff0c;通常同一套程序会被安装到不同环境&#xff0c;比如:开发、测试、生产等。其中数据库地址、服务器端口等等配置都不同&#xff0c;如果每次打包时&#xff0c;都要修改配置文件&#xff0c;那么非常麻烦。profile功能就…

用Python做一个游戏辅助脚本,完整编程思路分享!

一、说明 简述&#xff1a;本文将以4399小游戏《 宠物连连看经典版2 》作为测试案例&#xff0c;通过识别小图标&#xff0c;模拟鼠标点击&#xff0c;快速完成配对。对于有兴趣学习游戏脚本的同学有一定的帮助。 运行环境&#xff1a;Win10/Python3.5。 主要模块&#xff1…

吴恩达llama课程笔记:第七课llama安全工具

羊驼Llama是当前最流行的开源大模型&#xff0c;其卓越的性能和广泛的应用领域使其成为业界瞩目的焦点。作为一款由Meta AI发布的开放且高效的大型基础语言模型&#xff0c;Llama拥有7B、13B和70B&#xff08;700亿&#xff09;三种版本&#xff0c;满足不同场景和需求。 吴恩…

C语言:文件操作(三)

目录 前言 5、文章的随机读写 5.1 fseek 5.2 ftell 5.3 rewind 结语 前言 本篇文章继续讲解文件操作&#xff0c;讲解文件的随机读写&#xff0c;主要有三个函数&#xff1a;fseek&#xff1b;ftell&#xff1b;rewind。 前面讲解的函数都是对文件内容进行顺序读写&#x…

STM32CubeMx下载安装环境搭建及工程创建

一、stm32介绍 STM32F103C8T6是一款由意法半导体公司&#xff08;ST&#xff09;推出的基于Cortex-M3内核的32位微控制器&#xff0c;硬件采用LQFP48封装&#xff0c;属于ST公司微控制器中的STM32系列。除了被我们熟知的STM32&#xff0c;ST公司还有SPC5X系列、STM8系列等&…

【C++类和对象】类和对象的引入

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

微信运动接口(获取自己的微信运动数据)

var pc new WXBizDataCrypt(appid, session_key); 这段代码是使用微信官方提供的 WXBizDataCrypt 类来解密微信运动数据。WXBizDataCrypt 是一个用于解密微信开放平台返回的加密数据的类&#xff0c;它需要传入两个参数&#xff1a;appid 和 session_key。其中&#xff0c;ap…

如何重置root用户的密码

即进入Linux操作系统的救援模式去重置密码。 1.首先重启机器&#xff0c; 2.进入grup菜单&#xff0c;按上下键盘&#xff0c;让系统的启动停在这个界面&#xff0c; 3.选择这个grup菜单的第一项&#xff0c;可以看界面下面的提示&#xff0c;按字母e编辑这个系统的启动配置…

STL —— stack、queue

博主首页&#xff1a; 有趣的中国人 专栏首页&#xff1a; C专栏 目录 1. 容器适配器 2. 栈的模拟实现 3. 队列的模拟实现 4. 双端队列deque 4.1 deque的原理介绍 4.2 deque的缺陷 4.3 为什么选择deque作为stack和queue的底层默认容器 本篇文章主要讲解 stack 和 queue …

基于SpringBoot的“银行OA系统的设计与实现”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“银行OA系统的设计与实现”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 用户登录界面 管理员主界面 员工基本档…

【C++从练气到飞升】07---内存管理

&#x1f388;个人主页&#xff1a;库库的里昂 ✨收录专栏&#xff1a;C从练气到飞升 &#x1f389;鸟欲高飞先振翅&#xff0c;人求上进先读书。 目录 一、 C/C内存分布 二、 C语言中动态内存管理方式 三、 C中动态内存管理 1. new/delete操作内置类型 2. new和delete操作…

Composer是什么?

Composer是PHP的一个依赖管理工具&#xff0c;它允许开发者声明项目所依赖的代码库&#xff0c;并在项目中自动安装这些依赖。它使用composer.json文件来定义项目的依赖关系&#xff0c;并使用composer.lock文件来锁定依赖的版本&#xff0c;以确保项目的稳定性和可重复性。 Co…

流媒体服务器的应用场景

流媒体服务器的应用场景 流媒体常用协议 RTSP 不适合手机和浏览器端 RTMP 比较适合手机和浏览器端直播 HLS 延迟比较高&#xff0c;适合点播

mysql奇葩问题union

单独执行第一条&#xff0c;有三条结果&#xff1b; union之后&#xff0c;只有一条结果&#xff1b; union自动的把重复数据合并了&#xff1b;

Nacos源码分析,Nacos gRPC服务端通信渠道是如何启动的?

作为SpringCloudAlibaba微服务架构实战派上下册和RocketMQ消息中间件实战派上下册的作者胡弦&#xff0c;我来给大家带来Nacos源码分析的技术文章。 Nacos默认会启动两个gRPC服务端通信渠道&#xff0c;一个用于Nacos集群节点之间的交互&#xff08;GrpcClusterServer&#xf…

大数据建模理论

文章目录 一、数仓概述1、数据仓库概念1.1 概述1.2 数据仓库与数据库的区别1.3 技术选型和架构 2、数仓常见名词2.1 实体2.2 维度2.3 度量2.4 粒度2.5 口径2.6 指标2.7 标签2.8 自然键/持久键/代理键2.9 退化维度2.10 下钻/上卷2.11 数据集市 3、数仓名词之间关系3.1 实体表&am…

每日一练

这题我主要用的思想是:动态规划 1.状态表示&#xff1a;以i位置为结尾的字符串是否可以用字典表示&#xff0c;然后就可以拆分成 j ~ i 为字典中的最后一个单词&#xff0c;此时 0 < j < i (1.有可能全部为字典的一个单词&#xff0c;2.有可能只有一个字母的单词)&#x…

【SpringBoot】返回参数

返回参数 返回页面返回数据返回 html 代码返回 json 数据两数相加用户登录 返回页面 首先在 static 文件夹中创建 index.html 文件&#xff1a; 代码&#xff1a; <html> <body><h1>hello word!!!</h1><p>this is a html page</p> <…

[C++初阶]类和对象(一)

1.面向过程和面向对象的区分 我们之前都是用C语言写的代码,我们知道C语言是一个面向过程的语言,但是现在我们学的时C,我们都知道C是一种面向对象的语言,那么什么叫面向过程?什么叫面向对象呢? 这里我们来举个例子: 比如我们是开饭店的&#xff0c;客人点了一道菜&#xff0c…