ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

BST二分搜索树(二叉树)

2022-07-10 18:05:08  阅读:143  来源: 互联网

标签:二分 node right return cur BST 二叉树 null left


java实现二叉树

 

1、定义数据结点

    class Node<E> {
        E e;
        Node<E> left, right;

        int size, depth;// 扩展

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

        public Node(E e) {
            this.e = e;
            this.left = null;
            this.right = null;
        }
    }

 

2、插入结点

    /**
     * BST添加元素
     * 
     * @return
     */
    public void add(E e) {
        root = add(root, e);
    }

    /**
     * 向以node为根的二分搜索树中插入元素e,递归算法 返回插入新节点后二分搜索树的根
     * 
     * @return
     */
    private Node<E> add(Node<E> node, E e) {
        if (node == null) {
            size++;
            return new Node<E>(e);
        }

        if (e.compareTo(node.e) < 0) {
            node.left = add(node.left, e);
        } else if (e.compareTo(node.e) > 0) {
            node.right = add(node.right, e);
        }

        return node;
    }

 

3、查询最小值

    /**
     * BST最小值
     * 
     * @param node
     */
    public E min() {
        if (isEmpty()) throw new IllegalArgumentException("BST is isEmpty");

        return min(root).e;
    }

    private Node<E> min(Node<E> node) {
        if (node.left == null) return node;
        
        return min(node.left);
    }

 

 

4、查询最大值

    /**
     * BST最大值
     * 
     * @param node
     */
    public E max() {
        if (isEmpty()) throw new IllegalArgumentException("BST is isEmpty");
        
        return max(root).e;
    }

    private Node<E> max(Node<E> node) {
        if (node.right == null) return node;
        
        return max(node.right);
    }

 

 

5、判断是否存在

    /**
     * 判断是否存在
     * 
     * @param e
     * @return
     */
    public boolean contains(E e) {
        return contains(root, e);
    }

    private boolean contains(Node<E> node, E e) {
        if (node == null) return false;

        if (e.compareTo(node.e) == 0) return true;
        //左子树
        else if (e.compareTo(node.e) < 0)  return contains(node.left, e);
        //右子树
        else return contains(node.right, e);
    }

 

 

6、删除最小值

    /**
     * BST删除最小值
     * 
     * @param node
     */
    public E removeMin() {
        E min = min();

        root = removeMin(root);

        return min;
    }

    /**
     * 向以node为根的二分搜索树中删除元素,递归算法 返回待删除节点后二分搜索树的根
     * 
     */
    private Node<E> removeMin(Node<E> node) {
        if (node.left == null) {
            BST<E>.Node<E> right = node.right;
            node = null;
            return right;// 返回最左节点
        }

        // 存在右子树
        node.left = removeMin(node.left);
        
        size--;
        return node;
    }

 

 

7、删除最大值

    /**
     * BST删除最大值
     * 
     * @param node
     */
    public E removeMax() {
        E max = max();

        root = removeMax(root);

        return max;
    }

    /**
     * 向以node为根的二分搜索树中删除元素,递归算法 返回待删除节点后二分搜索树的根
     * 
     */
    private Node<E> removeMax(Node<E> node) {
        if (node.right == null) {
            Node<E> left = node.left;
            left.right = null;
            return left;// 返回最左节点
        }

        // 存在右子树
        node.right = removeMax(node.right);
        
        size--;
        return node;
    }

 

 

8、删除指定元素

 

/**
     * BST删除指定元素
     * 
     * @param node
     */
    public void remove(E e) {
        root = remove(root, e);
    }

    /**
     * 向以node为根的二分搜索树中删除元素,递归算法 返回待删除节点后二分搜索树的根 
     * 1、头结点 
     * 2、叶子节点
     * 3、非叶子节点:①只有右子树;②只有左子树;③有左右子树
     * 
     */
    private Node<E> remove(Node<E> node, E e) {
        if (node == null) return null;

        if (e.compareTo(node.e) == 0) {
            size--;
            //①只有右子树;
            if (node.left == null) return node.right;
            //②只有左子树
            if (node.right == null) return node.left;

            // ③有左右子树 重新选举节点:后驱法(右子树最小值)、前驱法(左子树最大值)
  Node<E> rightMinNode = removeMin(node.right); 
rightMinNode.left = node.left;
rightMinNode.right = node.right;
       return rightMinNode;
 

// Node<E> lefgMaxNode = removeMax(node.left);
// lefgMaxNode.left = node.left;
// lefgMaxNode.right = node.right;

// return lefgMaxNode ;

        } else if (e.compareTo(node.e) < 0) {

            node.left = remove(node.left, e);
        } else {
            node.right = remove(node.right, e);
        }
        return node;
    }

 

 

