实质: 将二叉树中的空指针指向前驱或者后继元素.
如果元素指针不为空,那么他的后继 是从它开始 按照X遍历顺序 遍历的第一个左叶结点或右叶结点.
1:对二叉树进行遍历 == 对二叉树的
"线性化操作" ------> 会生成一个访问的线性 序列. 每个元素有了自己的
惟一前驱和后继.
2:可以利用二叉树中的叶节点中未被使用的 lchild 和 rchild 分别
指向该节点 按某准
遍历顺序 的 前驱节点和后继节点.
3:生成的树称为 "线索二叉树".
建立线索二叉树:
1: 建立一棵常规二叉树.
2:遍历这个二叉树.
3:在遍历过程中修改空指针指向前驱和后继.
所用树模型:
public class ThreadTree {
char ele;
ThreadTree lchild, rchild;
int LTag =1,RTag;
static ThreadTree pre = null;
static int exp = 0;
static final int Link = 1;
static final int Thread = 2;
public static void main(String[] args){
ThreadTree T = new ThreadTree();
String s = "abc%%de%g%%f%%%";
char[] chs = s.toCharArray();
T = createThreadTree(T, chs);
ThreadTree Res = new ThreadTree();
Res = CreateThreadTree(Res,T);
BianLi(Res);//c b e g d f a
}
//建立二叉树,exp当前下标值
public static ThreadTree createThreadTree(ThreadTree T,char[] chs){
if(exp >= chs.length || chs[exp] == '%') {T = null; exp++;}
else{
T = new ThreadTree();
T.ele = chs[exp++];
T.lchild = createThreadTree(T.lchild,chs);
T.rchild = createThreadTree(T.rchild,chs);
}
return T;
}
//建立线索二叉树
public static ThreadTree CreateThreadTree(ThreadTree Thrt,ThreadTree T){
Thrt = new ThreadTree();
Thrt.LTag = Link; Thrt.RTag = Thread;
Thrt.rchild = Thrt;
if(T == null) Thrt.lchild = Thrt;
else{
Thrt.lchild = T;
pre = Thrt;
InThreading(T);
pre.rchild = Thrt;
pre.RTag = Thread;
Thrt.rchild = pre;
}
return Thrt;
}
private static void InThreading(ThreadTree p) {
if(p != null){
InThreading(p.lchild);
if(p.lchild == null){
p.LTag = Thread; p.lchild = pre;
}
if(pre.rchild == null){
pre.RTag = Thread; pre.rchild = p;
}
pre = p;
InThreading(p.rchild);
}
}
//非递归遍历线索二叉树
public static void BianLi(ThreadTree T){
ThreadTree p = T.lchild;
while(p != T){
while(p.LTag == Link){
p = p.lchild;
}
System.out.println(p.ele);
while(p.RTag == Thread && p.rchild != T){
p = p.rchild; System.out.println(p.ele);
}
p = p.rchild;
}
}
}