1. 引入
2. 基本介绍
- n 个结点的二叉链表中含有 n+1 个空指针域
- 利用二叉链表中的空指针域,存放指向该结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索")
- 一个结点的前一个结点,称为“前驱结点”
- 一个结点的后一个结点,称为“后继结点”
- 这种加上了线索的二叉链表称为线索链表,相应的二叉树称为“线索(Threaded) 二叉树”。根据线索性质的不同,线索二叉树又可分为:
- 前序线索二叉树
- 中序线索二叉树
- 后序线索二叉树
3. 案例
3.1 中序线索化二叉树
3.2 遍历线索化二叉树
4. 代码实现
public class ThreadedBinaryTreeDemo {
public static void main(String[] args) {
ThreadedBinaryTree tree = new ThreadedBinaryTree();
Node root = new Node(1);
Node node3 = new Node(3);
Node node6 = new Node(6);
Node node8 = new Node(8);
Node node10 = new Node(10);
Node node14 = new Node(14);
root.left = node3;
root.right = node6;
node3.left = node8;
node3.right = node10;
node6.left = node14;
tree.root = root;
tree.midThreadedNodes();
System.out.println("node10-left: " + node10.left);
System.out.println("node10-right: " + node10.right);
tree.midOrderThreadedBiTree();
}
}
// 实现了线索化功能的二叉树
class ThreadedBinaryTree{
public Node root;
/*
* 为了实现线索化, 需要创建 1 个指向当前结点的前驱结点的引用
* 在递归进行线索化时, preNode 总是指向前一个结点
*/
public Node preNode;
public void midThreadedNodes() {
midThreadedNodes(root);
}
// 中序线索化
public void midThreadedNodes(Node node) {
if (node == null) return;
// 1. 线索化左子树
midThreadedNodes(node.left);
// 2. 线索化当前结点
// 2.1 处理当前结点的前驱结点
if (node.left == null) {
// 修改当前结点的左指针类型
node.leftType = 1;
// 当前结点的左指针指向中序遍历时的前驱结点
node.left = preNode;
}
// 2.2 处理(上一个结点的)后继结点
if (preNode != null && preNode.right == null) {
// 修改上一个结点的右指针类型
preNode.rightType = 1;
// 上一个结点的右指针指向当前结点
preNode.right = node;
}
// 2.3* 每处理完一个结点, 便让当前结点成为下一个待处理结点的前驱结点
preNode = node;
// 3. 线索化右子树
midThreadedNodes(node.right);
}
// 中序遍历
public void midOrderThreadedBiTree() {
// 存储当前遍历的结点
Node node = root;
while (node != null) {
// leftType = 1说明该结点是按照线索化处理后的有效结点
while (node.leftType == 0) // 第一个找到的是[8]
node = node.left;
// 退出循环则说明找到了leftType = 1的结点, 打印当前结点即可
System.out.println(node);
// 如果当前结点的右指针指向后继结点, 就输出
while (node.rightType == 1) {
node = node.right;
System.out.println(node);
}
node = node.right;
}
}
}
class Node {
public int no;
public Node left;
public Node right;
/*
* leftType = 0, 表示指向左子树
* = 1, 表示指向前驱结点
* rightType = 0, 表示指向右子树
* = 1, 表示指向后继结点
*/
public int leftType;
public int rightType;
public Node(int no) {
this.no = no;
}
@Override
public String toString() {
return "[no=" + no + "]";
}
}
[待补充] 前序线索化二叉树和后序线索化二叉树及有关遍历