13.3.1 遍历中序线索树
**说明:**对前面的中序先躲的二叉树,进行遍历
**分析:**因为线索化后,各个结点指向有变化,因此原来的遍历方式不能使用这时需要使用新的方式遍历线索化二叉树,各个节点可以通过线性方式遍历。因此无需使用递归方式,这样也提高了便利的效率。 遍历的次序应当和中序遍历保持一致
package tree.threadedbinarytree;
public class ThreadedBinaryTreeDemo {
public static void main(String[] args) {
// 测试 把中序线索二叉树
Node1 root = new Node1(1, "12");
Node1 node2 = new Node1(3, "13");
Node1 node3 = new Node1(6, "16");
Node1 node4 = new Node1(8, "18");
Node1 node5 = new Node1(10, "114");
Node1 node6 = new Node1(14, "114");
// 二叉树后面要递归创建,现在手动创建
root.setLeft(node2);
root.setRight(node3);
node2.setLeft(node4);
node2.setRight(node5);
node3.setLeft(node6);
// 测试中序线索化
infixThreadedBinaryTree infixThreadedBinaryTree = new infixThreadedBinaryTree();
infixThreadedBinaryTree.setRoot(root);
infixThreadedBinaryTree.threadeNodes();
// 测试:以10号结点为测试
Node1 leftNode = node5.getLeft();
Node1 rightNode = node5.getRight();
System.out.println("10号结点的前驱结点时:" + leftNode);
System.out.println("10号结点的后继结点" + rightNode);
System.out.println("使用线索化的方式遍历 线索化二叉树");
infixThreadedBinaryTree.infixThreadedList();
}
}
// 线索化二叉树 实现了线索化功能的二叉树
class infixThreadedBinaryTree{
private Node1 root;
// 为了实现线索化,需要创建要给指向当前节点的前驱结点的指针
// 在递归的进行线索时,pre 总是保留一个结点
private Node1 pre = null;
// 遍历中序线索二叉树
public void infixThreadedList(){
// 定义一个变量,存储当前遍历的节点,从root开始
Node1 node = root;
while(node != null){
// 循环的找到leftType == 1的节点,第一个找到的就是8
// 后面随着遍历node会变化,
// 因为当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();
}
}
// 重载一把threadeNodes方法
public void threadeNodes(){
this.threadedNodes(root);
}
// 编写二叉树进行中序线索化的方法
/**
*
* @param node 就是当前需要线索化的结点
*/
public void threadedNodes(Node1 node){
// 如果 node == null,不能进行线索化
if (node == null){
return;
}
// 1. 先线索化左子树
threadedNodes(node.getLeft());
// 2. 线索化当前结点
// 2.1 先处理当前节点的前驱结点
if (node.getLeft() == null){
// 让当前节点的左指针指向前驱结点
node.setLeft(pre);
// 修改当前节点的左指针的类型,指向前驱结点
node.setLeftType(1);
}
// 2.2 处理当前节点的后继结点
if (pre != null && pre.getRight() == null){
// 让前驱结点的右指针指向当前结点
pre.setRight(node);
// 修改前驱结点的右指针类型
pre.setRightType(1);
}
// 没处理一个节点后,让当前结点时下一个节点的前驱结点
pre = node;
// 3. 再线索化右子树
threadedNodes(node.getRight());
}
}
// 先创建节点
class Node1{
private int id;
private String name;
private Node1 left;
private Node1 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 Node1(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Node1 getLeft() {
return left;
}
public void setLeft(Node1 left) {
this.left = left;
}
public Node1 getRight() {
return right;
}
public void setRight(Node1 right) {
this.right = right;
}
@Override
public String toString() {
return "Node1{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}