线索化二叉树,前序、中序以及后序遍历代码

2023-11-12


节点代码

class Node {
    int value;
    Node left;//左子树
    Node right;//右子树
    Node pre;//父节点

    //左节点属性,若值为0,其指向的是子树,若值为1,其指向的是前序节点
    int leftType;
    //右节点属性,若值为0,其指向的是子树,若值为1,其指向的是后继节点
    int rightType;

    public Node(int value) {
        this.value = value;
    }

    public int getLeftType() {
        return leftType;
    }

    public void setLeftType(int leftType) {
        this.leftType = leftType;
    }

    public int getRightType() {
        return rightType;
    }

    public void setRightType(int rightType) {
        this.rightType = rightType;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public Node getLeft() {
        return left;
    }

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

    public Node getRight() {
        return right;
    }

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

    public Node getPre() {
        return pre;
    }

    public void setPre(Node pre) {
        this.pre = pre;
    }

    @Override
    public String toString() {
        return "Node{" + "value=" + value + '}';
    }
}

前、中、后序线索化以及遍历代码

public class ThreadedBinaryTree {
    //二叉树的根节点
    Node root;

    //用于在线索化时保存前一个节点
    Node pre;

    /*
     * 前序线索化
     * @author Eleven
     * @return void
     * @date 16:30 2021/11/21
     */
    public void preThreaded() {
        this.preThreaded(root);
    }

    private void preThreaded(Node node) {
        if (node == null) {
            return;
        }

        //对本节点进行线索化
        threaded(node);

        //若该节点的左节点类型不为1(防止成环)就向左递归
        if (node.leftType != 1) {
            preThreaded(node.left);
        }

        //若该节点的右节点类型不为1(防止成环)就向右递归
        if (node.rightType != 1) {
            preThreaded(node.right);
        }

    }


    /*
     * 中序线索化
     * @author Eleven
     * @return void
     * @date 16:27 2021/11/21
     */
    public void infixThreaded() {
        this.infixThreaded(root);
    }

    private void infixThreaded(Node node) {
        if (node == null) {
            return;
        }
        //向左子树遍历
        infixThreaded(node.left);

        //对本节点进行线索化
        threaded(node);

        //向左子树遍历
        infixThreaded(node.right);

    }



    /*
     * 后序线索化
     * @author Eleven
     * @return void
     * @date 16:59 2021/11/21
     */
    public void postThreaded() {
        this.postThreaded(root);
    }

    private void postThreaded(Node node) {
        if (node == null) {
            return;
        }

        //先向左(右)子树进行递归进行线索化
        postThreaded(node.left);
        postThreaded(node.right);

        //再处理本节点,进行线索化
        threaded(node);

    }

    /*
     * 对传入节点进行线索化
     * @author Eleven
     * @param node
     * @return void
     * @date 19:45 2021/11/21
     */
    private void threaded(Node node) {
        //若该节点的左子树节点为空,就将左子树节点指向前一个节点
        //并将左子树节点的属性置1
        if (node.left == null) {
            node.left = pre;
            node.setLeftType(1);
        }

        //对前一个节点的右节点进行线索化
        //若前一个节点的右节点为null,就将前一个节点的右节点指向该节点
        if (pre != null && pre.right == null) {
            pre.right = node;
            pre.setRightType(1);
        }

        //将该节点赋给pre记录为下一个节点的前节点
        pre = node;
    }

    /*
     * 对前序线索化后的二叉树进行遍历
     * @author Eleven
     * @return void
     * @date 17:19 2021/11/21
     */
    public void preThreadedList() {
        Node node = root;
        if (root == null) {
            System.out.println("该树为空树");
            return;
        }

        while (node != null) {
            System.out.println(node);
            while (node.left != null && node.leftType != 1) {
                System.out.println(node.left);
                node = node.left;
            }
            node = node.right;
        }

    }

    /*
     * 对中序线索化后的二叉树进行遍历
     * @author Eleven
     * @return void
     * @date 19:20 2021/11/21
     */
    public void infixThreadedList() {
        Node node = root;
        if (root == null) {
            System.out.println("该树为空树");
            return;
        }

        while(node != null){
            while (node.leftType != 1) {
                node = node.left;
            }

            System.out.println(node);

            while (node.right != null && node.rightType == 1) {
                node = node.right;
                System.out.println(node);
            }

            node = node.right;
        }
    }

