线索化二叉树

Posted bingbug

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线索化二叉树相关的知识,希望对你有一定的参考价值。

线索化二叉树的特点是:每一个节点都有前驱和后继节点(第一个和最后一个除外)所以查找某一节点会很容易

缺点:也很明显就是在插入新节点和删除时过于麻烦,实际应用需自己取舍

public class ThreadedBinaryTreeDemo {

    public static void main(String[] args) {
        HeroNode root = new HeroNode(1, "tom");
        HeroNode node2 = new HeroNode(3, "jack");
        HeroNode node3 = new HeroNode(6, "smith");
        HeroNode node4 = new HeroNode(8, "mary");
        HeroNode node5 = new HeroNode(10, "king");
        HeroNode node6 = new HeroNode(14, "dim");

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

//        node2.setParent(root);
//        node3.setParent(root);
//        node4.setParent(node2);
//        node5.setParent(node2);
//        node6.setParent(node3);

        ThreadedBinaryTree threadedBinaryTree = new ThreadedBinaryTree();
        threadedBinaryTree.setRoot(root);
        threadedBinaryTree.threadedNodes();

        //8 10 3 14 6 1
        HeroNode leftNode = node4.getLeft();
        HeroNode rightNode = node4.getRight();
//        System.out.println(leftNode);//null
//        System.out.println(rightNode);//10
        threadedBinaryTree.threadedList();

    }
}

class ThreadedBinaryTree {
    private HeroNode root;
    //指向当前节点的前驱节点
    private HeroNode pre = null;

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

    //重载
    public void threadedNodes() {
        this.threadedNodes(root);
    }

    public void threadedNodes(HeroNode 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()!=1){
            threadedNodes(node.getLeft());
        }
        if (node.getRightType()!=1){
            threadedNodes(node.getRight());
        }

//        //线索化左子树
//        threadedNodes(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;
//        //线索化右子树
//        threadedNodes(node.getRight());

//        threadedNodes(node.getLeft());
//        threadedNodes(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 threadedList() {
        HeroNode node = root;
        while (node != null) {
            while (node.getLeftType() == 0) {
                System.out.println(node);
                node = node.getLeft();
            }
            System.out.println(node);
            node = node.getRight();
        }

//        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();
//        }

//        while ( node != null && node.getLeftType() == 0 ) {
//            node = node.getLeft();
//        }
//        while (node != null) {
//            if (node.getRightType() == 1) {
//                System.out.println(node);
//                pre = node;
//                node = node.getRight();
//            } else {
//                //如果上个处理的节点是当前节点的右节点
//                if (node.getRight() == pre) {
//                    System.out.println(node);
//                    if (node == root) {
//                        return;
//                    }
//                    pre = node;
//                    node = node.getParent();
//                } else {    //如果从左节点的进入则找到有子树的最左节点
//                    node = node.getRight();
//                    while ( node != null && node.getLeftType() == 0 ) {
//                        node = node.getLeft();
//                    }
//                }
//            }
//        }
    }

    //
    public void preOrder() {
        if (this.root != null) {
            this.root.preOrder();
        } else {
            System.out.println("null");
        }
    }

    //
    public void infixOrder() {
        if (this.root != null) {
            this.root.infixOrder();
        } else {
            System.out.println("null");
        }
    }

    //
    public void postOrder() {
        if (this.root != null) {
            this.root.postOrder();
        } else {
            System.out.println("null");
        }
    }

    //查找
    public HeroNode preOrderSearch(int no) {
        if (root != null) {
            return root.preOrderSearch(no);
        } else {
            return null;
        }
    }

    public HeroNode infixOrderSearch(int no) {
        if (root != null) {
            return root.infixOrderSearch(no);
        } else {
            return null;
        }
    }

    public HeroNode postOrderSearch(int no) {
        if (root != null) {
            return root.postOrderSearch(no);
        } else {
            return null;
        }
    }

    //删除
    public void delNode(int no) {
        if (root != null) {
            if (root.getNo() == no) {
                root = null;
            } else {
                root.delNode(no);
            }
        } else {
            System.out.println("空树");
        }
    }

    public void del(int no) {
        if (root != null) {
            if (root.getNo() == no) {
                root = null;
            } else {
                root.del(no);
            }
        } else {
            System.out.println("空树");
        }
    }

}

class HeroNode {
    private int no;
    private String name;
    private HeroNode left;
    private HeroNode right;
    private HeroNode parent;

    public HeroNode getParent() {
        return parent;
    }

    public void setParent(HeroNode parent) {
        this.parent = parent;
    }

    private int leftType;//0 指向左子树 1 指向前驱节点
    private int rightType;//0 指向右子树 1 指向后继节点

    public HeroNode(int no, String name) {
        this.no = no;
        this.name = name;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

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

    public HeroNode getLeft() {
        return left;
    }

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

    public HeroNode getRight() {
        return right;
    }

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

    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;
    }

    @Override
    public String toString() {
        return "HeroNode[" +
                "no=" + no +
                ", name=‘" + name + ‘‘‘ +
                ‘]‘;
    }

    /*
        是什么遍历看什么时候输出父节点
     */
    //前序遍历
    public void preOrder() {
        System.out.println(this);
        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.println(this);
        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.println(this);
    }

    //前序查找
    public HeroNode preOrderSearch(int no) {
        if (this.no == no) {
            return this;
        }
        HeroNode resNode = null;
        if (this.left != null) {
            resNode = this.left.preOrderSearch(no);
        }
        if (resNode != null) {
            return resNode;
        }
        if (this.right != null) {
            resNode = this.right.preOrderSearch(no);
        }
        return resNode;
    }

    //中序查找
    public HeroNode infixOrderSearch(int no) {
        HeroNode resNode = null;
        if (this.left != null) {
            resNode = this.left.infixOrderSearch(no);
        }
        if (resNode != null) {
            return resNode;
        }
        if (this.no == no) {
            return this;
        }
        if (this.right != null) {
            resNode = this.right.infixOrderSearch(no);
        }
        return resNode;
    }

    //后序查找
    public HeroNode postOrderSearch(int no) {
        HeroNode resNode = null;
        if (this.left != null) {
            resNode = this.left.postOrderSearch(no);
        }
        if (resNode != null) {
            return resNode;
        }
        if (this.right != null) {
            resNode = this.right.postOrderSearch(no);
        }
        if (resNode != null) {
            return resNode;
        }
        if (this.no == no) {
            return this;
        }
        return resNode;
    }

    public void delNode(int no) {
        if (this.left != null && this.left.no == no) {
            this.left = null;
            return;
        }
        if (this.right != null && this.right.no == no) {
            this.right = null;
            return;
        }
        if (this.left != null) {
            this.left.delNode(no);
        }
        if (this.right != null) {
            this.right.delNode(no);
        }
    }

    public void del(int no) {
        if (this.left != null && this.left.no == no) {
            this.left = null;
            return;
        }
        if (this.right != null && this.right.no == no) {
            if (this.right.left != null && this.right.right != null) {
                this.right.left.right = this.right.right;
                this.right = this.right.left;
                return;
            } else {
                this.right = null;
                return;
            }
        }
        if (this.left != null) {
            this.left.delNode(no);
        }
        if (this.right != null) {
            this.right.delNode(no);
        }
    }
}

以上是关于线索化二叉树的主要内容,如果未能解决你的问题,请参考以下文章

C#数据结构-线索化二叉树

线索化二叉树

数据--第37课 - 线索化二叉树

数据结构与算法:树 线索化二叉树(中,前,后序)

数据结构与算法:树 线索化二叉树(中,前,后序)

线索化二叉树详解