数据结构和算法(22)之线索二叉树

学习数据结构和算法的日常Demo

二叉树遍历存在的问题

在这里插入图片描述

线索二叉树基本介绍

在这里插入图片描述

中序线索二叉树思路分析

在这里插入图片描述

代码实现

public class TreeNode {
    private int value;
    private TreeNode left;
    private TreeNode right;
    // 如果leftType为0,表示指向左子树,如果为1表示指向前驱节点(rightType同)
    private int leftType;
    private int rightType;

    public TreeNode(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "TreeNode{" +
                "value=" + value +
                '}';
    }

    public int getValue() {
        return value;
    }

    public int getLeftType() {
        return leftType;
    }

    public void setLeftType(int leftType) {
        this.leftType = leftType;
    }

    public int getRightType() {
        return rightType;
    }

    public void setRightType(int rightType) {
        this.rightType = rightType;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public TreeNode getLeft() {
        return left;
    }

    public void setLeft(TreeNode left) {
        this.left = left;
    }

    public TreeNode getRight() {
        return right;
    }

    public void setRight(TreeNode right) {
        this.right = right;
    }

    // 前序遍历
    public void preOrder() {
        // 输出父节点
        System.out.print(this.value + " ");
        // 递归左子树
        if (this.left != null) {
            this.left.preOrder();
        }
        // 递归右子树
        if (this.right != null) {
            this.right.preOrder();
        }
    }

    // 中序遍历
    public void infixOrder() {
        // 递归左子树
        if (this.left != null) {
            this.left.infixOrder();
        }
        // 输出父节点
        System.out.print(this.value + " ");
        // 递归右子树
        if (this.right != null) {
            this.right.infixOrder();
        }
    }

    // 后序遍历
    public void postOrder() {
        // 递归左子树
        if (this.left != null) {
            this.left.postOrder();
        }
        // 递归右子树
        if (this.right != null) {
            this.right.postOrder();
        }
        // 输出父节点
        System.out.print(this.value + " ");
    }
 }

public class ThreadedBinaryTree {
    private TreeNode root;
    private TreeNode pre = null;    // 线索化的前驱节点

    public TreeNode getRoot() {
        return root;
    }

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

    // 对二叉树中序线索化
    // node即为当前需要线索化的节点
    public void threadedNodes(TreeNode node) {
        if (node == null) {
            return;
        }
        // 1.线索化左子树
        threadedNodes(node.getLeft());
        // 2.线索化当前节点
        // 处理当前节点的前驱节点
        if (node.getLeft() == null) {
            // 让当前节点的左指针指向前驱节点
            node.setLeft(pre);
            // 修改当前左指针的指向类型
            node.setLeftType(1);
        }
        // 处理后继节点
        if (pre != null && pre.getRight() == null) {
            // 前驱节点的右指针指向当前节点
            pre.setRight(node);
            // 修改前驱节点的右指针类型
            pre.setRightType(1);
        }
        // 每处理一个节点,让当前节点是下一个节点的前驱节点
        pre = node;
        // 3.线索化右子树
        threadedNodes(node.getRight());
    }

    // 遍历中序线索化二叉树
    public void threadedList(){
        // 定义一个变量,存储当前遍历到的节点
        TreeNode node = root;
        while(node!=null){
            // 循环找到leftType == 1的节点
            // 当leftType == 1,说明该节点是线索化处理后的
            while (node.getLeftType() == 0){
                node = node.getLeft();
            }
            // 打印当前节点
            System.out.print(node.getValue()+" ");
            // 如果当前节点的右节点指向后继节点,就一直输出
            while (node.getRightType() == 1){
               // 获取到当前节点的后继节点
                node = node.getRight();
                System.out.print(node.getValue()+" ");
            }
            // 替换这个遍历的节点
            node = node.getRight();
        }
    }

    // 前序遍历
    public void preOrder() {
        if (root != null) {
            root.preOrder();
        } else {
            System.out.println("二叉树为空!");
        }
    }

    public void infixOrder() {
        if (root != null) {
            root.infixOrder();
        } else {
            System.out.println("二叉树为空!");
        }
    }

    public void postOrder() {
        if (root != null) {
            root.postOrder();
        } else {
            System.out.println("二叉树为空!");
        }
    }
}

// 测试类
public class ThreadedBinaryTreeDemo {
    public static void main(String args[]) {
        ThreadedBinaryTree tree = new ThreadedBinaryTree();
        TreeNode root = new TreeNode(1);
        TreeNode node1 = new TreeNode(3);
        TreeNode node2 = new TreeNode(6);
        TreeNode node3 = new TreeNode(8);
        TreeNode node4 = new TreeNode(10);
        TreeNode node5 = new TreeNode(14);
        // 构建树
        root.setLeft(node1);
        root.setRight(node2);
        node1.setLeft(node3);
        node1.setRight(node4);
        node2.setLeft(node5);
        // 创建根节点
        tree.setRoot(root);
        /*
                        1
                   3         6
                 8   10   14
         */
        tree.infixOrder();
        System.out.println("中序遍历(线索化前)");
        // 线索化二叉树
        System.out.println("中序线索化:");
        tree.threadedNodes(root);
        // 测试,10号节点
        System.out.println("10的前驱节点:" + node4.getLeft());
        System.out.println("10的后继节点:" + node4.getRight());
        // 当线索化二叉树后,不能使用原先的遍历方式
        tree.threadedList();
        System.out.println("中序遍历(线索化后)");
    }

在这里插入图片描述

线索化二叉树关键点

	// 代码片段
 	// 如果leftType为0,表示指向左子树,如果为1表示指向前驱节点
    private int leftType;
    // 如果rightType为0,表示指向右子树,如果为1表示指向前后继节点
    private int rightType;

// 每处理一个节点,让当前节点是下一个节点的前驱节点
        pre = node;

递归过程中,不断处理前驱节点和后继节点的指向

GitHub:数据结构和算法源代码

发布了67 篇原创文章 · 获赞 21 · 访问量 2684

猜你喜欢

转载自blog.csdn.net/qq_44779506/article/details/105124881