声明
线索二叉树结点中含有五个变量,分别是该结点存储的值,该结点指向的左右结点,该结点左右两边的索引值,当左右索引值为 false 就表示左右指向正常的孩子结点,若为 true 表示左右指向前驱或者后继结点
为什么要线索化二叉树呢?
我们知道对于一个满二叉树来讲,其叶子结点为2^(n-1)
个,这些叶子空指针域有2^n
个,这个 n 是树的深度,我们可以利用这些空指针域来存放一些有意义的信息
为什么我没写后序遍历线索二叉树?
后序的话有些麻烦,建议把后序的左右根通过倒序的根右左来遍历,然后再倒序即可,这个根右左的写法和先序就很类似了
Java 实现// 结点
class Node {
int data;
// 左索引
boolean leftType;
Node left = null;
// 右索引
boolean rightType;
Node right = null;
}
// 线索二叉树
public class ThreadedBinaryTree {
// 根结点
private Node root;
// 前驱结点
private Node pre;
// 输入的数组
private int[] arr_in;
// 输出的数组
private int[] arr_out;
// 记录数组下标
private static int index;
// 初始化
public ThreadedBinaryTree(int[] arr) {
root = new Node();
pre = null;
this.arr_in = arr;
arr_out = new int[arr.length];
index = 0;
}
// 先序线索化二叉树
public Node preThreading(Node r) {
if (r) {
if (r.left == null) {
r.leftType = true;
r.left = pre;
}
else
r.leftType = false;
if (pre.right == null) {
pre.rightType = true;
pre.right = r;
}
else
pre.rightType = false;
pre = r;
preThreading(r.left);
preThreading(r.right);
}
return r;
}
// 中序线索化二叉树
public Node inThreading(Node r) {
if (r) {
preThreading(r.left);
if (r.left == null) {
r.leftType = true;
r.left = pre;
}
else
r.leftType = false;
if (pre.right == null) {
pre.rightType = true;
pre.right = r;
}
else
pre.rightType = false;
pre = r;
preThreading(r.right);
}
return r;
}
// 后序线索化二叉树
public void postThreading(Node r) {
if (r) {
preThreading(r.left);
preThreading(r.right);
if (r.left == null) {
r.leftType = true;
r.left = pre;
}
else
r.leftType = false;
if (pre.right == null) {
pre.rightType = true;
pre.right = r;
}
else
pre.rightType = false;
pre = r;
}
return r;
}
// 先序遍历线索二叉树
public void preTraverse(Node r) {
Node n = r;
while (n) {
System.out.println(n.data);
while (!n.leftType) {
n = n.left;
System.out.println(n.data);
}
n = n.right;
}
}
// 中序遍历线索二叉树
public void inTraverse(Node r) {
Node n = r;
while (n) {
while (!n.leftType)
n = n.left;
System.out.println(n.data);
while (n.rightType) {
n = n.right;
System.out.println(n.data);
}
n = n.right;
}
}
}