    /*
     * 对后序线索化后的二叉树进行遍历
     * @author Eleven
     * @return void
     * @date 19:20 2021/11/21
     */
    public void postThreadedList() {
        Node node = root;
        if (root == null) {
            System.out.println("该树为空树");
            return;
        }

        while(node != null){
            //寻找下一个后续节点
            //若是首次进入循环为寻找需要遍历的第一个节点
            while (node.leftType != 1) {
                node = node.left;
            }

            //找到后续节点,直接输出
            System.out.println(node);

            //根据后续线索进行遍历
            while (node.right != null && node.rightType == 1) {
                node = node.right;
                System.out.println(node);
            }

            //若当前节点的父节点为空,即该节点为root节点,说明后序线索遍历已完成
            // 将node置为空,结束遍历
            //若父节点不为null,说明该节点的父节点的左子树已遍历完成,将后续节点
            //指向父节点的右子树,进行右子树的遍历
            node = node.pre==null ? null : node.pre.right;

        }

    }
}

测试代码

public class ThreadedBinaryTreeTest {
    Node root, node1, node2, node3, node4, node5;
    ThreadedBinaryTree tbt;

    @Before
    public void setUp() {
        root = new Node(1);
        node1 = new Node(3);
        node2 = new Node(6);
        node3 = new Node(8);
        node4 = new Node(10);
        node5 = new Node(14);

        root.left = node1;
        root.right = node2;
        node1.left = node3;
        node1.right = node4;
        node1.pre = root;
        node2.left = node5;
        node2.pre = root;
        node3.pre = node1;
        node4.pre = node1;
        node5.pre = node2;

        tbt = new ThreadedBinaryTree();
        tbt.root = root;
    }

    @Test
    public void infixThreaded() {

        tbt.infixThreaded();
        System.out.println(node5.left);
        System.out.println(node5.right);
    }

    @Test
    public void preThreaded() {
        tbt.preThreaded();
        System.out.println(node5.left);
        System.out.println(node5.right);
    }

    @Test
    public void postThreaded() {
        tbt.postThreaded();
        System.out.println(node3.left);
        System.out.println(node3.right);

    }

    @Test
    public void preThreadedList() {
        tbt.preThreaded();
        tbt.preThreadedList();
    }

    @Test
    public void infixThreadedList() {
        tbt.infixThreaded();
        tbt.infixThreadedList();
    }


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

线索化二叉树,前序、中序以及后序遍历代码 的相关文章

随机推荐

  • 大数据时代——生活、工作与思维的重大变革

    最近读了维克托 迈尔 舍恩伯格的 大数据时代 觉得有不少收获 让我这个大数据的小白第一次理解了大数据 作者是大数据的元老级先驱 放一张帅照 膜拜下 不过这本书我本人不推荐从头读一遍 因为书中的核心理念并不是特别多 可以看看我这篇博客 1 海
  • idea中git的简单使用及git分支

    这篇文章简单介绍了git 着重介绍了分支概念和idea中git的简单使用 提问题 git是啥 git的分支概念 idea中git的使用 git仓库 git命令 git安装 参考文章 git是个啥 分布式版本管理工具 git的前生今世 git
  • Solidity:源文件结构

    Solidity 源文件结构 SPDX License Identifier 如果源代码可用 则可以更好地建立对智能合约的信任 由于提供源代码总是涉及版权方面的法律问题 Solidity编译器鼓励使用机器可读的SPDX License Id
  • Synchronized详解

    目录 一 如何解决线程并发安全问题 二 synchronized原理详解 1 加锁的方式 2 synchronized底层原理 3 Monitor监视器锁 MonitorEnter指令获取monitor所有权过程 MonitorExit指令
  • java.lang.StackOverflowError: null(栈内存溢出)递归导致

    通常是递归导致 或者死循环 在方法里调用了自己 导致无限调用 很快就会报错StackOverflowError 例如 有些初学者会犯如下错误 这是service类 public void saveEntity Emp emp this sa
  • vue拖拽

    1 定义拖拽指令 2 使用 3 效果 4 完整代码
  • Spring Boot入门编写简单java代码

    这里我简单编写一个Hello World的代码 文章目录 1 设置访问端口 2 编写项目代码 1 设置访问端口 在yml文件中编写端口为8080 我们启动项目是的路径就是localhost 8080 server port 8080 2 编
  • ‘UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xff in position 0: invalid start byte‘成功解决

