八、线索二叉树
1、概念
n个节点的二叉树中含有 n + 1 ==> 2n - (n - 1)
个空指针(没有指向任何节点,一般是叶子节点),将这些节点,在某种遍历次序下
,与其前一个结点(前驱节点
,一般是父节点)或后一个节点(后继节点
,一般是父节点)连接,这种连接的指针被称之为线索
。
所以线索二叉树又分为:前序线索二叉树、中序线索二叉树和后序线索二叉树
1
2 3
4 5 6
4的左指针为空,右指针指向2
5的左指针指向2,右指针指向1
6的左指针指向1,右指针指向3
1
2 3
4 5 6
4的左指针指向2,右指针指向1
5的左指针指向1,右指针指向3
6的左指针指向3,右指针为空
2、示例
class ThreadedBinaryTree<T> {
private TreeNode<T> root;
/**
* 指向前一个节点
*/
private TreeNode<T> preNode = null;
public ThreadedBinaryTree(TreeNode<T> root) {
this.root = root;
}
public void infixOrderThreadTree() {
infixOrderThreadTree(root);
}
/**
* 中序线索化树
*/
private void infixOrderThreadTree(TreeNode<T> node) {
if (null == node) {
return;
}
infixOrderThreadTree(node.getLeft());
// 当前是叶子节点,且其前驱节点为空
if (null == node.getLeft()) {
node.setLeft(preNode); // 叶子节点的前驱节点,指向前节点
node.setLeftType(1);
}
// 前节点是叶子节点,且其后继节点为空
if (null != preNode && null == preNode.getRight()) {
preNode.setRight(node); // 前节点的后继节点,指向当前节点
preNode.setRightType(1);
}
// 更新前节点,为当前节点,并继续遍历下一个节点
preNode = node;
infixOrderThreadTree(node.getRight());
}
public void preOrder() {
TreeNode<T> node = root;
while (null != node) {
// 输出根/右子节点
System.out.print(node.getData() + " ");
// 遍历寻找左子节点
while (0 == node.getLeftType()) {
node = node.getLeft();
// 输出左子节点
System.out.print(node.getData() + " ");
}
// 遍历寻找右叶子节点
while (1 == node.getRightType()) {
node = node.getRight();
}
// 指向右子节点
node = node.getRight();
}
System.out.println();
}
public void infixOrder() {
TreeNode<T> node = root;
while (null != node) {
// 遍历寻找左子节点
while (0 == node.getLeftType()) {
node = node.getLeft();
}
// 输出左叶子节点
System.out.print(node.getData() + " ");
// 遍历寻找右叶子节点
while (1 == node.getRightType()) {
node = node.getRight();
// 输出右叶子节点
System.out.print(node.getData() + " ");
}
// 指向右子节点
node = node.getRight();
}
System.out.println();
}
}
class TreeNode<T> {
private final T data;
private TreeNode<T> left;
private TreeNode<T> right;
/**
* 0-左子节点,1-前驱节点
*/
private int leftType;
/**
* 0-右子节点,1-后继节点
*/
private int rightType;
public TreeNode(T data) {
this.data = data;
}
public T getData() {
return data;
}
public TreeNode<T> getLeft() {
return left;
}
public void setLeft(TreeNode<T> left) {
this.left = left;
}
public TreeNode<T> getRight() {
return right;
}
public void setRight(TreeNode<T> right) {
this.right = right;
}
public int getLeftType() {
return leftType;
}
public void setLeftType(int leftType) {
this.leftType = leftType;
}
public int getRightType() {
return rightType;
}
public void setRightType(int rightType) {
this.rightType = rightType;
}
}
class Test {
public static void main(String[] args) {
ThreadedBinaryTree<Integer> tree = new Test().createBinaryTree();
tree.infixOrderThreadTree();
tree.preOrder(); // 1 2 4 5 3 6
tree.infixOrder(); // 4 2 5 1 6 3
}
/**
* 1
* 2 3
* 4 5 6
*/
private ThreadedBinaryTree<Integer> createBinaryTree() {
TreeNode<Integer> one = new TreeNode<Integer>(1);
TreeNode<Integer> two = new TreeNode<Integer>(2);
TreeNode<Integer> three = new TreeNode<Integer>(3);
TreeNode<Integer> four = new TreeNode<Integer>(4);
TreeNode<Integer> five = new TreeNode<Integer>(5);
TreeNode<Integer> six = new TreeNode<Integer>(6);
one.setLeft(two);
one.setRight(three);
two.setLeft(four);
two.setRight(five);
three.setLeft(six);
return new ThreadedBinaryTree<Integer>(one);
}
}