每一个结点的左指针指向其左子结点或前驱结点,右指针指向其右子结点或后继结点,这样可以构成一个线索化二叉树。为了方便后续的操作,我们需要将其指针指向的两种类型区分开。同时在遍历的过程中,由于我们无法由子结点得到前驱结点或者父结点,需要一个pre结点保存遍历的前一个结点。
public class ThreadedBinaryTreeDemo {
public static void main(String[] args) {
// 测试一把中序线索二叉树的功能
Book0 root = new Book0(1, "Joker");
Book0 book2 = new Book0(2, "No face man");
Book0 book3 = new Book0(3, "Traveler");
Book0 book4 = new Book0(4, "Immortal");
Book0 book5 = new Book0(5, "Red sacrifices");
Book0 book6 = new Book0(6, "Light trap");
Book0 book7 = new Book0(7, "Handed man");
root.setLeft(book2);
root.setRight(book3);
book2.setLeft(book4);
book2.setRight(book5);
book3.setLeft(book6);
ThreadedBinaryTree threadedBinaryTree = new ThreadedBinaryTree();
threadedBinaryTree.setRoot(root);
threadedBinaryTree.threadedNodes();
Book0 leftNode = book5.getLeft();
Book0 rightNode = book5.getRight();
System.out.println("5号结点的前驱结点是:" + leftNode);
System.out.println("5号结点的后续结点是:" + rightNode);
System.out.println("使用线索化的方式遍历线索化二叉树");
threadedBinaryTree.threadedList();
}
}
class ThreadedBinaryTree {
private Book0 root;
// 为了实现线索化,需要创建要指向当前结点的前驱结点的指针
// 在递归进行线索化时,pre总是保留前一个结点
private Book0 pre;
public void setRoot(Book0 root) {
this.root = root;
}
public void threadedNodes() {
this.threadedNodes(root);
}
// 编写对二叉树进行中序线索化的方法
/*
* node就是当前需要线索化的结点
*/
public void threadedNodes(Book0 node) {
// 如果node==null,不能线索化
if (node == null) {
return;
}
// 1、先线索化左子树
threadedNodes(node.getLeft());
// 2、线索化当前结点
if (node.getLeft() == null) {
// 让当前结点的左指针指向前驱结点
node.setLeft(pre);
// 修改当前结点左指针类型
node.setLeftType(1);
}
// 处理后继结点
if (pre != null && pre.getRight() == null) {
// 让前驱结点的右指针指向当前结点
pre.setRight(node);
// 修改前驱结点的右指针类型
pre.setRightType(1);
}
// 每处理一个结点后,让当前结点是下一个结点的前驱结点
pre = node;
// 3、线索化右子树
threadedNodes(node.getRight());
}
// 遍历线索化二叉树的方法
public void threadedList() {
Book0 node = root;
while (node != null) {
// 循环的找到leftType==1的结点,第一个找到就是4结点
// 后面随着遍历而变化,因为当leftType==1时,说明该结点是按照线索化
// 处理后的有效结点
while (node.getLeftType() == 0) {
node = node.getLeft();
}
System.out.println(node);
// 如果当前结点的右指针指向的是后继结点,就一直输出
// 不是后继节点就退出循环,获得其真实指向的右结点
while (node.getRightType() == 1) {
node = node.getRight();
System.out.println(node);
}
// 替换这个遍历的结点
node = node.getRight();
}
}
}
class Book0 {
private int no;
private String name;
private Book0 left;
private Book0 right;
// 说明:
// 1、如果leftType==0表示指向的是左子树,如果1则表示指向前驱结点
// 2、如果rightType==0表示指向的是右子树,如果1表示指向后继结点
private int leftType;
private int rightType;
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;
}
public Book0(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Book0 getLeft() {
return left;
}
public void setLeft(Book0 left) {
this.left = left;
}
public Book0 getRight() {
return right;
}
public void setRight(Book0 right) {
this.right = right;
}
@Override
public String toString() {
return "Book [no=" + no + ", name=" + name + "]";
}
}