先看一个问题

将数列 {1, 3, 6, 8, 10, 14  } 构建成一颗二叉树

问题分析:

  1. 当我们对上面的二叉树进行中序遍历时,数列为 {8, 3, 10, 1, 6, 14 }
  2. 但是 6, 8, 10, 14 这几个节点的 左右指针,并没有完全的利用上.
  3. 如果我们希望充分的利用 各个节点的左右指针, 让各个节点可以指向自己的前后节点,怎么办?
  4. 解决方案-线索二叉树

线索二叉树基本介绍

1、n个结点的二叉链表中含有n+1  【公式 2n-(n-1)=n+1】 个空指针域。利用二叉链表中的空指针域,存放指向该结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索")

2、这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种

3、一个结点的前一个结点,称为前驱结点

4、一个结点的后一个结点,称为后继结点

线索二叉树应用案例

应用案例说明:将下面的二叉树,进行中序线索二叉树。中序遍历的数列为 {8, 3, 10, 1, 14, 6}

思路分析: 中序遍历的结果:{8, 3, 10, 1, 14, 6}

说明: 当线索化二叉树后,Node节点的 属性 left 和 right ,有如下情况:

  1. left 指向的是左子树,也可能是指向的前驱节点. 比如 ① 节点 left 指向的左子树, 而 ⑩ 节点的 left 指向的就是前驱节点.
  2. right指向的是右子树,也可能是指向后继节点,比如 ① 节点right 指向的是右子树,而⑩ 节点的right 指向的是后继节点.

代码实现:

  1. class BinaryTree {
  2. private HeroNode root;
  3. privateHeroNode pre=null;
  4. public void threadNodes() {
  5. threadNodes(root);
  6. }
  7. public void threadNodes(HeroNode node) {
  8. if(node==null) {
  9. return;
  10. }
  11. threadNodes(node.getLeft());
  12. if(node.getLeft()==null){
  13. node.setLeft(pre);
  14. node.setLeftType(1);
  15. }
  16. if(pre!=null&&pre.getRight()==null) {
  17. pre.setRight(node);
  18. pre.setRightType(1); }
  19. pre=node;
  20. threadNodes(node.getRight());}}

代码

  1. public class BinaryTreeDemo {
  2. public static void main(String[] args) {
  3. BinaryTree binaryTree = new BinaryTree();
  4. HeroNode root = new HeroNode(1, "jack");
  5. HeroNode node1 = new HeroNode(3, "tom");
  6. HeroNode node2 = new HeroNode(6, "mike");
  7.  
  8. root.setLeftNode(node1);
  9. root.setRightNode(node2);
  10. binaryTree.setRoot(root);
  11.  
  12. HeroNode node3 = new HeroNode(8, "林冲");
  13. HeroNode node4 = new HeroNode(10, "关胜");
  14. node1.setLeftNode(node3);
  15. node1.setRightNode(node4);
  16. HeroNode node5 = new HeroNode(14, "jerry");
  17. node2.setLeftNode(node5);
  18.  
  19. System.out.println("---中序---");
  20. binaryTree.infixOrder();
  21. //中序线索化二叉树
  22. binaryTree.threadNodes();
  23.  
  24. HeroNode afterHeroNode10 = node4.getRight();
  25. System.out.println(afterHeroNode10);// no=1 name=jack ok了
  26. }}

测试

遍历线索化二叉树

说明:对前面的中序线索化的二叉树, 进行遍历

分析:因为线索化后,各个结点指向有变化,因此原来的遍历方式不能使用,这时需要使用新的方式遍历线索化二叉树,各个节点可以通过线型方式遍历,因此无需使用递归方式,这样也提高了遍历的效率。遍历的次序应当和中序遍历保持一致

  1. //遍历线索化二叉树的方法
  2. public void threadedList() {
  3. //定义一个变量,存储当前遍历的结点,从root开始
  4. HeroNode node = root;
  5. while(node != null) {
  6. //循环的找到leftType == 1的结点,第一个找到就是8结点
  7. //后面随着遍历而变化,因为当leftType==1时,说明该结点是按照线索化
  8. //处理后的有效结点
  9. while(node.getLeftType() == 0) {
  10. node = node.getLeft();
  11. }
  12.  
  13. //打印当前这个结点
  14. System.out.println(node);
  15. //如果当前结点的右指针指向的是后继结点,就一直输出
  16. while(node.getRightType() == 1) {
  17. //获取到当前结点的后继结点
  18. node = node.getRight();
  19. System.out.println(node);
  20. }
  21. //替换这个遍历的结点
  22. node = node.getRight();
  23.  
  24. }
  25. }

代码

  1. public static void main(String[] args) {
  2. //测试一把中序线索二叉树的功能
  3. HeroNode root = new HeroNode(1, "tom");
  4. HeroNode node2 = new HeroNode(3, "jack");
  5. HeroNode node3 = new HeroNode(6, "smith");
  6. HeroNode node4 = new HeroNode(8, "mary");
  7. HeroNode node5 = new HeroNode(10, "king");
  8. HeroNode node6 = new HeroNode(14, "dim");
  9.  
  10. //二叉树,后面我们要递归创建, 现在简单处理使用手动创建
  11. root.setLeft(node2);
  12. root.setRight(node3);
  13. node2.setLeft(node4);
  14. node2.setRight(node5);
  15. node3.setLeft(node6);
  16.  
  17. //测试中序线索化
  18. ThreadedBinaryTree threadedBinaryTree = new ThreadedBinaryTree();
  19. threadedBinaryTree.setRoot(root);
  20. threadedBinaryTree.threadedNodes();
  21.  
  22. //测试: 以10号节点测试
  23. HeroNode leftNode = node5.getLeft();
  24. HeroNode rightNode = node5.getRight();
  25. System.out.println("10号结点的前驱结点是 =" + leftNode); //
  26. System.out.println("10号结点的后继结点是=" + rightNode); //1
  27.  
  28. //当线索化二叉树后,能在使用原来的遍历方法
  29. //threadedBinaryTree.infixOrder();
  30. System.out.println("使用线索化的方式遍历 线索化二叉树");
  31. threadedBinaryTree.threadedList(); // 8, 3, 10, 1, 14, 6
  32.  
  33. }

