先看一个问题

将数列 {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 指向的是后继节点.

代码实现:

 class BinaryTree {
private HeroNode root;
privateHeroNode pre=null;
public void threadNodes() {
threadNodes(root);
}
public void threadNodes(HeroNode node) {
if(node==null) {
return;
}
threadNodes(node.getLeft());
if(node.getLeft()==null){
node.setLeft(pre);
node.setLeftType(1);
}
if(pre!=null&&pre.getRight()==null) {
pre.setRight(node);
pre.setRightType(1); }
pre=node;
threadNodes(node.getRight());}}

代码

 public class BinaryTreeDemo {
public static void main(String[] args) {
BinaryTree binaryTree = new BinaryTree();
HeroNode root = new HeroNode(1, "jack");
HeroNode node1 = new HeroNode(3, "tom");
HeroNode node2 = new HeroNode(6, "mike"); root.setLeftNode(node1);
root.setRightNode(node2);
binaryTree.setRoot(root); HeroNode node3 = new HeroNode(8, "林冲");
HeroNode node4 = new HeroNode(10, "关胜");
node1.setLeftNode(node3);
node1.setRightNode(node4);
HeroNode node5 = new HeroNode(14, "jerry");
node2.setLeftNode(node5); System.out.println("---中序---");
binaryTree.infixOrder();
//中序线索化二叉树
binaryTree.threadNodes(); HeroNode afterHeroNode10 = node4.getRight();
System.out.println(afterHeroNode10);// no=1 name=jack ok了
}}

测试

遍历线索化二叉树

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

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

 //遍历线索化二叉树的方法
public void threadedList() {
//定义一个变量,存储当前遍历的结点,从root开始
HeroNode node = root;
while(node != null) {
//循环的找到leftType == 1的结点,第一个找到就是8结点
//后面随着遍历而变化,因为当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(); }
}

代码

 public static void main(String[] args) {
//测试一把中序线索二叉树的功能
HeroNode root = new HeroNode(1, "tom");
HeroNode node2 = new HeroNode(3, "jack");
HeroNode node3 = new HeroNode(6, "smith");
HeroNode node4 = new HeroNode(8, "mary");
HeroNode node5 = new HeroNode(10, "king");
HeroNode node6 = new HeroNode(14, "dim"); //二叉树,后面我们要递归创建, 现在简单处理使用手动创建
root.setLeft(node2);
root.setRight(node3);
node2.setLeft(node4);
node2.setRight(node5);
node3.setLeft(node6); //测试中序线索化
ThreadedBinaryTree threadedBinaryTree = new ThreadedBinaryTree();
threadedBinaryTree.setRoot(root);
threadedBinaryTree.threadedNodes(); //测试: 以10号节点测试
HeroNode leftNode = node5.getLeft();
HeroNode rightNode = node5.getRight();
System.out.println("10号结点的前驱结点是 =" + leftNode); //
System.out.println("10号结点的后继结点是=" + rightNode); //1 //当线索化二叉树后,能在使用原来的遍历方法
//threadedBinaryTree.infixOrder();
System.out.println("使用线索化的方式遍历 线索化二叉树");
threadedBinaryTree.threadedList(); // 8, 3, 10, 1, 14, 6 }

测试

数据结构与算法---线索化二叉树(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. C#并口热敏小票打印机打印位图

    原文:C#并口热敏小票打印机打印位图 最近一直在研究并口小票打印机打印图片问题,这也是第一次和硬件打交道,不过还好,最终成功了.   这是DEMO的窗体:   下面是打印所需要调用的代码: class ...

  2. Android指纹识别

    原文:Android指纹识别 上一篇讲了通过FingerprintManager验证手机是否支持指纹识别,以及是否录入了指纹,这里进行指纹的验证. //获取FingerprintManager实例 F ...

  3. win10应用程序添加到开机启动项的两种解决办法

    原文 win10应用程序添加到开机启动项的两种解决办法 在windows10系统中,如果想让应用程序在开机之后自动运行起来,可以怎么做呢? 方法一: 1.首先创建应用程序的快捷方式 找到自己想加入开机 ...

  4. WPF Aero Glass Window

    原文:WPF Aero Glass Window 用法 Win7 DwmSetWindowAttribute function Win10 SetWindowCompositionAttribute ...

  5. 重写QLineEdit,实现编辑框内添加删除按钮的功能(随时把控件Move到一个地方,然后show就可以了,这是万能的办法)

    http://www.qtcn.org/bbs/read-htm-tid-62265-ds-1-page-1.html#180286

  6. FrieMonkey获取手机的IMSI等信息

    procedure THeaderFooterForm.FormCreate(Sender: TObject); var TelephonyManager: JTelephonyManager; Te ...

  7. C++迭代器 iterator

    1. 迭代器(iterator)是一中检查容器内元素并遍历元素的数据类型.(1) 每种容器类型都定义了自己的迭代器类型,如vector:vector<int>::iterator iter ...

  8. easyui在IE中: SCRIPT1003: 缺少 ':'

  9. XP下安装ubuntu

    一,环境说明 dell vostro 1400笔记本,winxp sp3操作系统,ubuntu-9.10-desktop-i386.iso 写这篇随笔的时候我用的已经是ubuntu了. 我是在我的移动 ...

  10. SYN2136型 北斗NTP网络时间服务器

    SYN2136型  北斗NTP网络时间服务器 北斗NTP网络时间服务器时间服务器使用说明视频链接: http://www.syn029.com/h-pd-109-0_310_36_-1.html 请将 ...