线索二叉树的简单写法

package com.xiejianjun.day08.threadBinaryTreeDemo;

/**
 * @author bilibilidick
 * @version 2022 04
 * @date 2022/4/22 17:45
 */

public class ThreadBinaryTreeDemo {
    public static void main(String[] args) {
        BinaryNode one = new BinaryNode(1, "one");
        BinaryNode two = new BinaryNode(2, "two");
        BinaryNode three = new BinaryNode(3, "three");
        BinaryNode four = new BinaryNode(4, "four");
        BinaryNode five = new BinaryNode(5, "five");
        one.left = two;
        one.right = three;
        two.left = four;
        three.right = five;
        BinaryTree binaryTree = new BinaryTree();
        binaryTree.setRoot(one);
        // 线索化二叉树
        binaryTree.threadInTreeNode(one);
        // 遍历线索化之后的二叉树
        binaryTree.threadInTreeList(one);
    }
}

class BinaryTree {
    public BinaryNode root;
    public BinaryNode pre = null;

    public void setRoot(BinaryNode root) {
        this.root = root;
    }

    public void inRootOrder() {
        System.out.println("中序遍历根节点");
        if (this.root != null)
            this.root.inOrder();
    }


    public void deleteNodeById(int id) {
        System.out.printf("开始删除值为%d的结点", id);
        if (this.root == null) {
            System.out.println("空树");
            return;
        }
        if (this.root.id == id) {
            this.root = null;
        } else {
            this.root.deleteNode(id);
        }
    }

    public void threadInTreeList(BinaryNode root) {
        BinaryNode node = root;
        // root本身为空树或者到达最后一个结点退出循环
        while (node != null) {

            // 当结点有左子树时,继续找其左子树结点,直到找到左子树结点为空的结点,即leftType = 0的结点
            while (node != null && node.leftType == 0) {
                node = node.left;
            }
            System.out.println(node);
            // 当结点的rightType为1时,代表此结点拥有后继结点,则遍历其后继结点直到rightType为0,即遍历到有右子树结点的结点
            while (node != null && node.rightType == 1) {
                node = node.right;
                System.out.println(node);
            }
            // 当遍历到有右子树结点的结点时,由于此遍历方式为中序遍历,则将当前遍历的结点用其右子树替换,继续循环遍历即可
            node = node.right;
        }


    }

    public void threadInTreeNode(BinaryNode node) {
        if (node == null) {
            return;
        }
        // 先中序线索化左子树
        threadInTreeNode(node.left);
        // 线索化当前结点
        // 先处理当前结点的前驱结点,如果当前节点的左子树为空,则让其指向前驱结点,并将leftType置为1
        if (node.left == null) {
            node.left = pre;
            node.leftType = 1;
        }
        // 因为树是单向的,所以要在下一个结点处判断前一个结点的右子树是否为空,若为空,则将上一个结点的右子树指向自己,即后继结点的线索化
        if (pre != null && pre.right == null) {
            pre.right = node;
            pre.rightType = 1;
        }
        pre = node;
        // 再中序线索化右子树
        threadInTreeNode(node.right);
    }

}

class BinaryNode {
    public int id;
    public String name;
    public BinaryNode left;
    public BinaryNode right;
    public int leftType = 0;
    public int rightType = 0;


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

    @Override
    public String toString() {
        return "BinaryNode{" +
                "id=" + id +
                ", left=" + ((left == null)?"无前驱节点":left.id) +
                ", right=" + ((right == null)?"无后继节点":right.id) +
                ", leftType=" + leftType +
                ", rightType=" + rightType +
                '}';
    }



    public void inOrder() {
        if (this.left != null && this.leftType == 0) {
            this.left.inOrder();
        }
        System.out.println(this);
        if (this.right != null && this.rightType == 0) {
            this.right.inOrder();
        }
    }



    public void deleteNode(int id) {
        if (this.left != null) {
            if (this.left.id == id) {
                this.left = null;
                return;
            } else {
                this.left.deleteNode(id);
            }
        }

        if (this.right != null) {
            if (this.right.id == id) {
                this.right = null;
            } else {
                this.right.deleteNode(id);
            }
        }

    }

    public boolean isLeaf(BinaryNode node) {
        return node.left == null && node.right == null;
    }







}

关键代码:

public void threadTreeNode(BinaryNode node) {
        if (node == null) {
            return;
        }
        // 先中序线索化左子树
        threadTreeNode(node.left);
        // 线索化当前结点
        // 先处理当前结点的前驱结点,如果当前节点的左子树为空,则让其指向前驱结点,并将leftType置为1
        if (node.left == null) {
            node.left = pre;
            node.leftType = 1;
        }
        // 因为树是单向的,所以要在下一个结点处判断前一个结点的右子树是否为空,若为空,则将上一个结点的右子树指向自己,即后继结点的线索化
        if (pre != null && pre.right == null) {
            pre.right = node;
            pre.rightType = 1;
        }
        pre = node;
        // 再中序线索化右子树
        threadTreeNode(node.right);
    }

精髓在于由于二叉树单向的特点,需要设置前驱结点,并且利用了第一个结点无须设置前驱结点的特性,绕开了第一层的设置,非常精妙

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值