测试

数据结构与算法---线索化二叉树(Threaded BinaryTree)的更多相关文章

  1. C#数据结构-线索化二叉树

    为什么线索化二叉树? 对于二叉树的遍历,我们知道每个节点的前驱与后继,但是这是建立在遍历的基础上,否则我们只知道后续的左右子树.现在我们充分利用二叉树左右子树的空节点,分别指向当前节点的前驱.后继,便 ...

  2. 线索化二叉树的构建与先序,中序遍历(C++版)

    贴出学习C++数据结构线索化二叉树的过程, 方便和我一样的新手进行测试和学习 同时欢迎各位大神纠正. 不同与普通二叉树的地方会用背景色填充 //BinTreeNode_Thr.h enum Point ...

  3. 图解前序遍历线索化二叉树,前序线索二叉树遍历,C\C++描述

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  4. 图解中序遍历线索化二叉树,中序线索二叉树遍历,C\C++描述

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  5. 后序线索化二叉树(Java版)

    前面介绍了前序线索化二叉树.中序线索化二叉树,本文将介绍后序线索化二叉树.之所以用单独的一篇文章来分析后序线索化二叉树,是因为后序线索化二叉树比前序.中序要复杂一些:另外在复习线索化二叉树的过程中,大 ...

  6. JAVA递归实现线索化二叉树

    JAVA递归实现线索化二叉树 基础理论 首先,二叉树递归遍历分为先序遍历.中序遍历和后序遍历. 先序遍历为:根节点+左子树+右子树 中序遍历为:左子树+根节点+右子树 后序遍历为:左子树+右子树+根节 ...

  7. YTU 3026: 中序线索化二叉树

    原文链接:https://www.dreamwings.cn/ytu3026/2896.html 3026: 中序线索化二叉树 时间限制: 1 Sec  内存限制: 128 MB 提交: 9  解决: ...

  8. Java 内功修炼 之 数据结构与算法(一)

    一.基本认识 1.数据结构与算法的关系? (1)数据结构(data structure): 数据结构指的是 数据与数据 之间的结构关系.比如:数组.队列.哈希.树 等结构. (2)算法: 算法指的是 ...

  9. JS数据结构与算法 - 二叉树(一)基本算法

    仅供JavaScript刷题参考用. 二叉查找树和平衡二叉树 其它树:满二叉树.完全二叉树.完美二叉树.哈弗曼树.二叉查找树BST.平衡二叉树AVL 了解:红黑树,是一种特殊的二叉树.这种树可以进行高 ...

随机推荐

  1. WPF滚动条嵌套,响应鼠标滑轮事件的处理

    在C# 中,两个ScrollViewer嵌套在一起或者ScrollViewer里面嵌套一个ListBox.Listview(控件本身有scrollviewer)的时候,我们本想要的效果是鼠标滚动整个S ...

  2. github page的两种类型

    1. 什么是Github ? Github 官方主页 简单说,Github是一个基于git的社会化代码分享社区. 你可以在Github上创建免费的远程仓库(remote repository),分享你 ...

  3. Delphi Android 将Google ZXing 整合(调用Jar文件)

    前篇文章介绍了在delphi App(以下简称App)中可使用intent来调用Google ZXing 条码扫描器(以下简称zx),其各有优缺点,优点是我们不需关注zx本身的细节,只需调用其接口即可 ...

  4. Win8Metro(C#)数字图像处理--2.5图像亮度调整

    原文:Win8Metro(C#)数字图像处理--2.5图像亮度调整  2.5图像亮度调整函数 [函数名称] 图像亮度调整函数BrightnessAdjustProcess(WriteableBit ...

  5. mysql的命令行安装,忘记密码,密码重置问题

    1.下载,安装msi 2.在MYSQL安装目录下,新建data目录 3.进入MYSQL的安装目录下,新建一个默认配置文件my.ini [mysql] # 设置mysql客户端默认字符集 default ...

  6. 程序定义了多个入口点。使用 /main (指定包含入口点的类型)进行编译

    原文:请使用/main进行编译,以指定包含入口点类型 在使用VS工具初学C#的时候需要不停的写小程序,觉得每次都新建项目太过麻烦,所以试着把程序写在一个项目下面,结果编译的时候出错了,因为我每个小程序 ...

  7. Win10《芒果TV》商店版更新v3.2.4:新增跨年事件直播、电视台直播,新年快乐

    听说半个娱乐圈都来了,<芒果TV>UWP版邀您一起,于2016年12月31日晚,观看<湖南卫视2016·2017跨年演唱会>直播,请更新v3.2.4版,主要新增大事件直播和电视 ...

  8. EnterpriseLibrary 6.0 AOP 使用问题

    因为EnterPrise Library 6.0改动了模块的功能类不再自动从Unity创建了,也就是引导也不依赖Unity容器组件,需要先使用静态方法注册一下 private static void ...

  9. Delphi中Menu设置Images属性后快捷按键下划线被隐藏解决方法

    现象:MainMenu设置Images属性后,看不到快捷按键的下划线,如:新建(&N) 分析:VCL中Menus.pas单元的代码,看到如下语句procedure TMenuItem.Adva ...

  10. Windows窗体原理及控件WM_DRAWITEM和子类化重绘演示文件

    http://download.csdn.net/detail/wenzhou1219/6783959