线索二叉树

假设二叉树有n个结点,那么就有2n个指针域(左、右),n-1个连接分支线,意味着只有n-1个指针域得到利用,有2n-(n-1)个指针域为空指针域占用空间

线索二叉树

线索二叉树就是解决普通二叉树的空间利用率不够的问题。普通二叉树没有前驱和后继保存。刚好可以利用空指针域保存前驱和后继,当左指针域为空指针域时将左指针域指向它的前驱,当右指针域为空时指向该结点的后继。

为了区分指针域此时是前驱后继还是指向左子树右子树,那么就需要添加一个标志,标注此时指针域的状态。当指针域指向前驱后继时,可以很方便的查找到它的下一步和上一步该如何走,此时称指针域的指向为线索(thread)

import java.util.Scanner;

// 线索二叉树
// n个结点一共有2n个指针域(左右指针域)
// 一共有n-1个分支线,所以有n-1个指针域可以利用,有2n-(n-1)=n+1个指针域占用空间
// 线索二叉树就是解决普通二叉树的空间利用不够的问题
// 普通二叉数没有前驱和后继,正好利用空间存储加上线索。指向下一步或者上一步该如何走
// 达到一次
public class ThreadBinaryTree {
    private BTreeNode root;// 根节点
    public ThreadBinaryTree(String data){
        this.root = new BTreeNode(data);
    }
    private enum Tag{Thread,Linked};
    private class BTreeNode{
        String data;// 数据域
        BTreeNode left;// 左指针域
        BTreeNode right;// 右指针域
        Tag ltag = Tag.Linked;// 左孩子是线索还是指针
        Tag rtag = Tag.Linked;// 右孩子是线索还是指针

        public BTreeNode(String data){
            this.data = data;
        }
        public void setLeft(BTreeNode left){
            this.left = left;
        }
        public void setRight(BTreeNode right){
            this.right = right;
        }
    }
//    生成一个结点
    public BTreeNode createBTreeNode(String data){
        return new BTreeNode(data);
    }
//    前序遍历线索化
    private static BTreeNode prev;// 前一个结点
    public void inThreading(BTreeNode node){
        if (node==null) return;

        if (node.left==null){
            node.ltag = Tag.Thread;
            node.left = prev;
        }

        if (prev!=null&&prev.right==null){
            prev.rtag = Tag.Thread;
            prev.right = node;
        }
        prev = node;


        if (node.ltag==Tag.Linked) inThreading(node.left);
        if (node.rtag==Tag.Linked) inThreading(node.right);
    }

//    前序遍历二叉树
    public void prevOrderRecurse(BTreeNode node){
        if (node==null) return;
        System.out.println(node.data);
        prevOrderRecurse(node.left);
        prevOrderRecurse(node.right);
    }
//    线索二叉树前序遍历
    public void threadPrevOrderRecurse(BTreeNode node){

        if (node==null) return;

        BTreeNode p = node;

        while (p!=null){
//            遍历左边
            while (p.left!=null&&p.ltag==Tag.Linked){
                System.out.println(p.data);
                p = p.left;
            }

//           一直查找右边即可
            if (p.rtag==Tag.Thread) p = p.right;

            while (p!=null){
                System.out.println(p.data);
                p = p.right;
            }
        }

    }
    public static void main(String[] args){
        ThreadBinaryTree thrBTree = new ThreadBinaryTree("A");
        BTreeNode node1 = thrBTree.createBTreeNode("B");
        BTreeNode node2 = thrBTree.createBTreeNode("C");
        BTreeNode node3 = thrBTree.createBTreeNode("D");

        node1.setRight(node3);
        thrBTree.root.setLeft(node1);
        thrBTree.root.setRight(node2);

//        普通二叉树遍历
        thrBTree.prevOrderRecurse(thrBTree.root);

//        线索二叉树遍历
        thrBTree.inThreading(thrBTree.root);
        thrBTree.threadPrevOrderRecurse(thrBTree.root);
    }
}

private enum Tag{Thread,Linked};枚举用于标注此时指针域的状态为线索(Thread)还是普通连接(Linked)。

使用线索二叉树遍历的好处在于充分利用了空间、一次线索化终身受用的目的、非递归遍历二叉树

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值