数据结构与算法:树 线索化二叉树(中,前,后序)
Posted android超级兵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法:树 线索化二叉树(中,前,后序)相关的知识,希望对你有一定的参考价值。
Tips: 采用java语言,关注博主,底部附有完整代码
工具:IDEA
本系列介绍的是数据结构: 树
这是第三篇目前计划一共有12篇:
- 二叉树入门
- 顺序二叉树
- 线索化二叉树 (本篇)
- 堆排序
- 赫夫曼树(一)
- 赫夫曼树(二)
- 赫夫曼树(三)
- 二叉排序树
- 平衡二叉树
- 2-3树,2-3-4树,B树 B+树 B*树 了解
- 红黑树(一)
- 红黑树(二)
敬请期待吧~~
高光时刻
中序线索化 | 前序线索化 | 后续线索化 |
---|---|---|
回顾
先来回顾一下中序遍历
每一个结点有2个对象,最终导致叶子结点就有所浪费
当前一共有6个元素,分别是 [1,3,6,8,10,14], 最终就会导致有7个对象浪费(null)掉
出现问题
线索化二叉树就是尽量少浪费对象,那么空对象如何处理呢?
如何解决
先来看完整流程图,在逐步分析:
最终结果图:
中序线索化二叉树 就是按照中序遍历的结果将
- 叶子结点
- 单子结点
按照中序的排列连接起来
当前中序遍历结果是 [8, 3, 10, 1, 14, 6]
以10举例,10是叶子结点,那么就按照中序遍历10左右的结点连接起来
- 10左侧的值3 当作10的左子结点
- 10右侧的值1 当作10的右子结点
因为10是叶子结点,如果连接起来的也叫左子结点和右子结点容易和真正有左子/右子结点的结点搞混
所以在线索化中,如果是通过连接连起来的就叫做前驱结点 和 后继结点
例如 :
-
10的前驱结点是3
-
10的后继结点是1
-
8的前驱结点是null
-
8的后继结点是3
-
3的左子结点是8
-
3的右子结点是10
先按照树状图来看结点,如果他有左子结点或者右子结点,那么就按照排列好的顺序来,就是前驱结点和后继结点
直接来看一眼代码
中序
中序线索化
结点:
public class HeroNode
public int id;
public String name;
// 左子结点
public HeroNode leftNode;
// 右子结点
public HeroNode rightNode;
// [0 左子节点] [1 前驱节点]
public int leftType;
// [0 右子节点] [1 后继节点]
public int rightType;
public HeroNode(int id, String name)
this.id = id;
this.name = name;
@Override
public String toString()
return "HeroNode" +
"id=" + id +
", name='" + name + '\\'' +
", leftType='" + leftType + '\\'' +
", rightType='" + rightType + '\\'' +
'';
Tree:
public class ThreadedBinaryTree
// root 结点
private final HeroNode root;
public ThreadedBinaryTree(HeroNode root)
this.root = root;
public void threadedCenter()
threadedCenter(root);
// 用于记录中序线索化上一个元素
private HeroNode centerPre;
public void threadedCenter(HeroNode node)
// 如果 node == null 就退出递归
if (node == null)
return;
// 线索化左子树
threadedCenter(node.leftNode);
// 处理左子树 如果 leftNode == null 就认为他是前驱结点
if (node.leftNode == null)
// 设置为前驱节点
node.leftNode = centerPre;
// 设置为前驱类型
node.leftType = 1;
// 处理右子树 如果rightNode == null 就认为他是后继结点
if (centerPre != null && centerPre.rightNode == null)
centerPre.rightNode = node;
// 设置为后继结点类型
centerPre.rightType = 1;
// pre后移
centerPre = node;
// 线索化右子树
threadedCenter(node.rightNode);
中序线索化遍历
public void showThreadedCenter(HeroNode node)
if (node == null)
return;
// 如果是左子结点就遍历
if (node.leftType == 0)
showThreadedPre(node.leftNode);
System.out.println(node);
// 如果是右子结点就遍历
if (node.rightType == 0)
showThreadedPre(node.rightNode);
中序线索化和普通树结构遍历是类似的,只需要判断是否是左子 / 右子结点即可!
前序
前序遍历 | 解决前 | 解决后 |
---|---|---|
可以看到前序遍历,如果前序线索化后,只浪费了一个结点 !
前序线索化
# ThreadedBinaryTree.java
// 记录前序线索化上一个元素
public HeroNode prePre;
public void threadedPre(HeroNode node)
// 如果node == null 就退出递归
if (node == null)
return;
// 和中序思路一样
if (node.leftNode == null)
node.leftNode = prePre;
node.leftType = 1;
if (prePre != null && prePre.rightNode == null)
prePre.rightNode = node;
prePre.rightType = 1;
prePre = node;
// 如果是左子结点点就去线索化 是前序结点就不走
if (node.leftType == 0)
// 线索化左子树
threadedPre(node.leftNode);
// 如果是右子结点就去线索化 是后继结点就不走
if (node.rightType == 0)
// 线索化右子树
threadedPre(node.rightNode);
// endregion
这里思路和中序线索化一样,就不过多赘述了,来看看遍历吧
前序线索化遍历
# ThreadedBinaryTree.java
// region TODO 前序线索化遍历
// @author: android 超级兵
// @create: 2022/6/8 09:55
//
public void showThreadedPre()
showThreadedPre(root);
public void showThreadedPre(HeroNode root)
if (root == null)
return;
System.out.println(root);
if (root.leftType == 0)
showThreadedPre(root.leftNode);
if (root.rightType == 0)
showThreadedPre(root.rightNode);
后续
后续遍历 | 线索前 | 线索后 |
---|---|---|
代码思路和前序一样:直接看
后续线索化
# ThreadedBinaryTree.java
/*
* 作者:android 超级兵
* 创建时间: 6/7/22 5:48 PM
*/
private HeroNode lastPre;
public void threadedLast()
threadedLast(root);
public void threadedLast(HeroNode node)
if (node == null)
return;
// 如果是左子结点才遍历
if (node.leftType == 0)
// 线索化左子树
threadedLast(node.leftNode);
// 如果是右子结点才遍历
if (node.rightType == 0)
// 线索化右子树
threadedLast(node.rightNode);
if (node.leftNode == null)
node.leftNode = lastPre;
node.leftType = 1;
if (lastPre != null && lastPre.rightNode == null)
lastPre.rightNode = node;
lastPre.rightType = 1;
lastPre = node;
//endregion
后续线索化遍历
# ThreadedBinaryTree.java
public void showThreadedLast()
showThreadedLast(root);
public void showThreadedLast(HeroNode root)
// 左子结点就遍历
if (root.leftType == 0)
showThreadedLast(root.leftNode);
// 右子结点就遍历
if (root.rightType == 0)
showThreadedLast(root.rightNode);
System.out.println(root);
原创不易,您的点赞就是对我最大的支持!
下一篇:堆排序[开发中…]
以上是关于数据结构与算法:树 线索化二叉树(中,前,后序)的主要内容,如果未能解决你的问题,请参考以下文章
数据结构与算法__07--前序中序后序线索化二叉树,前序中序后序线索化二叉树遍历(Java语言版本)
超强二叉树解析.必收藏!(数组,链表实现,8种遍历方法,前,中,后序线索化二叉树及其遍历)---风之java
算法系列之线索化二叉树,前序线索化中序线索化后序线索化以及遍历~