java实现二分搜索树

二分搜索树

  • 我们的二分搜索树不包含重复的元素

​ 如果想包含重复元素的话,只需要定义:

​ 左子树小于等于节点;或者右子树大于等于节点

我自己之前学习的数组和链表是可以拥有重复元素的

  • 二分搜索树添加元素的非递归写法,和链表很像
  • 二分搜索树方面的实现,我更关注递归实现

在现代计算机下,使用递归可能看不出来,但是在极端情况下还是可以看出来的


向二分搜索树中添加新的元素e

  /**
     * 向二分搜索树中添加新的元素e
     */
    public void add(E e){
        if(root==null){
            root=new Node(e);
            size++;
        }else{
            add(root ,e);

        }
    }

    /**
     * 向以node为根的二分搜索树种插入元素e,递归算法
     */
     private void add(Node node,E e){
         if(e.equals(node.e))
             return;
         else if(e.compareTo(node.e)<0&&node.left==null){
             node.left=new Node(e);
             size++;
             return;
         }else if (e.compareTo(node.e)>0&&node.right==null){
             node.right=new Node(e);
             size++;
             return;
         }
         //以上代码是递归终结条件
         
         if(e.compareTo(e)<0)
             add(node.left,e);
         else //e.compareTo(e)>0
       
            add(node.right,e);
     }


现在这个添加代码还是相对比较复杂的。

改进后的代码

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


      /**
     * 向以node为根的二分搜索树种插入元素e,递归算法
     * 返回插入信节点后二分搜索树的根
     *
     */
    private Node add(Node node ,E e ){
        //如果所在节点是空,就创建一个新的节点,返回给上一个递归调用
        if(node==null){
            size++;
            return new Node(e);
        }

        if(node.e.compareTo(e)<0){
            //比较e和当前节点的大小,判断左右孩子
            //如果是左孩子,将新创建好的节点,连接到左孩子
            //右边同理
            node.left  = add(node.left, e);
        }else if(node.e.compareTo(e)<0){
            node.right=add(node.right,e);
        }

        return node;
    }

二分搜索树中是否包含元素e

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

    /**
     * 看以node为根的二分搜索树中是否包含元素e,递归算法
     */
    private boolean contains(Node node, E e){
        if(node==null)
            return false;
        if(node.e.compareTo(e)==0)
            return  true;
        else if(node.e.compareTo(e)<0)
            
           return  contains(node.left,e);
        else //root.e.compareTo(e)>0
           return contains(node.right,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.left);
    }
    

前序遍历将二分搜索树打印

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

    /**
     * 生成以node为根节点,深度为depth的描述二叉树的字符串
     * @param node
     * @param depth
     * @param res
     */
    private void generateBSTString(Node node, int depth, StringBuilder res) {
        if(node==null){
            res.append(generateDepthString(depth)+"null\n");
            return;
        }

        res.append(generateDepthString(depth)+node.e+"\n");
        generateBSTString(node.left,depth+1,res);
        generateBSTString(node.right,depth+1,res);
    }

    private String generateDepthString(int depth) {
        StringBuilder res=new StringBuilder();
        for (int i = 0; i < depth; i++) {
            res.append("--");

        }
        return res.toString();

    }

输出结果:

5
--3
----2
------null
------null
----4
------null
------null
--6
----null
----8
------null
------null

‘--’代表深度为1
‘----’代表深度为2
以‘--’ 为一个深度,以此类推。

前序遍历的非递归方法

利用栈进行遍历

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

            if (cur.right != null)
                stack.push(cur.right);
            if (cur.left != null)
                stack.push(cur.left);
        }
    }

中序遍历二分搜索树

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

Tips:以中序遍历打印二分搜索树的时候打印的是 ,排序后的结果

后序遍历不再赘述

二分搜索树的层序遍历

利用队列进行控制

  /**
     * 二分搜索树的层序遍历
     */
    public void levelOrder(){
        Queue<Node> q=new LinkedList<>();
        q.add(root);
        while(!q.isEmpty()){
            Node cur=q.remove();
            System.out.println(cur.e);

            if(cur.left!=null)
                q.add(cur.left);
            if(cur.right!=null)
                q.add(cur.right);
        }

    }

