顺序存储二叉树以及线索化二叉树

目录

今日良言:丈夫志四海,万里犹比邻。

一、顺序存储二叉树

1.顺序存储二叉树介绍

2.实现思路分析

3.效果展示

二、线索化二叉树

1.线索化二叉树介绍

2.中序线索化实现思路

3.遍历线索化二叉树


今日良言:丈夫志四海,万里犹比邻。

一、顺序存储二叉树

1.顺序存储二叉树介绍

顺序存储二叉树指的是使用数组存储二叉树。注:顺序存储二叉树只能适用于完全二叉树,所以说,如果想对普通二叉树进行顺序存储,需要提前将普通二叉树转换成完全二叉树。

2.实现思路分析

以数组arr[] = {1,2,3,4,5,6,7} 为例进行分析,如果构建成二叉树的话如下图:

每个结点下面蓝色的数字代表其在数组中的下标。

创建一个ArrayBinaryTree 类,该类中有一个私有属性arr数组,同时提供其构造方法。

1. 然后我们对于数组以二叉树的形式进行前中后序遍历,这里只进行前序遍历分析,中序以及后续遍历其实与前序遍历的核心思路是一样的。

2.创建一个带有整型参数的方法进行前序遍历,第一步需要在该方法中先对数组进行判断,如果为空或者长度为0就说明数组为空,无法进行前序遍历。传入的整型参数是数组下标。

3.第一次传入的就是数组的0下标,那么,对于前序遍历而言,先打印当前位置的结点,也就是数组下标数据,那么如何递归打印其左右子树呢?这里就需要说明一下顺序存储二叉树的特点: 当前结点下标如果为index,那么其左孩子结点的下标为 :2 *index  + 1  右孩子结点的下标为:2 * index + 2   其父节点的下标为: (index - 1) / 2  ,根据这个特性,我们进行前序遍历时,左子树递归的条件就是:当该结点的左孩子结点的下标不越界时,就进行递归打印,右孩子结点同理。

将上述操作转换成如下代码:

3.效果展示

还是以数组arr[] = {1,2,3,4,5,6,7}为例

前序遍历:

中序遍历

 后序遍历:

完整代码在github中如下链接:

java-/ArrayBinaryTree at master · mhy2656810734/java- (github.com)

二、线索化二叉树

1.线索化二叉树介绍

线索化二叉树其实是对普通二叉树的扩展,对于一个普通二叉树的结点而言,一般包括一个数据域和两个指针域,线索化二叉树实际上是将普通二叉树的结点未利用的指针域重新利用,使其指向前驱结点或者后继结点。

我们用如下图来分析:

观察上图数据为10的结点会发现,该结点的左右指针域都未被利用。我们使用中序线索化的方法来分析,上图二叉树中序遍历的顺序是: 8 3 10 1 14 6 。  对于结点10而言,该结点的前驱节点是3,后继节点是1 。所以说我们对该二叉树线索化以后,10的L、R指针域分别指向结点3 和 结点1,线索化后的二叉树就是如下图:

 值得一提的是:含有n个结点的二叉树,未被利用的空指针域为 n+1 个,就上图而言,共6个结点,未被利用的空指针域为 7 个。

2.中序线索化实现

1.首先,我们需要创建好一个结点类,包含如下属性,同时重写打印方法,get和set和构造方法也要提供。

其它属性都好理解,这里说明一下这个 leftType 和 rightType属性,这两个属性代表的是当前这个结点的左指针域和右指针域指向的是左右子树 还是 前驱或者后继节点,取出两个结点进行说明。如上图中的结点3和结点10,当线索化以后,由于结点3的左右指针域都已经指向 左右子树,所以leftType 和 rightType 默认为0无需修改,而对于结点10而言,线索化以后,该结点的左右指针域分别指向前驱和后继节点,那么就需要修改该leftType 和 rightType 的值为1。

2.我们创建一个线索化二叉树,首先需要明白这个类中含有的属性,首先,根节点必不可少,然后提供一个根节点root的set方法。 我这里只实现了中序线索化二叉树,所以我们以中序线索化二叉树为例,我们第一个需要处理的结点是8这个结点,结点8的前驱结点为空,结点8有后继节点,我们需要处理,但是,如果只有一个结点8我们是没有办法让其指向它的后继节点,所以说,还需要一个属性prev表示当前处理结点的前一个结点,所以,当prev 的右指针域为空时,让prev的右指针域指向当前结点节课。

所以,该线索化二叉树类有如下属性:

上述线索化用图解的方式如下:

 上述操作转换成如下代码:

3.遍历线索化二叉树

对于线索化后的二叉树,我们还能像以前中序遍历普通二叉树的方法遍历吗?显然是行不通的,因为线索化后的二叉树,每个结点的左右指针域都不为空,只进行判空进行对左右子树进行递归显然不合适,所以说,我们需要分析一下如何对于线索化后的二叉树进行遍历。

当然,遍历的起点是根节点1,我们创建一个结点node来辅助遍历,其实,我们可以根据每个结点的leftType 和 rightType 的值进行操作,首先,我们需要找到第一个leftType的值不为0的结点,说明这个结点就是第一个被处理的结点,我们打印该结点,上述实例中第一个打印的结点是8,后续结点如何打印呢? 其实,结点8的 rightType值也被修改过了,可以根据这个性质进行打印,最后需要注意的是, 上述操作显然是一个循环,我们在最后对node进行修改。

上述操作转换为如下代码:

下面是github完整代码链接:

java-/ThreadedTree at master · mhy2656810734/java- (github.com)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值