二叉链表作为存储结构时只能找到结点的左、右孩子的信息,而不能直接得到结点的任一序列的前驱和后继信息,这种信息只有在遍历的动态过程中才能得到。
为保存前驱和后继信息,在每个结点的指针域增加两个区域,分别标识其前驱和后继,并增加两个标志区域。
只有中序遍历才可以对其进行线索化!!
把树的结构遍历的时候看一下哪些地方有空余,会发现中序刚好每个结点间都有
- -
结点类
public class BiNode<T> {
private T data;
private BiNode<T>lChild;
private BiNode<T> rChild;
private int lTag;
private int rTag;
public int getlTag() {
return lTag;
}
public void setlTag(int lTag) {
this.lTag = lTag;
}
public int getrTag() {
return rTag;
}
public void setrTag(int rTag) {
this.rTag = rTag;
}
BiNode( T Data){
this.data=Data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public BiNode<T> getlChild() {
return lChild;
}
public void setlChild(BiNode<T> lChild) {
this.lChild = lChild;
}
public BiNode<T> getrChild() {
return rChild;
}
public void setrChild(BiNode<T> rChild) {
this.rChild = rChild;
}
}
前序遍历生成一颗树
public String[] str;
int count=0;
/*前序遍历生成一颗树*/
public BiNode<T> CreateBiTree(){
BiNode<T> bNode =null;
if(count >= str.length || str[count++].equals("#")){
bNode = null;
}
else{
bNode = new BiNode<T>((T)str[count-1]);
bNode.setlChild(CreateBiTree());
bNode.setrChild(CreateBiTree());
bNode.setlTag(0);//先把所有子树标识为都有孩子
bNode.setrTag(0);
}
return bNode;
}
线索化
//全局变量,始终指向刚访问过的结点
BiNode<T> pre=null;
/*初始化pre_建立头指针,左孩子指向第一个结点,右孩子为线索,树的第一个访问或最后一个访问结点指向他 */
public BiNode<T> InOrderThreading(BiNode<T> btree){
BiNode<T> p = new BiNode<T>(null);//头结点
p.setlTag(0);
p.setrTag(1);
p.setrChild(p);
if(btree==null){//二叉树为空,则回指
p.setlChild(p);
}else{
p.setlChild(btree);//头结点加到树上
pre=p;
InThreading(btree);//中序遍历线索化
pre.setrChild(p);//最后一个结点线索化
pre.setrTag(1);
p.setrChild(pre);
}
return p;
}
中序遍历线索化
/*中序遍历线索化*/
public void InThreading(BiNode<T> root){
if(root!=null){
InThreading(root.getlChild());//左孩子线索化
//结点处理
if(root.getlChild()==null){//该结点没有左孩子,设置标识为1,并把lchild指向前驱(刚刚访问的结点)
root.setlTag(1);
root.setlChild(pre);
}
if(pre!=null&&pre.getrChild()==null){//此时不能知道p的后继是什么,只能知道刚才的结点pre的后继为btree
pre.setrTag(1);
pre.setrChild(root);
}
pre=root;
InThreading(root.getrChild());//右孩子线索化
}
}
->中序遍历非递归
/*中序非递归*/
public static void OrderTraverse(BiNode<Integer> root){
BiNode<Integer> p;
p=root.getlChild();
while(p!=root){
while(p.getlTag()==0){
p = p.getlChild();
}
System.out.print(p.getData());
while(p.getrTag()==1&&p.getrChild()!=root){
p=p.getrChild();
System.out.print(p.getData());
}
p = p.getrChild();
}
}
测试->
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
while (cin.hasNext()) {
String s = cin.nextLine();
String[] str = s.split(",");
BitThrTree<Integer> tree = new BitThrTree<Integer>();
tree.str=str;
BiNode<Integer> root = tree.CreateBiTree();
OrderTraverse(tree.InOrderThreading(root));
}
}
结果
输入:A,B,D,G,#,#,H,#,#,#,C,E,#,T,#,#,F,#,#
输出结果:GDHBAETCF(中序遍历结果)
图的结构见
http://blog.csdn.net/luotuomianyang/article/details/50933465
程序中有一些定义不规范的地方比如:定义变量的时候如l和1,i要分清,l一般为L,LChild~后序在改进