二分搜索树实现

二分搜索树删除任意节点

只有右孩子的节点

与删除最小元素的情况相同    

只有左孩子的节点

与删除最大元素的情况相同

叶子节点

即可以当做只有左孩子的节点也可以当做只有右孩子的节点

既有左孩子又有右孩子的节点

待删除的节点记作d
找到右子树中最小的节点来替代待删除的节点,右子树中最小的节点记作s,s是d的后继

s=min(d->right)

s->right=delMin(d->right)
s-left=d->left

二分搜索树的相关实现 ##

二分搜索树的相关实现

package com.learn.xt.bst;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class BST <E extends Comparable<E>> {

    private class Node{
        public E e;
        public Node left;
        public Node right;

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

    private Node root;
    private int size;

    public BST(){
        root=null;
        size=0;
    }

    public int size(){
        return size;
    }

    public boolean isEmpty(){
        return size==0;
    }

    public void add(E e){
        root=add(root,e);
    }

    /**
     * 向以node为根的二分搜索树中插入元素e
     * @param node
     * @param e
     * @return  返回根节点
     */
    private Node add(Node node,E e){
        if(node==null){
            size++;
            return new Node(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;
    }

    /**
     * 查看二分搜索树中是否包含元素e
     * @param e
     * @return
     */
    public boolean contain(E e){
        return contain(root,e);
    }

    /**
     * 查看以node为根的二分搜索树中是否包含元素e
     * @param node
     * @param e
     * @return
     */
    public boolean contain(Node node,E e){

        if(node==null){
            return false;
        }
        if(e.compareTo(node.e)<0){
            return contain(node.left,e);
        }else if(e.compareTo(node.e)>0){
            return contain(node.right,e);
        }else{
            return true;
        }
    }

    /**
     * 中序遍历
     * 二分搜索树的中序输出是排好序的
     */
    public void inOrder(){
        inOrder(root);
    }

    /**
     * 以node为根二分搜索树的中序遍历
     * @param node
     */
    private void inOrder(Node node){
        if(node==null){
            return;
        }
        inOrder(node.left);
        System.out.println(node.e);
        inOrder(node.right);
    }

    /**
     * 后续遍历
     */
    public void bgOrder(){
        bgOrder(root);
    }

    /**
     * 以node为根二分搜索树的后续遍历
     * @param node
     */
    private void bgOrder(Node node){
        if(node==null){
            return;
        }
        bgOrder(node.left);
        bgOrder(node.right);
        System.out.println(node.e);
    }

    /**
     * 前序遍历
     */
    public void preOrder(){
        preOrder(root);
    }

    /**
     * 以node为根二分搜索树的前序遍历
     * @param node
     */
    private void preOrder(Node node){
        if(node==null){
            return;
        }
        System.out.println(node.e);
        preOrder(node.left);
        preOrder(node.right);
    }

    public static void main(String[] args) {
        BST<Integer> bst=new BST<>();
        int[] nums={1,5,3,6,4};
        for(int num:nums){
            bst.add(num);
        }

        bst.preOrder();
    }

    @Override
    public String toString(){
        StringBuilder res=new StringBuilder();
        generateBSTString(root,0,res);
        return res.toString();
    }

    private void generateBSTString(Node node,int depth,StringBuilder res){
        if(node==null){
            res.append(generateDepthString(depth)+"null\n");
            return;
        }
        res.append(generateDepthString(depth).concat(node.e+"\n"));
        generateBSTString(node.left,depth+1,res);
        generateBSTString(node.right,depth+1,res);
    }

    /**
     * 用来生成前面的--
     * @param depth  树的深度
     * @return
     */
    private String generateDepthString(int depth){
        StringBuilder res=new StringBuilder();
        for(int i=0;i<depth;i++){
            res.append("--");
        }
        return res.toString();
    }

    /**
     * 二分搜索树的前序非递归写法
     * 需要借助栈的数据结构,
     * 1.先初始化栈,把跟节点入栈
     * 2.再循环,直到栈为空
     *      2.1  出栈,获取当前栈
     *      2.2  访问当前栈
     *      2.3  当前栈的右子树不为空时将当前栈的右子树入栈
     *      2.4  当前栈的左子树不为空时将当前栈的左子树入栈
     */
    public void preOrderNR(){
        Stack<Node> stack=new Stack<>();
        stack.push(root);
        while(!stack.isEmpty()){
            Node curNode=stack.pop();
            System.out.println(curNode.e);
            if(curNode.right!=null){
                stack.push(curNode.right);
            }
            if(curNode.left!=null){
                stack.push(curNode.left);
            }
        }
    }

    /**
     * 广度优先遍历
     */
    public void levelOrder(){
        Queue<Node> que=new LinkedList<>();
        que.add(root);
        while(!que.isEmpty()){
            Node curentNode = que.remove();
            System.out.println(curentNode.e);
            if(curentNode.left!=null){
                que.add(curentNode.left);
            }
            if(curentNode.right!=null){
                que.add(curentNode.right);
            }
        }

    }

    /**
     * 返回二分搜索树的最小元素
     * @return
     */
    public E minmum(){
        if(size==0){
            throw new IllegalArgumentException("BST is empty");
        }
        return minmum(root).e;
    }

    /**
     * 寻找二分搜索树中以node为根的最小的节点
     * @param node
     * @return
     */
    public Node minmum(Node node){
        if(node.left==null){
            return node;
        }
        return minmum(node.left);
    }

    /**
     * 返回二分搜索树的最大元素
     * @return
     */
    public E maxmum(){
        if(size==0){
            throw new IllegalArgumentException("BST is empty");
        }
        return maxmum(root).e;
    }

    /**
     * 寻找二分搜索树中以node为根的最小的节点
     * @param node
     * @return
     */
    public Node maxmum(Node node){
        if(node.right==null){
            return node;
        }
        return maxmum(node.right);
    }

    /**
     * 删除最小的元素
     * @return
     */
    public E removeMin(){
        E ret=minmum();
        root=removeMin(root);
        return ret;
    }

    /**
     * 删除以node为根的最小元素
     * @param node
     * @return
     */
    public Node removeMin(Node node){
        if(node.left==null){
            Node rigthNode=node.right;
            node.right=null;
            size--;
            return rigthNode;
        }
        node.left=removeMin(node.left);
        return node;
    }

    /**
     * 删除二分搜索树中的任意元素
     */
    public void remove(E e){
        root=remove(root,e);
    }

    /**
     * 删除以node为根,节点元素为e的节点
     * @param node
     * @param e
     * @return  返回新的二分搜索树
     */
    private Node remove(Node node,E e){
        if(node==null)
            return null;
        if(e.compareTo(node.e)<0){
            node.left=remove(node.left,e);
            return node;
        }else if(e.compareTo(node.e)>0){
            node.right=remove(node.right,e);
            return node;
        }else{//e==node.e的情况  也是递归结束的情况

            //如果左子树为null
            if(node.left==null){
                Node rightNode=node.right;
                node.right=null;
                size--;
                return rightNode;
            }

            //如果右子树为null
            if(node.right==null){
                Node leftNode=node.left;
                node.left=null;
                size--;
                return leftNode;
            }

            //待删除节点左右子树均不为null
            Node successor=minmum(node.right);
            successor.right=removeMin(node.right);
            successor.left=node.left;
            node.left=null;
            node.right=null;
            return successor;
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值