9、前序遍历

 

    /**
     * BST前序遍历-非递归
     */
    public void preOrderTraverseNR() {
        Stack<Node<E>> stack = new Stack<Node<E>>();
        stack.push(root);
        while (!stack.isEmpty()) {
            Node<E> cur = stack.pop();
            System.out.println(cur.e);

            // 栈:先进后出特性决定,右子树先入栈
            if (cur.right != null) stack.push(cur.right);
            
            if (cur.left != null) stack.push(cur.left);
        }
    }

 

 

    /**
     * BST前序遍历-深度优先遍历(Depth First Search)
     * 
     * @param node
     */
    public void preOrderTraverse() {
        preOrderTraverse(root);
    }

    /**
     * BST前序遍历:①. 根----->左------->右  ②. 根据前序遍历的结果可知第一个访问的必定是root结点
     * 
     * @param node
     */
    private void preOrderTraverse(Node<E> node) {
        if (node == null) return;

        System.out.println(node.e);
        
        preOrderTraverse(node.left);
        
        preOrderTraverse(node.right);
    }

 

 

 

10、中序遍历

 

 

    /**
     * BST中序遍历-非递归
     */
    public void midOrderTraverseNR() {
        Stack<Node<E>> stack = new Stack<Node<E>>();
        Node<E> cur = root;
        while (cur!= null || !stack.isEmpty()) {
            //一路向左走到最左侧节点
            while(cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            //此时到达最左侧节点
            cur = stack.pop();
            System.out.println(cur.e);
            cur = cur.right;
        }
    }

 

    /**
     * BST中序遍历:
     * 
     * @param node
     */
    public void midOrderTraverse() {
        midOrderTraverse(root);
    }

    /**
     * BST中序遍历:①. 左----->根------->右 ②. 根据中序遍历的结果,再结合前序遍历的root结点去划分root结点的左右子树。
     * 
     * @param node
     */
    private void midOrderTraverse(Node<E> node) {
        if (node == null) return;

        midOrderTraverse(node.left);
        
        System.out.println(node.e);
        
        midOrderTraverse(node.right);
    }

 

 

11、后续遍历

 

    /**
     * BST后序遍历-非递归
     */
    public void afterOrderTraverseNR() {
        Stack<Node<E>> stack = new Stack<Node<E>>();
        Node<E> cur = root;
        Node<E> pre = null;
        while (cur != null || !stack.isEmpty()) {
            //所有左节点入栈
            while(cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            //此时到达最左侧节点
            cur = stack.pop();
            
            //没有右结点
            if(cur.right == null) {
                System.out.println(cur.e);
                pre = cur;
                cur = null;//已遍历结点置空
                continue;
            }
            
            //二次访问父节点
            if(cur.right == pre) {
                System.out.println(cur.e);
                pre = cur;
                cur = null;//已遍历结点置空
                continue;
            }
            
            //父节点二次入栈
            stack.push(cur);
            //访问右结点
            cur = cur.right;
        }
    }

 

    /**
     * BST后序遍历:
     * 
     * @param node
     */
    public void afterOrderTraverse() {
        afterOrderTraverse(root);
    }

    /**
     * BST后序遍历 
     *     应用:内存释放 ①. 左------>右------>根  ②. 根据后序遍历的结果可知最后访问的必定是root结点。
     * 
     * @param node
     */
    private void afterOrderTraverse(Node<E> node) {
        if (node == null) return;

        afterOrderTraverse(node.left);
        
        afterOrderTraverse(node.right);
        
        System.out.println(node.e);
    }

 

标签:二分,node,right,return,cur,BST,二叉树,null,left
来源: https://www.cnblogs.com/wangymd/p/16456288.html

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

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

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

ICode9版权所有