线索二叉树的后序遍历
因为我们需要在后序遍历时得到结点的父节点,所以需要一个新的指针指向
父节点private HeroNode parent;
/**
* 节点HeroNode
*/
class HeroNode{
private int no;
private String name;
/**
* left:默认为空
* right:默认为空
*/
private HeroNode left;
private HeroNode right;
public HeroNode getParent() {
return parent;
}
public void setParent(HeroNode parent) {
this.parent = parent;
}
private HeroNode parent;
/**
* 如果leftType==0表示指向左子树,如果1则表示指向前驱结点
* 如果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 HeroNode(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 HeroNode getLeft() {
return left;
}
public void setLeft(HeroNode left) {
this.left = left;
}
public HeroNode getRight() {
return right;
}
public void setRight(HeroNode right) {
this.right = right;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
创建后序线索二叉树:
/**
* 编写对二叉树后序线索化的方法
* @param node 就是当前需要线索化的结点
*/
public void postThreadedNodes(HeroNode node){
//如果node==null,不能线索化
if (node==null){
return;
}
//1.先线索化左子树
postThreadedNodes(node.getLeft());
//2.再线索化右子树
postThreadedNodes(node.getRight());
//3.线索化当前节点 (难点)
//处理前驱节点
if (node.getLeft()==null){
node.setLeft(pre);
//修改当前结点的左指针的类型
node.setLeftType(1);
}
//处理后继结点
if (pre!=null&&pre.getRight()==null){
//让前驱节点的右指针指向当前节点
pre.setRight(node);
//修改前驱节点的右指针类型
pre.setRightType(1);
}
//!! 每处理一个节点后,让当前结点是下一个节点的前驱结点
pre=node;
}
后序线索二叉树的遍历:
/**
* 后序遍历线索二叉树的方法
*/
public void postThreadedList() {
HeroNode node = root;
while (node != null && node.getLeftType() == 0) {
node = node.getLeft();
}
while (node != null) {
//后继已经线索化的直接打印
if (node.getRightType() == 1) {
System.out.println(node);
pre = node;
node = node.getRight();
} else {
if (node.getRight() == pre) {
System.out.println(node);
//注意如果这个子树的根节点为树的根节点,遍历结束
if (node == root) {
return;
}
pre = node;
//且当前结点置换为父节点,否则继续右线索会导致死循环
node = node.getParent();
} else {
//左子树回调的则不会有死循环的风险,直接左线索遍历
node = node.getRight();
while (node != null && node.getLeftType() == 0) {
node = node.getLeft();
}
}
}
}
}
测试:
public static void main(String[] args) {
HeroNode root = new HeroNode(1, "tom");
HeroNode node2 = new HeroNode(3, "Z");
HeroNode node3 = new HeroNode(6, "T");
HeroNode node4 = new HeroNode(8, "J");
HeroNode node5 = new HeroNode(10, "H");
HeroNode node6 = new HeroNode(14, "G");
//二叉树我们后面要自动创建,现在简单处理使用手动创建
root.setLeft(node2);
root.setRight(node3);
node2.setLeft(node4);
node2.setRight(node5);
node3.setLeft(node6);
node2.setParent(root);
node3.setParent(root);
node4.setParent(node2);
node5.setParent(node2);
node6.setParent(node3);
//测试中序线索化
ThreadedBinaryTree threadedBinaryTree = new ThreadedBinaryTree();
threadedBinaryTree.setRoot(root);
threadedBinaryTree.postThreadedNodes(root);
//以10号节点测试
System.out.println(node4.getLeftType());
System.out.println("10号的前驱节点是:"+node2.getLeft());
System.out.println("10号的后继结点的:"+node2.getRight());
System.out.println("线索化方式遍历二叉树:");
threadedBinaryTree.postThreadedList();
}