ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

前驱线索树的遍历(Java个人理解)

2021-08-10 21:32:23  阅读:228  来源: 互联网

标签:node pre 结点 遍历 Java 节点 前驱 Node1 public


13.3.2 遍历前序线索树

我的个人理解:所谓的前序遍历就是每读到一个节点,就输出他的值,先左后右,这是一般二叉树的思路,但是,线索二叉树,子叶节点可能存在前驱和后继结点,那么,我们可以利用这一点,如果当前节点存在后继节点,我们直接在输出完当前节点后直接指向后继结点(按照一点的递归思想我们是一步一步返回去,然后再向右查找,由于存在后继节点,那么我们可以直接利用,大大缩短了查询效率)

package tree.threadedbinarytree;


public class ThreadedBinaryTreeDemo {
    public static void main(String[] args) {
        // 测试 把中序线索二叉树
        Node1 root = new Node1(1, "12");
        Node1 node2 = new Node1(3, "13");
        Node1 node3 = new Node1(6, "16");
        Node1 node4 = new Node1(8, "18");
        Node1 node5 = new Node1(10, "114");
        Node1 node6 = new Node1(14, "114");

        // 二叉树后面要递归创建,现在手动创建
        root.setLeft(node2);
        root.setRight(node3);
        node2.setLeft(node4);
        node2.setRight(node5);
        node3.setLeft(node6);

        infixThreadedBinaryTree infixThreadedBinaryTree = new infixThreadedBinaryTree();


        // 测试前序线索化
        infixThreadedBinaryTree.setRoot(root);
        infixThreadedBinaryTree.preNodes();

        // 测试:以10号结点为测试
        Node1 leftNode = node5.getLeft();
        Node1 rightNode = node5.getRight();
        System.out.println("10号结点的前驱结点时:" + leftNode);
        System.out.println("10号结点的后继结点" + rightNode);

        System.out.println("前序线索树遍历");
        infixThreadedBinaryTree.preThreadedList();
    }
}
// 线索化二叉树 实现了线索化功能的二叉树
class infixThreadedBinaryTree{
    private Node1 root;

    // 为了实现线索化,需要创建要给指向当前节点的前驱结点的指针
    // 在递归的进行线索时,pre 总是保留一个结点
    private Node1 pre = null;

    // 遍历中序线索二叉树
    public void infixThreadedList(){
        // 定义一个变量,存储当前遍历的节点,从root开始
        Node1 node = root;
        while(node != null){
            // 循环的找到leftType == 1的节点,第一个找到的就是8
            // 后面随着遍历node会变化,
            // 因为当leftType == 1时,说明该节点时按照线索化处理后的有效节点
            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 preThreadedList(){
        Node1 node = root;
        System.out.println(node); // 先输出当前node的值
        while (node != null){
            // 然后判断左节点是否是前驱结点,如果不是且不为空,就输出它的左孩子,并且指针指向左节点,进行下一次循环
            if (node.getLeftType() == 0 && node.getLeft() != null){
                System.out.println(node.getLeft());
                node = node.getLeft();
                continue;
            }
            // 判断右节点是否是后继结点,如果不是且为不为空,就输出它的右孩子,并且指针指向右节点,进行下一次循环
            if (node.getRightType() == 0 && node.getRight() != null){
                System.out.println(node.getRight());
                node = node.getRight();
                continue;
            }
            // 判断当前节点的右节点是否是后继结点,如果是,直接输出它的后继结点,然后指针指向后继结点
            if (node.getRightType() == 1){
                System.out.println(node.getRight());
                node = node.getRight();
            }

        }
    }
    // 重载一把threadeNodes方法
    public void threadeNodes(){
        this.threadedNodes(root);
    }
    // 编写二叉树进行中序线索化的方法
    /**
     *
     * @param node 就是当前需要线索化的结点
     */
    public void threadedNodes(Node1 node){
        // 如果 node == null,不能进行线索化
        if (node == null){
            return;
        }
        // 1. 先线索化左子树
        threadedNodes(node.getLeft());
        // 2. 线索化当前结点
        // 2.1 先处理当前节点的前驱结点
        if (node.getLeft() == null){
            // 让当前节点的左指针指向前驱结点
            node.setLeft(pre);
            // 修改当前节点的左指针的类型,指向前驱结点
            node.setLeftType(1);
        }
        // 2.2 处理当前节点的后继结点
        if (pre != null && pre.getRight() == null){
            // 让前驱结点的右指针指向当前结点
            pre.setRight(node);
            // 修改前驱结点的右指针类型
            pre.setRightType(1);
        }
        // 没处理一个节点后,让当前结点时下一个节点的前驱结点
        pre = node;
        // 3. 再线索化右子树
        threadedNodes(node.getRight());
    }

    public void preNodes(){
        this.preNodes(root);
    }
    // 前序线索化
    public void preNodes(Node1 node){
        if (node == null){
            return;
        }
        if (node.getLeft() == null){
            node.setLeft(pre);
            node.setLeftType(1);
        }
        if (pre != null && pre.getRight() == null){
            pre.setRight(node);
            pre.setRightType(1);
        }
        pre = node;
        if (node.getLeftType() == 0){
            preNodes(node.getLeft());
        }

        if (node.getRightType() == 0){
            preNodes(node.getRight());
        }

    }
    // 后序线索化
    public void postNodes(){
        this.postNodes(root);
    }
    public void postNodes(Node1 node){
        if (node == null){
            return;
        }
        postNodes(node.getLeft());
        postNodes(node.getRight());
        if (node.getLeft() == null){
            node.setLeft(pre);
            node.setLeftType(1);
        }
        if ( pre != null && pre.getRight() == null){
            pre.setRight(node);
            pre.setRightType(1);
        }

        pre = node;
    }
    public void setRoot(Node1 root) {
        this.root = root;
    }


}
// 先创建节点
class Node1{
    private int id;
    private String name;
    private Node1 left;
    private Node1 right;
    // 说明
    // 1. 如果leftType == 0 表示的指向的是左子树,如果1则表示指向前驱结点
    // 2. 如果rightType == 0 表示指向的是右子树,如果1则表示指向的是后继结点
    private int leftType;
    private int rightType;

    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 Node1(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Node1 getLeft() {
        return left;
    }

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

    public Node1 getRight() {
        return right;
    }

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

    @Override
    public String toString() {
        return "Node1{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

}


标签:node,pre,结点,遍历,Java,节点,前驱,Node1,public
来源: https://www.cnblogs.com/sharpenblogs/p/15125870.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有