28-线索化二叉树

1. 引入

2. 基本介绍

  • n个结点的二叉链表中含有 n+1个空指针域

  • 利用二叉链表中的空指针域,存放指向该结点在某种遍历次序下前驱和后继结点的指针(这种附加的指针称为"线索")
    • 一个结点的前一个结点,称为 前驱结点
    • 一个结点的后一个结点,称为 后继结点
  • 这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树 (Threaded BinaryTree)
  • 根据线索性质的不同,线索二叉树可分为
    • 前序线索二叉树
    • 中序线索二叉树
    • 后序线索二叉树

3. 案例

3.1 中序线索化 二叉树

3.2 遍历 线索化二叉树

4. 代码实现

public class ThreadedBinaryTreeDemo {
    public static void main(String[] args) {
        ThreadedBinaryTree tree = new ThreadedBinaryTree();
        Node root = new Node(1);
        Node node3 = new Node(3);
        Node node6 = new Node(6);
        Node node8 = new Node(8);
        Node node10 = new Node(10);
        Node node14 = new Node(14);
        root.left = node3;
        root.right = node6;
        node3.left = node8;
        node3.right = node10;
        node6.left = node14;
        tree.root = root;
        tree.midThreadedNodes();
        System.out.println("node10-left: " + node10.left);
        System.out.println("node10-right: " + node10.right);
        tree.midOrderthreadedBiTree();
    }
}

// 实现了线索化功能的二叉树
class ThreadedBinaryTree{
    public Node root;
    /*
     * 为了实现线索化, 需要创建 1 个指向当前结点的前驱结点的引用
     * 在递归进行线索化时, preNode 总是指向前一个结点
     */
    public Node preNode;
    
    public void midThreadedNodes() {
        midThreadedNodes(root);
    }
    
    // 中序线索化
    public void midThreadedNodes(Node node) {
        if(node == null)
            return;
        // 1. 线索化左子树
        midThreadedNodes(node.left);
        
        // 2. 线索化当前结点
        // 2.1 处理当前结点的前驱结点
        if(node.left == null) {
            // 修改当前结点的左指针类型
            node.leftType = 1;
            // 当前结点的左指针指向中序遍历时的前驱结点
            node.left = preNode;
        }
        // 2.2 处理(上一个结点的)后继结点
        if(preNode != null && preNode.right == null) {
            // 修改当前结点的右指针类型
            preNode.rightType = 1;
            // 上一个结点的右指针指向当前结点
            preNode.right = node;
        }
        // 2.3* 每处理完一个结点, 便让当前结点成为下一个待处理结点的前驱结点
        preNode = node;
        
        // 3. 线索化右子树
        midThreadedNodes(node.right);
    }
    
    // 中序遍历
    public void midOrderthreadedBiTree() {
        // 存储当前遍历的结点
        Node node = root;
        while(node != null) {
            // leftType = 1说明该结点是按照线索化处理后的有效结点
            while(node.leftType == 0) // 第一个找到的是[8]
                node = node.left;
            // 退出循环则说明找到了leftType = 1的结点, 打印当前结点即可
            System.out.println(node);
            
            // 如果当前结点的右指针指向后继结点, 就输出
            while(node.rightType == 1) {
                node = node.right;
                System.out.println(node);
            }
            node = node.right;
        }
    }
    
}

class Node {
    public int no;
    public Node left;
    public Node right;
    /*
     * leftType = 0, 表示指向左子树
     *          = 1, 表示指向前驱结点
     * rightType = 0, 表示指向右子树
     *           = 1, 表示指向后继结点
     */
    public int leftType;
    public int rightType;
    
    public Node(int no) {
        this.no = no;
    }
    
    @Override
    public String toString() {
        return "[no=" + no + "]";
    }
}

[待补充] 前序线索化二叉树和后序线索化二叉树及有关遍历

猜你喜欢

转载自www.cnblogs.com/liujiaqi1101/p/12327932.html