    今天在用pandas进行读取时出现了bug 出现这种情况的原因是 文件的编码不是 UTF8 编码的 而pandas读取文件时固定采用 UTF8 解码 解决方法是改为对应的解码方式 解决的方式有两种 第一种 可以查看你对应文件的编码格式 使用
  • 生成对角矩阵 numpy.diag

    给定对角线上元素 我想生成对角矩阵 在网上搜了一下 竟然都是numpy diagonal 这个函数的作用是提取给定矩阵的对角元素 当然不是我想要的 后来发现numpy diag才是生成对角矩阵的函数 所以写此文章记录之 import num
  • 【运维&测试】如何写好测试用例

    一 常用术语 按软件测试手段 黑盒 灰盒 白盒 其中白盒测试是三个当中技术难度最高的 测试方向 功能 性能 安全 测试点划分 兼容性 易用性 UI元素 二 测试用例是什么 是测试工作的核心 是一组在测试时输入输出的标准 是软件需求的具体对照
  • 微服务 tars php,TARS-PHP

    TARS PHP是针对PHP使用tars二进制协议 以及Tars平台整体运维 RPC等一系列能力的解决方案 它主要由如下的几个部分组成 Tars是基于名字服务使用 Tars 协议的高性能 RPC 开发框架 同时配套一体化的服务治理平台 帮助
  • Python调用java代码-两种方法

    使用的模块jpype 一 直接使用java内置函数 from jpype import startJVM 开启java虚拟机 getDefaultJVMPath 自动获取虚拟机路径 startJVM getDefaultJVMPath ea
  • 第六大晶圆代工厂商2021净利润大增593.3%

    3月29日 华虹半导体发布2021全年业绩公告 销售收入创历史新高 达16 31亿美元 较上年度增长69 6 净利润为2 31亿美元 较2020年上升593 3 公告指出 华虹半导体销售收入增长因付运晶圆增加及平均销售价格上涨所致 在原材料
  • 使用Navicat+Premium模型设计表之间关系图(1:n;n:n)

    一 设计E R图之间关系 1 打开Navicat Premium软件 开始设计表 2 设计表之间的关系 操作步骤 选中关系图标 将某张表的一个字段拖动到另外一张表的字段 设计表之间的关系 4 导出成png 5 保存模型 使用Navicat逆
  • winform 开发用什么框架_为什么自动化测试框架中优先用 Pytest而不是 Robot Framework?...

    Python 自动化测试框架 的优缺点对比 之前曾提问请教过 Pytest 和 Robot Framework 的优缺点对比 由于网上关于这方面的信息比较少 收到大家的反馈建议 十分感谢 现在是该总结一下了 欢迎大家一起交流探讨 在对比框架
  • javaparser_JavaParser生成,分析和修改Java代码

    javaparser 作为开发人员 我们经常鄙视手动进行重复工作的人员 我们认为 他们应该实现这一目标 尽管如此 我们还是进行与编码有关的所有活动 当然 我们使用的高级IDE可以为我们执行一些重构 但这基本上就结束了 我们不品尝我们自己的药
  • [R语言] ggplot2入门笔记2—通用教程ggplot2简介

    文章目录 通用教程简介 Introduction To ggplot2 2 ggplot2入门笔记2 通用教程ggplot2简介 1 了解ggplot语法 Understanding the ggplot Syntax 2 如何制作一个简单
  • JS中的for循环讲解

    1 什么时候使用for循环 当我们想要遍历一个数组的值 或者实现一个点击按钮 多个按钮 时需要干的事情等等 这时候我们需要使用for循环实现可以更加的节约代码量 因此 可以简化为一句话 需要一轮一轮的重复去做这件事 可以使用for循环 真实
  • mysql分库分表的原则

    分库分表的种类 分库分表是指把数据库中数据物理地拆分到多个实例或多台机器上 非mysql原生态partitioning partitioning是mysql官方支持 在本地针对表的分区进行操作 它 可以将一张表的数据分别存储为多个文件 如果
  • 线索化二叉树,前序、中序以及后序遍历代码

    文章目录 节点代码 前 中 后序线索化以及遍历代码 测试代码 节点代码 class Node int value Node left 左子树 Node right 右子树 Node pre 父节点 左节点属性 若值为0 其指向的是子树 若值