java二叉树

什么是二叉树

二叉树是指树中节点的度不大于2的有序树,也就是说这颗树有且只有一个根节点,且分支不得大于2。具体想了解树以及二叉树的朋友请看https://www.jianshu.com/p/bf73c8d50dc2,里边详细介绍了。本文中重点说明查找二叉树。本文参考https://www.cnblogs.com/yandufeng/p/10845118.html(本文和这位大佬的文章大相径庭,但我在他基础上改成我想要的结果),以及程序员小灰的公众号文章https://mp.weixin.qq.com/s/-8JFh5iLr88XA4AJ9mMf6g

查找二叉树的条件

1.子树上所有结点的值均小于或等于它的根结点的值。

2.子树上所有结点的值均大于或等于它的根结点的值。

3.左、右子树也分别为二叉排序树。

如图所示,

构建二叉树

构建节点类

@Data
public class Node {
    Integer id;
    Node left;
    Node right;

    Node(Integer id){
        this.id = id;
        this.left = null;
        this.right = null;
    }

    Node() {
        this.id = null;
        this.left = null;
        this.right = null;
    }
}

整体树类

包含根节点

@Data
public class BinaryTree extends Node{
    private Node root;
}

添加节点

    /*
    首先我们必须找到新节点的位置,是为了保持树排序。从根节点开始,必须遵循下面的规则:
    如果新节点小于当前的值,将会进入左子树。
    如果新节点大于当前的节点,将会进入右子树。
    当当前的节点是null时,我们已经到达叶子节点,我们可以添加新节点到这个位置。
    */
    public Node addNode(Node currentNode, int value) {
        //第一次创建,从根节点开始
        if (currentNode == null){
            return new Node(value);
        }
        if (value< currentNode.getId()){ //如果新节点小于当前的值,将会进入左子树。
            currentNode.left =addNode(currentNode.left, value);
        }else {
            currentNode.right =addNode(currentNode.right, value);
        }

        return currentNode;
    }

    public void addNode(int value) {
        root = addNode(root,value);
    }

查找节点以及其子节点

   public BinaryTree selectNode(int value,Node current){
        BinaryTree binaryTree = new BinaryTree();
        if (current == null){
            return null;
        }
        if (value == current.id){
            binaryTree.root = current;
            return binaryTree;
        }else {
            if (value<root.id){
                current=root.left;
            }else {
                current=root.right;
            }
            return selectNode(value,current);
        }
    }

删除节点

    public Node deleteNode(Node current, int value) {
        if (current == null) {
            return null;
        }
        if (value == current.id) {
//            开启下边方法删除单个节点
//            if (current.left == null && current.right == null) {
//                return null;
//            }
//            if (current.left == null) {
//                return current.right;
//            }
//            if (current.right == null) {
//                return current.left;
//            }
//            int id = findNode(current.right);
//            current.id = id;
//            current.right = deleteNode(current.right, id);
//            return current;

//            删除当前节点下的子节点
//            current.left = null;
//            current.right = null;
//            return current;
//            删除本节点及其子节点
//            return null;
        }
        if(value < root.id) {
            current.left = deleteNode(current.left, value);
        }
        current.right = deleteNode(current.right, value);
        return current;
    }

    public BinaryTree deleteNode(BinaryTree binaryTree, int value){
        Node node = deleteNode(binaryTree.root, value);
        if (node!=null){
            binaryTree.root = node;
            return binaryTree;
        }
       return null;
    }
    
    private int findNode(Node root) {
        return root.left == null ? root.id : findNode(root.right);
    }

遍历树

这个就跟那位老哥写的一样了,简单易懂。

我们将以不同的方式遍历树,以depth-first,breadth-first方式遍历树。
以Depth-First遍历树
Depth-first查询是一种在查询兄弟节点之前,尽可能的查询每个子节点。
in-order,pre-order,post-order方式都是以depth-first方式遍历树的。

in-order遍历是首先遍历左子树,然后root节点,最后是右子树。

    public void traverseInOrder(Node root) {
        if (root != null) {
            traverseInOrder(root.left);
            System.out.println(root.data);
            traverseInOrder(root.right);
        }
    }

pre-order遍历首先是root节点,然后是左子树,最后是右子树。

public void traversePreOrder(Node root) {
        if (root != null) {
            System.out.println(root.data);
            traversePreOrder(root.left);
            traversePreOrder(root.right);
        }
    }

post-order遍历首先是遍历左子树,然后是右子树,最后是root节点。

public void traversePostOrder(Node root) {
        if (root != null) {
            traversePostOrder(root.left);
            traversePostOrder(root.right);
            System.out.println(root.data);
        }
    }

以Breadth-First遍历
它在遍历下一级的节点之前,会遍历当前级的所有节点。
这种类型的遍历也叫做level-order,遍历树从root节点开始,从左到右。
为了实现,使用队列来存储每个级别的节点。我们将会从列表中获取每个节点。然后添加他的子节点到队列中。

public void traverseLevelOrder(Node root) {
        if (root == null) {
            return;
        }
        Queue<Node> nodes = new LinkedList<Node>();
        nodes.add(root);
        while(!nodes.isEmpty()) {
            Node node = nodes.remove();
            System.out.println(node.data);
            if (node.left != null) {
                nodes.add(node.left);
            }
						
            if (node.right != null) {
                nodes.add(node.right);
            }
        }
    }

测试

创建树

    @Test
    public void Nodes() {
        //创建树
        BinaryTree binaryTree = new BinaryTree();
        binaryTree.addNode(5 );
        binaryTree.addNode(3 );
        binaryTree.addNode(7);
        binaryTree.addNode(2);
        binaryTree.addNode(4);
        binaryTree.addNode(6);
        binaryTree.addNode(8);

        //查询节点
        BinaryTree binaryTreeSun = binaryTree.selectNode(7,binaryTree.getRoot());

        System.err.println(binaryTreeSun.toString());

        binaryTree.traverseLevelOrder(binaryTree.getRoot());

        //删除节点
        BinaryTree binaryTrees = binaryTree.deleteNode(binaryTree,7);
        System.err.println(binaryTrees.toString());
    }

创建树完成后树结构为

查询节点树结构为

删除节点树结构为

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

答 案

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值