数据结构7—线索二叉树 (java)

二叉链表作为存储结构时只能找到结点的左、右孩子的信息,而不能直接得到结点的任一序列的前驱和后继信息,这种信息只有在遍历的动态过程中才能得到。

为保存前驱和后继信息,在每个结点的指针域增加两个区域,分别标识其前驱和后继,并增加两个标志区域。
这里写图片描述

只有中序遍历才可以对其进行线索化!!
把树的结构遍历的时候看一下哪些地方有空余,会发现中序刚好每个结点间都有

  • -

结点类

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~后序在改进

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值