java语言实现线索二叉树

  • 有如下一棵二叉树:
    在这里插入图片描述
    我们发现,有一部分节点(3,4,5,6号节点)的左右指针域为空,比较浪费空间。**且 n 个节点的二叉树含有 n+1 个空指针域。**但是没有这些左右指针域又不行,如果能够充分利用他们,那再好不过了。
    我们可以将他们用来指向自己的某种遍历方式的前序或者后序节点,方便遍历。这就是线索化二叉树,附加的指针称为“线索”。
  • 中序遍历为例,线索化二叉树如下图:
    在这里插入图片描述
  • 如何实现呢?
    1.首先,我们需要为Node节点类添加属性leftType、rightType来记录指针域是指向的子节点还是前驱或者后继节点。如果leftType = 0,说明指向的是左子树;leftType = 1,指向的是前驱结点,如果rightType = 0,说明指向的是右子树;rightType = 1,指向的是后继结点。节点类代码如下:
public class Node {
    private int id;
    private String name;
    private Node left;
    private Node right;

    //如果leftType == 0,说明指向的是左子树;leftType == 1,指向的是前驱结点
    //如果rightType == 0,说明指向的是右子树;rightType == 1,指向的是后继结点
    private int leftType;
    private int rightType;


    public Node(int id, String name) {
        this.id = id;
        this.name = name;
    }

	//getter  setter  toString方法

}

2.编写线索二叉树类,定义线索化方法。
由于父子节点之间是单向的,为了实现线索化,需要一个指向当前节点的前驱结点的指针pre,在线索化过程中,pre总是指向前一个节点。如果当前节点不为空,由于是中序遍历,所以先线索化左子树,再线索化当前节点,最后线索化右子树。线索化左子树右子树使用递归即可,关键的是对当前节点的线索化。
3.当前节点的线索化
需要判断当前节点的左右子节点是否存在(不存在的时候才会设置线索),以及当前节点的前驱结点的右子树是否存在(右子树为空才能将线索指向当前节点)。最后,还要把pre指向当前节点,往后继节点移动。
4.线索二叉树的遍历
先找到遍历的第一个节点,然后再顺着右指针线索遍历,只要rightType=1,就说明是后继节点。否则就遍历以rightType=0这个节点为根的二叉树,直到全部遍历结束(最后一个节点的右指针为空)。
5.代码如下:

public class ThreadedBinaryTree {
    private Node root;

    //为了实现线索化,需要一个指向当前节点的前驱结点的指针
    //在线索化过程中,pre总是指向前一个节点
    private Node pre = null;

    public ThreadedBinaryTree(Node root) {
        this.root = root;
    }

    //中序遍历线索二叉树
    public void threadedShow(Node node){

        while (node != null){
            while (node.getLeftType() == 0){
                node = node.getLeft();
            }
            System.out.println(node);

            while (node.getRightType() == 1){
                node = node.getRight();
                System.out.println(node);
            }
            node = node.getRight();
        }
    }


    //中序线索化二叉树
    public void threaded(Node node){
        if (node == null){
            return;
        }

        //先线索化左子树
        threaded(node.getLeft());

        //线索化当前节点
        if (node.getLeft() == null){
            node.setLeft(pre);
            node.setLeftType(1);
        }
        if (pre != null && pre.getRight() == null){
            pre.setRight(node);
            pre.setRightType(1);
        }
        pre = node;

        //最后线索化右子树
        threaded(node.getRight());
    }
}

  • 测试:
public class ThreadedDemo {
    public static void main(String[] args) {
        Node node1 = new Node(1,"A");
        Node node2 = new Node(2,"B");
        Node node3 = new Node(3,"C");
        Node node4 = new Node(4,"D");
        Node node5 = new Node(5,"E");
        Node node6 = new Node(6,"F");

        node1.setLeft(node2);
        node1.setRight(node3);
        node2.setLeft(node4);
        node2.setRight(node5);
        node3.setLeft(node6);

        ThreadedBinaryTree threadedBinaryTree = new ThreadedBinaryTree(node1);
        threadedBinaryTree.threaded(node1);
        threadedBinaryTree.threadedShow(node1);
        
    }
}

  • 中序线索二叉树的遍历结果:
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值