1120-2019-数据结构-二叉树+线索二叉树

ArrayList底层其实也是扩容。
数组:检索读取的效率还可以,但是插入删除的效率偏低。
链表:插入删除的效率好。但是检索读取的效率偏低。

所以引入二叉树。特别是二叉排序树、红黑树(HashMap的底层实现)。
对数据的增删改查的速度都会提高。

小概念
结点
根节点
父节点
子节点
叶子结点
结点的权(节点的值)

满二叉树
完全二叉树

一般来说我们只说二叉树。
前序遍历
中序遍历
后序遍历

前序:根左右
中序:左根右
后序:左右根
package BinaryTree;




/**
 * @author pdzz
 * @create 2019-11-19 10:29
 */
class Node{

    private int no;
    private String name;
    private Node left;
    private Node right;

    public Node(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 Node getLeft() {
        return left;
    }

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

    public Node getRight() {
        return right;
    }

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

    @Override
    public String toString() {
        return "Node{" +
                "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 midOrder(){
        //递归向左子树遍历
        if (this.left != null){
            this.left.midOrder();
        }
        //输出当前结点
        System.out.println(this);
        //向右递归当前结点
        if (this.right != null){
            this.right.midOrder();
        }
    }
    //后序遍历
    public void postOrder(){
        if (this.left != null){
            this.left.postOrder();
        }
        if (this.right != null){
            this.right.postOrder();
        }
        System.out.println(this);
    }

}
//定义一个二叉树
class BinaryTree{
    private Node root;
    public void setRoot(Node root){
        this.root = root;
    }

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



}
public class BinaryTreeDemo {
    public static void main(String[] args) {
        BinaryTree binaryTree = new BinaryTree();
        Node root = new Node(1,"a");
        Node node2 = new Node(2,"b");
        Node node3 = new Node(3,"c");
        Node node4 = new Node(4,"d");
        root.setLeft(node2);
        root.setRight(node3);
        node3.setRight(node4);
        binaryTree.setRoot(root);
        /*
        *        1
        *    2       3
        *               4
        *
        * 可以看出:前序遍历就是:1-2-3-4
        *          中序遍历就是:2-1-3-4
        *          后序遍历就是:2-4-3-1
        *
        *        1
        *    2       3
        *          5    4
        *
        *前序遍历:1-2-3-5-4
        *中序遍历:2-1-5-3-4
        *后序遍历:2-5-4-3-1
        *
        * */
        binaryTree.preOrder();
        binaryTree.midOrder();
        binaryTree.postOrder();

    }

}

前中后序查找指定节点

 
public Node preOrderSearch(int id){
        //前序遍历先找根节点
        if (this.no == id){
            return this;
        }
        Node resNode = null;
        if (this.left != null){
            resNode = this.left.preOrderSearch(id);
        }
        if (resNode != null){
            return resNode;
        }
        if (this.right != null){
            resNode = this.right.preOrderSearch(id);
        }
        return resNode;
    }
    public Node midOrderSearch(int id){
        Node resNode = null;
        if (this.left != null){
            resNode = this.left.midOrderSearch(id);
        }
        if (resNode != null){
            return resNode;
        }
        if (this.no == id){
            return this;
        }
        if (this.right != null){
            resNode = this.right.midOrderSearch(id);
        }
        return resNode;
    }
    public Node postOrderSearch(int id){
        Node resNode = null;
        if (this.left != null){
            resNode = this.left.postOrderSearch(id);
        }
        if (resNode != null){
            return resNode;
        }
        if (this.right != null){
            resNode = this.right.postOrderSearch(id);
        }
        if (this.no == id){
            return this;
        }
        return resNode;
}



BinaryTree类中的代码:
//前序遍历
    public Node preOrderSearch(int id){
        if (root != null){
            return root.preOrderSearch(id);
        }else {
            System.out.println("找不到id为" + id + "的节点");
            return null;
        }
    }
    public Node midOrderSearch(int id){
        if (root != null){
            return root.midOrderSearch(id);
        }else {
            System.out.println("找不到id为" + id + "的节点");
            return null;
        }
    }
    public Node postOrderSearch(int id){
        if (root != null){
            return root.postOrderSearch(id);
        }else {
            System.out.println("找不到id为" + id + "的节点");
            return null;
        }
    }


删除节点

public void delNode(int id){
        if (root != null){
            if (root.getNo() == id){
                root = null;
                return;
            }
            else{
                root.delNode(id);
            }
        }else {
            System.out.println("树是空树");
        }
    }

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

    }

线索二叉树

在这里插入图片描述

在这里插入图片描述

class ThreadedBinaryTree {
    private HeroNode root;

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

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

    //重载一把threadedNodes方法
    public void threadedNodes() {
        this.threadedNodes(root);
    }

    //遍历线索化二叉树的方法
    public void threadedList() {
        //定义一个变量,存储当前遍历的结点,从root开始
        HeroNode node = root;
        while(node != null) {
            //循环的找到leftType == 1的结点,第一个找到就是8结点
            //后面随着遍历而变化,因为当leftType==1时,说明该结点是按照线索化
            //处理后的有效结点
            while(node.getLeftType() == 0) {
                node = node.getLeft();
            }

            //打印当前这个结点
            System.out.println(node);
            //如果当前结点的右指针指向的是后继结点,就一直输出
            while(node.getRightType() == 1) {
                //获取到当前结点的后继结点
                node = node.getRight();
                System.out.println(node);
            }
            //替换这个遍历的结点,例如就是3输出以后,3的getRightType不等于1
            //所以退出while循环,执行下面的node = node.getRight();就是将当前的
            //node(值为3)替换为其	右子节点10,实现循环的操作。10的话左子节点的
            //类型不为1,所以打印出来10,继续判断其右子节点的类型是否为1,显
            //然是1,所以继续打印10的后继节点1,然后继续循环,1的右子节点的
            //类型不为1,所以退出循环,再次让当前的node(值为1)的指针指向的它的
            //右指针(值为6)。

            node = node.getRight();

        }
    }

    //编写对二叉树进行中序线索化的方法
    /**
     *
     * @param node 就是当前需要线索化的结点
     */
    public void threadedNodes(HeroNode node) {

        //如果node==null, 不能线索化
        if(node == null) {
            return;
        }

        //(一)先线索化左子树
        threadedNodes(node.getLeft());
        //(二)线索化当前结点[有难度]

        //处理当前结点的前驱结点
        //以8结点来理解
        //8结点的.left = null , 8结点的.leftType = 1
        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());


    }

集合的源码仔细看。
二叉树的遍历
图的深度优先遍历DFS

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值