寻找二分搜索树中的最小元素

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

    }
    public Node minimum(Node node){
        if(node.left==null)
            return node;
        return minimum(node.left);
    }

寻找二分搜索数中的最大元素

  /**
     * 寻找二分搜索树的最大元素
     * @return
     */
    public E maximum(){
        if(size==0)
            throw new IllegalArgumentException("BST is empty!");
        return maximum(root).e;
    }
    public Node maximum(Node node){
        if(node.right==null)
            return node;
        return maximum(node.right);
    }

删除二分搜索树中的最小值

/**
 * 从二分搜索树中删除最小值所在节点,返回最小值
 * @return
 */
public E removeMin(){
    E ret=minimum();

    root = removeMin(root);
    return ret;
}

/**
 * 删除掉以node为根的二分搜索树中的最小节点
 * 返回删除节点后新的二分搜索树的根
 * @param node
 * @return
 */
private Node removeMin(Node node){
    if(node.left==null){
        Node rightNode=node.right;
        node.right=null;
        size--;
        return rightNode;
    }
    node.left=removeMin(node.left);
    return node;
}

删除二分搜索树中的最大值

  /**
     * 从二分搜索树中删除最大值所在节点,返回最大值
     * @return
     */
    public E removeMax(){
        E ret=maximum();
        root=removeMax(root);
        return ret;
    }

    /**
     * 删除掉以node为根的二分搜索树中的最大节点
     * 返回删除节点后新的二分搜索树的根
     * @param node
     * @return
     */
    private Node removeMax(Node node ){
        if(node.right==null){
            Node leftNode=node.left;
            node.left=null;
            size--;
            return leftNode;
        }
        node.right =removeMax(node.right);
        return node;
    }

测试minimum()

import java.util.ArrayList;
import java.util.Random;

public class Main {



    public static void main(String[] args) {
        BST<Integer> bst = new BST<>();
        Random random = new Random();
        int n=1000;
        for (int i = 0; i < n; i++) {
            bst.add(random.nextInt(10000));
        }

        ArrayList<Integer> nums=new ArrayList<>();
        while (!bst.isEmpty()){
            nums.add(bst.removeMin());
        }
        System.out.println(nums);
        for (int i = 1; i < nums.size(); i++) {
            if(nums.get(i-1)>nums.get(i))
                throw new IllegalArgumentException("Error");
        }
        System.out.println("removeMin test completed.");

    
    }
}

输出结果:都是从小到大有序的

