用java构造一个二叉搜索树

java树的构造

public class BinearySearchTree<T extends Comparable<T>> { //让T具有可比性
    //树的结点
    private class Node<T> {
        private T ele;    //结点的值
        private Node left, right;    //分别指向左右孩子的索引
        private int frequence;   //元素出现的频率

        //构造方法
        public Node(T e) {
            this.ele = e;
            this.frequence = 1;
            this.left = this.right = null;
        }
    }

    //树的属性
    private Node<T> root;  //根节点
    private int size;   //树中结点个数

    public BinearySearchTree() {
        this.root = null;
        this.size = 0;
    }

    //获取树中结点的个数
    public int getSize() {
        return this.size;
    }

    //向以root为根的二分搜索树中添加元素
    public void add(T e) {
        //跟新根节点,因为递归完后根节点的左右孩子可能会有变化
        this.root = addDG(root, e);
    }

    //向以root为根的二分搜索树中添加元素递归
    private Node addDG(Node<T> root, T e) {
        //递归中止的条件
        if (root == null) {
            //表示找到添加的位置了
            this.size++;
            return new Node(e);
        }
        //递归操作
        //待插入元素小于当前节点元素,往左边添加
        if (root.ele.compareTo(e) > 0) {
            root.left = addDG(root.left, e);
        } else if (root.ele.compareTo(e) < 0) {
            root.right = addDG(root.right, e);
        } else {
            //如果相等说明树里面已经有此元素,则更新频率
            root.frequence++;
        }
        return root;
    }

    //查询
    public boolean search(T e) {
        return searchDG(this.root, e);
    }

    //从以root为根节点的二分搜索树中查询e递归
    private boolean searchDG(Node<T> root, T e) {
        //递归中止的条件
        if (root == null) {
            return false;
        }
        //递归操作
        if (root.ele.compareTo(e) == 0) {   //如果相等说明找到了返回true
            return true;
        } else if (root.ele.compareTo(e) > 0) {  //如果待查找元素小于根节点,就从左孩子处继续找
            return searchDG(root.left, e);
        } else {
            return searchDG(root.right, e);
        }
    }

    //二分搜索树的遍历

    //先序遍历 NLR
    public void preTravel() {
        //用abstractmap保存T元素类型和,Integer表示元素频率
        List<AbstractMap.SimpleEntry<T, Integer>> list = new ArrayList<>();
        preTravelDG(this.root, list);
        //显示list里的item
        //先把list变成流然后拆箱再对其中的每个元素收藏到一个string里进行显示
        System.out.println(list.stream().map(item -> "[" + item.getKey() + ": " + item.getValue() + "]").collect(Collectors.joining()));
    }

    //先序遍历以root为根的树,将结果保存在list中
    private void preTravelDG(Node<T> root, List<AbstractMap.SimpleEntry<T, Integer>> list) {
        //递归中止条件
        if (root == null) {
            return;
        }
        //先序遍历按中左右的顺序遍历
        //递归操作:
        //把元素添加到list里
        list.add(new AbstractMap.SimpleEntry<>(root.ele, root.frequence));
        //遍历左
        preTravelDG(root.left, list);
        //遍历右
        preTravelDG(root.right, list);
    }

    //中序遍历 LNR
    public void midTravel() {
        List<AbstractMap.SimpleEntry<T, Integer>> list = new ArrayList<>();
        midTravelDG(this.root, list);
        //显示list里的item
        //先把list变成流然后拆箱再对其中的每个元素收藏到一个string里进行显示
        System.out.println(list.stream().map(item -> "[" + item.getKey() + ": " + item.getValue() + "]").collect(Collectors.joining()));
    }

    //中序遍历以root为根的树,将结果保存在list中
    private void midTravelDG(Node<T> root, List<AbstractMap.SimpleEntry<T, Integer>> list) {
        //递归中止条件
        if (root == null) {
            return;
        }
        //先序遍历按中左右的顺序遍历
        //递归操作:
        //遍历左
        midTravelDG(root.left, list);
        //把元素添加到list里
        list.add(new AbstractMap.SimpleEntry<>(root.ele, root.frequence));
        //遍历右
        midTravelDG(root.right, list);
    }

