(1)概念:普通的二叉树遍历的时候左右指针并没有很好地利用,要完全利用每个结点的左右指针,就必须用到线索化二叉树。在遍历过程中使二叉树变成线索化二叉树的过程称为二叉树的线索化。在n个结点的二叉树中,有n+1个空链域,利用这些空链域存储某次遍历中结点的前续和后继结点。因为在特定的遍历方式下结点的遍历顺序是一定的。
(2)结点:
public class ClueNode {
private int no;
private String name;
private ClueNode left;
private ClueNode right;
/*
* 分别用两个标识符来表示是否有前驱和后继(在遍历中)
* 如果没有的化表明指向树结构中的左右子树
*/
private int flgLeft;
private int flgRight;
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 ClueNode getLeft() {
return left;
}
public void setLeft(ClueNode left) {
this.left = left;
}
public ClueNode getRight() {
return right;
}
public void setRight(ClueNode right) {
this.right = right;
}
public int getFlgLeft() {
return flgLeft;
}
public void setFlgLeft(int flgLeft) {
this.flgLeft = flgLeft;
}
public int getFlgRight() {
return flgRight;
}
public void setFlgRight(int flgRight) {
this.flgRight = flgRight;
}
@Override
public String toString() {
return "ClueNode [no=" + no + ", name=" + name + "]";
}
//删除结点
public void delNode(int no) {
if ((this.left!=null)&&(this.left.getNo()==no)) {
this.setLeft(null);return;
}
if ((this.right!=null)&&(this.right.getNo()==no)) {
this.right=null;
}
/*
* 注意递归的时候先判断是否为空
*/
if (this.left!=null) {
this.left.delNode(no);
}
if (this.right!=null) {
this.right.delNode(no);
}
}
//使用中序遍历所有
public void midList() {
if (this.left!=null) {
this.left.midList();
}
System.out.println(this);
if (this.right!=null) {
this.right.midList();
}
}
//使用中序根据编号查找结点
public ClueNode seaNode(int no) {
ClueNode node=null;
if (this.left!=null) {
node=this.left.seaNode(no);
if (node!=null) {
return node;
}
}
if (this.no==no) {
return this;
}
if (this.right!=null) {
node=this.right.seaNode(no);
if (node!=null) {
return node;
}
}
return node;
}
}
(3)线索二叉树的实现以及对其线索化
public class ClueBinaryTree {
private ClueNode root;
private ClueNode pre=null;
//当前结点的前驱
public ClueBinaryTree(ClueNode root) {
this.root=root;
}
//这个函数进行线索化
public void clue(ClueNode node) {
//判断当前结点是否为空
if (node==null) {
return;
}
//先从最左边的子树开始,遇到空的了自然会由上面的if语句返回
clue(node.getLeft());
//找到最左边没有前驱的结点,添加前驱
if (node.getLeft()==null) {
node.setLeft(pre);
node.setFlgLeft(1);
}
//处理当前结点的后继,因为现在是线索化左子树
//所以应该都有后继,可以pre下手,因为pre的后继就是node
if((pre!=null)&&(pre.getRight()==null)) {
pre.setRight(node);
pre.setFlgRight(1);
}
//直接把node给pre,相当于继续下一个结点
pre=node;
//再对右子树遍历
clue(node.getRight());
}
}