[3, 13, 21, 50, 52, 53, 54, 57, 74, 107, 112, 132, 137, 191, 193, 201, 225, 230, 240, 243, 257, 271, 288, 294, 298, 302, 305, 320, 339, 350, 358, 359, 385, 389, 391, 408, 410, 412, 420, 422, 459, 475, 482, 484, 495, 497, 515, 541, 542, 544, 564, 575, 579, 581, 585, 587, 614, 619, 645, 658, 674, 675, 679, 686, 688, 690, 721, 728, 744, 757, 767, 773, 778, 791, 797, 806, 821, 826, 831, 885, 905, 923, 926, 930, 932, 950, 979, 985, 997, 1009, 1015, 1026, 1050, 1056, 1068, 1088, 1096, 1112, 1132, 1133, 1137, 1151, 1184, 1198, 1205, 1208, 1212, 1213, 1230, 1248, 1265, 1267, 1276, 1279, 1291, 1310, 1341, 1351, 1368, 1379, 1383, 1388, 1422, 1430, 1440, 1442, 1446, 1459, 1470, 1502, 1521, 1528, 1535, 1551, 1561, 1571, 1575, 1589, 1595, 1602, 1614, 1620, 1624, 1633, 1636, 1641, 1678, 1679, 1687, 1695, 1708, 1710, 1712, 1714, 1716, 1735, 1738, 1739, 1756, 1765, 1770, 1786, 1803, 1823, 1827, 1829, 1832, 1844, 1846, 1847, 1849, 1858, 1870, 1915, 1937, 1944, 1975, 1980, 1991, 1992, 2018, 2027, 2032, 2037, 2046, 2061, 2064, 2089, 2099, 2124, 2126, 2132, 2133, 2157, 2167, 2174, 2185, 2193, 2226, 2238, 2246, 2253, 2254, 2255, 2268, 2277, 2295, 2297, 2304, 2314, 2325, 2328, 2336, 2337, 2342, 2353, 2375, 2381, 2390, 2396, 2408, 2409, 2419, 2424, 2439, 2460, 2471, 2488, 2489, 2492, 2498, 2504, 2509, 2524, 2531, 2532, 2536, 2545, 2548, 2559, 2568, 2571, 2572, 2576, 2582, 2589, 2590, 2606, 2610, 2613, 2633, 2647, 2657, 2663, 2699, 2704, 2705, 2706, 2732, 2733, 2734, 2751, 2754, 2758, 2771, 2774, 2787, 2789, 2792, 2798, 2801, 2802, 2816, 2818, 2824, 2828, 2836, 2846, 2868, 2871, 2887, 2890, 2893, 2895, 2902, 2905, 2939, 2952, 2958, 2977, 2985, 2987, 2993, 3030, 3036, 3056, 3082, 3087, 3097, 3127, 3130, 3139, 3158, 3163, 3176, 3191, 3206, 3223, 3225, 3228, 3230, 3236, 3244, 3267, 3271, 3279, 3284, 3296, 3297, 3298, 3303, 3319, 3321, 3324, 3354, 3375, 3378, 3387, 3397, 3403, 3410, 3428, 3433, 3435, 3437, 3442, 3448, 3453, 3460, 3463, 3482, 3490, 3498, 3512, 3522, 3532, 3535, 3536, 3543, 3551, 3552, 3555, 3557, 3559, 3566, 3575, 3593, 3608, 3638, 3646, 3647, 3659, 3660, 3663, 3672, 3691, 3698, 3703, 3705, 3708, 3709, 3721, 3732, 3738, 3749, 3754, 3769, 3777, 3785, 3792, 3796, 3809, 3812, 3821, 3822, 3838, 3847, 3854, 3872, 3895, 3908, 3911, 3915, 3916, 3921, 3931, 3941, 3969, 3972, 3977, 3980, 3989, 4005, 4008, 4035, 4036, 4054, 4057, 4070, 4072, 4078, 4079, 4083, 4090, 4099, 4123, 4128, 4134, 4140, 4143, 4149, 4159, 4162, 4198, 4199, 4204, 4209, 4215, 4228, 4241, 4246, 4255, 4270, 4286, 4292, 4293, 4294, 4306, 4314, 4321, 4331, 4333, 4334, 4340, 4342, 4347, 4359, 4370, 4385, 4397, 4401, 4402, 4404, 4420, 4422, 4434, 4454, 4467, 4473, 4483, 4486, 4492, 4502, 4504, 4508, 4509, 4511, 4514, 4516, 4525, 4529, 4543, 4554, 4562, 4563, 4581, 4599, 4605, 4620, 4631, 4650, 4665, 4672, 4675, 4688, 4704, 4723, 4732, 4737, 4738, 4740, 4758, 4763, 4779, 4786, 4803, 4824, 4829, 4838, 4847, 4851, 4872, 4887, 4888, 4894, 4905, 4907, 4919, 4924, 4936, 4941, 4958, 4974, 5005, 5010, 5012, 5032, 5044, 5049, 5082, 5091, 5110, 5114, 5135, 5144, 5146, 5147, 5163, 5167, 5174, 5191, 5221, 5230, 5233, 5243, 5255, 5274, 5275, 5276, 5320, 5347, 5353, 5389, 5396, 5400, 5420, 5427, 5445, 5446, 5456, 5464, 5481, 5495, 5550, 5551, 5563, 5598, 5599, 5602, 5604, 5606, 5629, 5680, 5683, 5686, 5719, 5721, 5729, 5731, 5735, 5738, 5740, 5747, 5749, 5754, 5778, 5780, 5794, 5821, 5833, 5843, 5861, 5864, 5892, 5893, 5939, 5944, 5945, 5946, 5964, 5983, 5993, 6005, 6015, 6016, 6018, 6029, 6033, 6041, 6054, 6077, 6078, 6091, 6111, 6130, 6131, 6164, 6177, 6187, 6196, 6198, 6199, 6205, 6207, 6208, 6216, 6219, 6232, 6238, 6248, 6271, 6294, 6301, 6306, 6310, 6329, 6344, 6346, 6349, 6367, 6384, 6387, 6430, 6436, 6441, 6448, 6450, 6451, 6455, 6460, 6461, 6480, 6483, 6496, 6507, 6517, 6529, 6538, 6558, 6567, 6571, 6574, 6578, 6598, 6610, 6614, 6616, 6636, 6693, 6695, 6707, 6734, 6738, 6758, 6779, 6782, 6785, 6828, 6837, 6838, 6841, 6869, 6870, 6873, 6919, 6929, 6931, 6940, 6968, 6976, 6980, 6986, 6999, 7020, 7054, 7055, 7092, 7105, 7107, 7108, 7111, 7125, 7129, 7130, 7132, 7140, 7150, 7151, 7152, 7154, 7157, 7160, 7174, 7177, 7183, 7211, 7212, 7252, 7263, 7303, 7310, 7317, 7320, 7355, 7357, 7365, 7369, 7382, 7383, 7386, 7418, 7433, 7434, 7459, 7482, 7483, 7546, 7553, 7554, 7579, 7609, 7614, 7621, 7623, 7630, 7643, 7684, 7692, 7711, 7720, 7721, 7722, 7734, 7736, 7751, 7764, 7770, 7772, 7777, 7779, 7808, 7819, 7824, 7828, 7836, 7850, 7866, 7908, 7920, 7934, 7937, 7971, 7990, 8037, 8046, 8049, 8082, 8110, 8119, 8129, 8133, 8135, 8163, 8165, 8167, 8170, 8174, 8186, 8199, 8211, 8234, 8237, 8240, 8253, 8255, 8258, 8265, 8274, 8281, 8295, 8300, 8333, 8369, 8370, 8428, 8431, 8442, 8451, 8456, 8472, 8480, 8491, 8521, 8525, 8538, 8540, 8542, 8551, 8557, 8561, 8567, 8568, 8571, 8580, 8596, 8602, 8609, 8610, 8612, 8630, 8642, 8653, 8663, 8668, 8704, 8710, 8747, 8754, 8761, 8773, 8774, 8779, 8792, 8808, 8820, 8825, 8827, 8840, 8843, 8859, 8897, 8937, 8942, 8946, 8956, 8957, 8969, 8971, 8973, 8980, 8993, 8998, 9000, 9020, 9041, 9043, 9052, 9064, 9080, 9110, 9113, 9118, 9172, 9184, 9204, 9207, 9208, 9212, 9217, 9232, 9248, 9252, 9271, 9274, 9282, 9293, 9302, 9308, 9316, 9331, 9341, 9346, 9357, 9362, 9370, 9371, 9372, 9392, 9416, 9429, 9438, 9441, 9447, 9453, 9454, 9465, 9468, 9484, 9485, 9511, 9517, 9531, 9540, 9543, 9550, 9566, 9567, 9576, 9604, 9607, 9608, 9616, 9637, 9639, 9640, 9653, 9668, 9673, 9712, 9713, 9718, 9720, 9726, 9738, 9748, 9751, 9756, 9765, 9767, 9777, 9801, 9802, 9821, 9826, 9870, 9872, 9899, 9904, 9921, 9940, 9945, 9949, 9956, 9963, 9967, 9977, 9978, 9984, 9997]
removeMin test completed.

二分搜索树中删除任意元素e

/**
     *
     * 从二分搜索树中删除元素为e的节点
     * @param e
     */
    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.compareTo(node.e) == 0
            //待删除节点左子树为空的情况
            if(node.left==null){
                Node rightNode=node.right;
                node.right=null;
                size--;
                return rightNode;
            }

            //待删除节点右子树为空的情况
            if(node.right==null){
                Node leftNode=node.left;
                node.left=null;
                size--;
                return leftNode;
            }

            //待删除节点左右子树均不为空的情况

            //找到比待删除节点大的最小节点,即待删除节点右子树的最小节点
            //用这个节点顶替待删除节点的位置
            Node successor=minimum(node.right);
            successor.right=removeMin(node.right);
            successor.left=node.left;
            node.left=node.right=null;
            return successor;

        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值