二叉树前中后线索化及对应前中后序线索化遍历(图解)

二叉树线索化都是套路,会一种另外两种只是稍微修改一下代码

值得一提的是后序线索化输出,逆序思维将后序线索化看成前序,采用"前序线索化输出"代码更加简洁,也更好理解

线索化基本介绍

二叉树线索化百度百科介绍:
https://baike.baidu.com/item/%E7%BA%BF%E7%B4%A2%E4%BA%8C%E5%8F%89%E6%A0%91/10810037?fr=aladdin

以下面二叉树为例

前序化流程图解

创建节点对象 (使用数组更方便)

class TreeNode1 {private int no;private TreeNode1 left;private TreeNode1 right;/** 说明: 1.如果 letfType 或 rightType 为 0 表示 左子树或右子树 2.如果 letfType 或 rightType 为 1 表示* 前驱或后驱节点*/private int leftType;private int rightType;public TreeNode1(int no) {this.no = no;}//getter/setter ...@Overridepublic String toString() {return "TreeNode1 [no=" + no + "]";}}

创建一个类实现线索化

class TreeManger1 {private TreeNode1 root;public void setRoot(TreeNode1 root) {this.root = root;}...线索化
}

## 中序最简单也最容易理解 所以先看一下中序线索化

// 为了实现 线索化,需要创建一个变量,指定向前节点的前驱节点// 在递归进行索化时,infixPre 总是保留前一个节点TreeNode1 infixPre = null;public void infixThreadTreeNode() {this.infixThreadTreeNode(root);}// 中序线索化public void infixThreadTreeNode(TreeNode1 node) {// 如果 node == null 则不能索化if (node == null) {return;}// 1.线索化左子树infixThreadTreeNode(node.getLeft());// 2.线索化当前节点if (node.getLeft() == null) {// 让当前节点的左指针指向前驱节点node.setLeft(infixPre);// 修改当前节点的左指针的类型,指向前驱节点node.setLeftType(1);}// 处理后继节点         if (infixPre != null && infixPre.getRight() == null) {// 让前驱节点的有指针指向当前节点infixPre.setRight(node);// 修改前驱节点的右指针类型infixPre.setRightType(1);}// !!!!!没处理一个节点后让当前节点指向下一个节点的前驱节点infixPre = node;// 3.线索化右子树infixThreadTreeNode(node.getRight());}

中序线索化遍历

// 中序线索化输出public void infixThreadTreeNodeOrde() {// 定义一个节点存储当前遍历的节点 从 root 开始TreeNode1 node = root; while (node != null) {// 循环找到 leftType = 1 的节点while (node.getLeftType() == 0) {node = node.getLeft();}// 打印当前节点System.out.println(node);// 如果当前节点的右指针指向的是后继节点,就一直输出while (node.getRightType() == 1) {// 获取当前节点的后继节点node = node.getRight();System.out.println(node);}// 替换这个遍历的节点node = node.getRight();}}

前序线索化

TreeNode1 prePre = null;// 前序线索化public void preThread(TreeNode1 node) {if (node == null) {return;}// 线索化当前节点if (node.getLeft() == null) {node.setLeft(prePre);node.setLeftType(1);}if (prePre != null && prePre.getRight() == null) {prePre.setRight(node);prePre.setRightType(1);}prePre = node;// 线索化左子树if (node.getLeftType() != 1) {preThread(node.getLeft());}// 线索化右子树if (node.getRightType() != 1) {preThread(node.getRight());}}

前序线索化输出

// 前序索化输出public void preThreadOrder() {TreeNode1 node = root;while (node != null) {while (node.getLeftType() != 1) {System.out.println(node);node = node.getLeft();}System.out.println(node);node = node.getRight();}}

后序线索化

TreeNode1 postPre = null;// 后序序线索化public void postThread(TreeNode1 node) {if (node == null) {return;}// 线索化左子树postThread(node.getLeft());// 线索化右子树postThread(node.getRight());// 线索化当前节点if (node.getLeft() == null) {node.setLeft(postPre);node.setLeftType(1);}if (postPre != null && postPre.getRight() == null) {postPre.setRight(node);postPre.setRightType(1);}postPre = node;}

后序线索化输出

/** 后线索化输出* * 逆序前线索化,将其压入栈中,最后依次弹出即可* */public void postThreadOrde() {Stack<TreeNode1> stack = new Stack<TreeNode1>();TreeNode1 node = root;while (node != null) {while (node.getRightType() != 1) {stack.push(node);node = node.getRight();}stack.push(node);node = node.getLeft();}while (!stack.isEmpty()) {System.out.println(stack.pop());}}

一张图对比一下 其实都是套路

全部代码

package com.kc.c09_tree._02threadbinarytree;import java.util.ArrayList;
import java.util.List;
import java.util.Stack;public class T {public static void main(String[] args) {TreeNode1 n11 = new TreeNode1(11);TreeNode1 n21 = new TreeNode1(21);TreeNode1 n31 = new TreeNode1(31);TreeNode1 n14 = new TreeNode1(14);TreeNode1 n15 = new TreeNode1(15);TreeNode1 n61 = new TreeNode1(61);TreeNode1 n71 = new TreeNode1(71);TreeNode1 n81 = new TreeNode1(81);TreeNode1 n91 = new TreeNode1(91);n11.setLeft(n21);n11.setRight(n31);n21.setLeft(n14);n21.setRight(n15);n31.setLeft(n61);n31.setRight(n71);n14.setLeft(n81);n14.setRight(n91);TreeManger1 tm = new TreeManger1();tm.setRoot(n11);//        tm.preThread(n11);
//      tm.infixThreadTreeNode(n11);tm.postThread(n11);
//      // 检验TreeNode1 left11 = n11.getLeft();TreeNode1 right11 = n11.getRight();System.out.println("no11 : left = " + left11 + ",right = " + right11);TreeNode1 left21 = n21.getLeft();TreeNode1 right21 = n21.getRight();System.out.println("no21 : left = " + left21 + ",right = " + right21);TreeNode1 left31 = n31.getLeft();TreeNode1 right31 = n31.getRight();System.out.println("no31 : left = " + left31 + ",right = " + right31);TreeNode1 left14 = n14.getLeft();TreeNode1 right14 = n14.getRight();System.out.println("no14 : left = " + left14 + ",right = " + right14);TreeNode1 left81 = n81.getLeft();TreeNode1 right81 = n81.getRight();System.out.println("no81 : left = " + left81 + ",right = " + right81);TreeNode1 left91 = n91.getLeft();TreeNode1 right91 = n91.getRight();System.out.println("no91 : left = " + left91 + ",right = " + right91);TreeNode1 left15 = n15.getLeft();TreeNode1 right15 = n15.getRight();System.out.println("no15 : left = " + left15 + ",right = " + right15);TreeNode1 left61 = n61.getLeft();TreeNode1 right61 = n61.getRight();System.out.println("no61 : left = " + left61 + ",right = " + right61);TreeNode1 left71 = n71.getLeft();TreeNode1 right71 = n71.getRight();System.out.println("no71 : left = " + left71 + ",right = " + right71);//        tm.preThreadOrder();
//      tm.infixThreadTreeNodeOrde();tm.postThreadOrde();}
}class TreeManger1 {private TreeNode1 root;public void setRoot(TreeNode1 root) {this.root = root;}/********* 线索化二叉树 *********//******************************************/TreeNode1 prePre = null;// 前序线索化public void preThread(TreeNode1 node) {if (node == null) {return;}// 线索化当前节点if (node.getLeft() == null) {node.setLeft(prePre);node.setLeftType(1);}if (prePre != null && prePre.getRight() == null) {prePre.setRight(node);prePre.setRightType(1);}prePre = node;// 线索化左子树if (node.getLeftType() != 1) {preThread(node.getLeft());}// 线索化右子树if (node.getRightType() != 1) {preThread(node.getRight());}}// 前序索化输出public void preThreadOrder() {TreeNode1 node = root;while (node != null) {while (node.getLeftType() != 1) {System.out.println(node);node = node.getLeft();}System.out.println(node);node = node.getRight();}}/******************************************/TreeNode1 postPre = null;// 后序序线索化public void postThread(TreeNode1 node) {if (node == null) {return;}// 线索化左子树postThread(node.getLeft());// 线索化右子树postThread(node.getRight());// 线索化当前节点if (node.getLeft() == null) {node.setLeft(postPre);node.setLeftType(1);}if (postPre != null && postPre.getRight() == null) {postPre.setRight(node);postPre.setRightType(1);}postPre = node;}/** 后线索化输出* * 逆序前线索化,将其压入栈中,最后依次弹出即可* */public void postThreadOrde() {Stack<TreeNode1> stack = new Stack<TreeNode1>();TreeNode1 node = root;while (node != null) {while (node.getRightType() != 1) {stack.push(node);node = node.getRight();}stack.push(node);node = node.getLeft();}while (!stack.isEmpty()) {System.out.println(stack.pop());}}/*************************************/// 为了实现 线索化,需要创建一个变量,指定向前节点的前驱节点// 在递归进行索化时,infixPre 总是保留前一个节点TreeNode1 infixPre = null;public void infixThreadTreeNode() {this.infixThreadTreeNode(root);}// 中序线索化public void infixThreadTreeNode(TreeNode1 node) {// 如果 node == null 则不能索化if (node == null) {return;}// 1.线索化左子树infixThreadTreeNode(node.getLeft());// 2.线索化当前节点if (node.getLeft() == null) {// 让当前节点的左指针指向前驱节点node.setLeft(infixPre);// 修改当前节点的左指针的类型,指向前驱节点node.setLeftType(1);}// 处理后继节点if (infixPre != null && infixPre.getRight() == null) {// 让前驱节点的有指针指向当前节点infixPre.setRight(node);// 修改前驱节点的右指针类型infixPre.setRightType(1);}// !!!!!没处理一个节点后让当前节点指向下一个节点的前驱节点infixPre = node;// 3.线索化右子树infixThreadTreeNode(node.getRight());}// 中序线索化输出public void infixThreadTreeNodeOrde() {// 定义一个节点存储当前遍历的节点 从 root 开始TreeNode1 node = root;while (node != null) {// 循环找到 leftType = 1 的节点while (node.getLeftType() == 0) {node = node.getLeft();}// 打印当前节点System.out.println(node);// 如果当前节点的右指针指向的是后继节点,就一直输出while (node.getRightType() == 1) {// 获取当前节点的后继节点node = node.getRight();System.out.println(node);}// 替换这个遍历的节点node = node.getRight();}}}class TreeNode1 {private int no;private TreeNode1 left;private TreeNode1 right;private int leftType;private int rightType;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 TreeNode1(int no) {this.no = no;}public int getNo() {return no;}public void setNo(int no) {this.no = no;}public TreeNode1 getLeft() {return left;}public void setLeft(TreeNode1 left) {this.left = left;}public TreeNode1 getRight() {return right;}public void setRight(TreeNode1 right) {this.right = right;}@Overridepublic String toString() {return "TreeNode1 [no=" + no + "]";}}

二叉树前、中、后线索化及对应前、中、后序线索化遍历相关推荐

  1. 为什么先序/中序线索二叉树不需要栈的支持,而后序线索二叉树需要栈的支持?

    为什么先序/中序线索二叉树不需要栈的支持,而后序线索二叉树需要栈的支持? 首先要明确两点 先序线索二叉树的缺点:无法找到先序序列中某结点的前驱 后序线索二叉树的缺点:无法找到后序序列中某结点的后继 中 ...

  2. 线索二叉树(前中后序线索化/遍历/画线索)

    线索二叉树 文章目录 线索二叉树 1 线索二叉树的基本概念 2 线索二叉树的构造 2.1 线索二叉树的存储结构 2.2 给线索二叉树画线索 2.2.1 中序 2.2.2 先序 2.2.3 后序 2.3 ...

  3. 二叉树前、中、后序线索化及遍历

    public class ThreadedBinaryTree {public static void main(String[] args){Heronodes node1=new Heronode ...

  4. 二叉树的先序线索化、中序线索化、后序线索化的对比

    有一点需要注意:在先序遍历一个节点的左子树时,需要判断其ltag的值是否为0,如果为0可以正常遍历,但是,如果为1就不能进行遍历.因为ltag的值为1说明该结点的左指针指向的是它的前驱结点而不是左孩子 ...

  5. 线索二叉树和中序非递归遍历线索化后的二叉树

    //线索二叉树 #include<stdio.h> #include<malloc.h> #include<process.h> #define OVERFLOW ...

  6. Java实现前中后序线索化二叉树以及遍历

    文章目录 一.线索化二叉树的原理 二.构建线索化二叉树 三.代码实现线索二叉树 一.线索化二叉树的原理 在前面介绍二叉树的文章中提到,二叉树可以使用两种存储结构:顺序存储和链式存储,在使用链式存储时, ...

  7. 线索二叉树原理及前序、中序线索化(Java版)

    转载 原文地址:https://blog.csdn.net/UncleMing5371/article/details/54176252 一.线索二叉树原理 前面介绍二叉树原理及特殊二叉树文章中提到, ...

  8. 先序abdfcegh 中序bfdagehc 后序线索二叉树_二叉树的遍历和线索二叉树

    二叉树的遍历是指按某条搜索路径访问树中的每个结点,使得每个结点均被访问一次,且只被访问一次. 先序遍历(NLR) 若二叉树为空,则什么也不做:否则, (1)访问根结点. (2)先序遍历左子树. (3) ...

  9. 二叉树前序中序后续线索树_后序线索二叉树怎么画 线索二叉树基本操作详解 - 办公软件 - 服务器之家...

    后序线索二叉树怎么画 线索二叉树基本操作详解 发布时间:2017-05-23 来源:服务器之家 遍历二叉树是以一定规则将二叉树中结点排列成一个线性序列,得到二叉树中结点的先序,中序或后序序列.这实际上 ...

最新文章

  1. 【浅墨Unity3D Shader编程】之三 光之城堡篇:子着色器、通道与标签的写法 amp; 纹理混合...
  2. 概率占据图(POM)算法理解
  3. openglshader实现虚拟场景_opengl+shader
  4. 可怕的春运,烦人的火车票!
  5. jQuery AJAX 与 jQuery 事件
  6. PyTorch学习笔记——词向量简介
  7. Axios 请求配置参数详解
  8. Android之Handler,举例说明如何更新UI
  9. h5调用摄像头 android,H5 使用移动端摄像头
  10. 输入某班C语言考试成绩,人数未知,用-1作为结束标志,若大于100分,则重新输入,计算全班的最高分、最低分与平均分
  11. python-docx处理word文件指定页面批量打印
  12. HighCharts柱状图显示百分比
  13. 那一年岳云鹏14岁,郭德纲26岁
  14. 网站ssl证书出现错误如何解决
  15. 能量英语(三) 之 “情感把控 II ”
  16. This beta version of Typora is expired, please download and install a newer version
  17. 记一次oracle通过dblink连接mysql实施
  18. photoshop将图层导出到文件脚本不带数字序号、下划线方法
  19. nginx缓冲区链表chain
  20. CSMA/CD 协议 详解

热门文章

  1. Datawhale-数据挖掘实践(智慧海洋)
  2. 怎样使用七牛云CDN加速并绑定阿里云域名
  3. Spring-ICE 结冰算法述评-(5)对流换热系数计算
  4. 名悦集团在线盘点汽车品牌标志背后的那些故事
  5. 最新升级pip命令,查看pip版本命令,pycharm升级pip命令,推荐收藏关注不迷路
  6. 基于51单片机的水温可测液体温度的控制器设计
  7. 虹膜识别论文1:Iris Recognition With Off-the-Shelf CNN Features: A Deep Learning Perspective 2017年 学习心得
  8. 【图片新闻】俄罗斯新型“Okhotnik”(“猎人”)重型攻击无人机首次亮相
  9. 安拆网分享:脚手架的防火要求及措施
  10. DNG图像文件的解码