    //后序遍历 LRN
    public void suffixTravel() {
        List<AbstractMap.SimpleEntry<T, Integer>> list = new ArrayList<>();
        suffixTravelDG(this.root, list);
        //显示list里的item
        //先把list变成流然后拆箱再对其中的每个元素收藏到一个string里进行显示
        System.out.println(list.stream().map(item -> "[" + item.getKey() + ": " + item.getValue() + "]").collect(Collectors.joining()));
    }

    //后序遍历以root为根的树,将结果保存在list中
    private void suffixTravelDG(Node<T> root, List<AbstractMap.SimpleEntry<T, Integer>> list) {
        //递归中止条件
        if (root == null) {
            return;
        }
        //先序遍历按中左右的顺序遍历
        //递归操作:
        //遍历左
        suffixTravelDG(root.left, list);
        //遍历右
        suffixTravelDG(root.right, list);
        //把元素添加到list里
        list.add(new AbstractMap.SimpleEntry<>(root.ele, root.frequence));
    }

    //判断树是否为空
    public boolean IsEmpty() {
        return this.size == 0;
    }

    //广度优先遍历:层序遍历,一层一层遍历
    public void levelTravel() {
        //判断树是否为空
        if (IsEmpty()) {
            return;
        }
        Queue<AbstractMap.SimpleEntry<Node<T>, Integer>> queue = new LinkedList<>();
        //先将根节点入队
        queue.add(new AbstractMap.SimpleEntry<>(this.root, 1));
        //遍历队列
        while (!queue.isEmpty()) {
            //出队
            AbstractMap.SimpleEntry<Node<T>, Integer> pair = queue.poll();
            //结点
            Node node = pair.getKey();
            int level = pair.getValue();
            System.out.println("[value:" + node.ele + ",level:" + level + "]  ");
            //判断左右子树是否为空
            if (node.left != null) {
                queue.add(new AbstractMap.SimpleEntry<>(node.left, level + 1));
            }
            if (node.right != null) {
                queue.add(new AbstractMap.SimpleEntry<>(node.right, level + 1));
            }
        }


    }

    //寻找树中最小元素
    public T getMinValue() {
        Optional<Node<T>> optional = getMinNode();
        //如果optional不为空返回ele,为空返回null
        if (optional.isPresent()) {
            return optional.get().ele;
        }
        return null;
    }

    private Optional<Node<T>> getMinNode() {
        if (this.root == null) {
            return Optional.empty();
        }
        //一直向左查找
        Node<T> node = this.root;
        while (node.left != null) {
            node = node.left;
        }
        return Optional.of(node);
    }

    public Node<T> getMinNode(Node<T> root){
        if (root == null) {
            return null;
        }
        //一直向左查找
        Node<T> node = root;
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

    //递归寻找最小元素
    public T DGgetMinValue() {
        Optional<Node<T>> optional = DGgetMinNode(this.root);
        //如果optional不为空返回ele,为空返回null
        if (optional.isPresent()) {
            return optional.get().ele;
        }
        return null;
    }

    private Optional<Node<T>> DGgetMinNode(Node<T> node) {
        //递归中止条件:
        //因为最小元素一定在左子树并且是最左边的位置
        if (node.left == null) {
            return Optional.of(node);
        }
        //递归操作
        return DGgetMinNode(node.left);
    }

    //寻找树中最大元素
    //找最大元素同理应该找最右边的元素
    public T getMaxValue() {
        Optional<Node<T>> optional = getMaxNode();
        //如果optional不为空返回ele,为空返回null
        if (optional.isPresent()) {
            return optional.get().ele;
        }
        return null;
    }

    private Optional<Node<T>> getMaxNode() {
        if (this.root == null) {
            return Optional.empty();
        }
        //一直向左查找
        Node<T> node = this.root;
        while (node.right != null) {
            node = node.right;
        }
        return Optional.of(node);
    }

    //递归寻找最大元素
    //找最大元素同理应该找最右边的元素
    public T DGgetMaxValue() {
        Optional<Node<T>> optional = DGgetMaxNode(this.root);
        //如果optional不为空返回ele,为空返回null
        if (optional.isPresent()) {
            return optional.get().ele;
        }
        return null;
    }

    private Optional<Node<T>> DGgetMaxNode(Node<T> node) {
        //递归中止条件:
        //因为最小元素一定在左子树并且是最左边的位置
        if (node.right == null) {
            return Optional.of(node);
        }
        //递归操作
        return DGgetMaxNode(node.right);
    }

    //删除最小结点
    public T removeMinNode() {
        if (this.IsEmpty()) {
            return null;
        }
        //保存最小结点
        T result = getMinValue();
        //更新根节点
        this.root = DGremoveMinNode(this.root);
        return result;
    }


    //语义:以node为根的二分搜索树中删除元素最小的结点
    //返回值为删除完最小结点之后的树的根节点
    private Node<T> DGremoveMinNode(Node<T> node) {
        //递归中止条件
        if (node.left == null) {
            //删除
            //1.记录右子树
            Node<T> rightTree = node.right;
            //失去关联关系
            node.right = null;
            //更新size
            this.size--;
            return rightTree;
        }
        //递归操作
        node.left = DGremoveMinNode(node.left);
        return node;
    }

    //删除最小结点
    public T removeMaxNode() {
        if (this.IsEmpty()) {
            return null;
        }
        //保存最小结点
        T result = getMaxValue();
        //更新根节点
        this.root = DGremoveMaxNode(this.root);
        return result;
    }

    //语义:以node为根的二分搜索树中删除元素最小的结点
    //返回值为删除完最小结点之后的树的根节点
    private Node DGremoveMaxNode(Node<T> node) {
        //递归中止条件
        if (node.right == null) {
            //删除
            //1.记录右子树
            Node<T> leftTree = node.left;
            //失去关联关系
            node.left = null;
            //更新size
            this.size--;
            return leftTree;
        }
        //递归操作
        node.right = DGremoveMaxNode(node.right);
        return node;
    }

    //删除任意节点
    public void remove(T ele) {
        //更新树结点
        this.root = DGremove(this.root, ele);
    }

    /*
    语义:以node为根的二分搜索树中删除值为ele的结点
    node 树的根节点
    ele 删除的结点值
    return 删除之后树的根节点
     */
    private Node<T> DGremove(Node<T> node, T ele) {
        //递归中止的条件
        //没有找到的情况:
        if (node == null) {
            return null;
        }
        //递归操作
        //找到了删除结点
        if (node.ele.compareTo(ele) == 0) {
            //node 是要删除的结点
            this.size--;
            //1.左空
            if(node.left==null){
                Node<T> rightNode=node.right;
                //取消关联关系
                node.right=null;
                return rightNode;
            }else if(node.right==null){
                //右空
                Node<T> leftNode=node.left;
                node.left=null;
                return leftNode;
            }
            else{    //左右都不空
                //把右子树中最小的结点放到删除结点的位置
                //从右子树中找到最小结点
                Node<T> suffixNode = getMinNode(node.right);
                //从右子树中删除最小结点并且返回删除后的子树的根节点
                suffixNode.right = DGremoveMinNode(node.right);
                suffixNode.left = node.left;
                //失去关联关系
                node.left=node.right=null;
                this.size++;
                return suffixNode;
            }
        }
        //没找到,如果node的大于ele说明ele在node的左子树,把左子树代进DGremove继续找
        else if (node.ele.compareTo(ele) > 0) {
            node.left = DGremove(node.left, ele);
        } else {
            node.right = DGremove(node.right, ele);
        }
        //返回根节点
        return node;
    }

    //删除根节点
    public void removeRoot(){
        if(this.root==null){
            return;
        }
        remove(this.root.ele);
    }
}
  • 14
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值