二叉搜索树的实现

本文详细介绍了二叉搜索树(BST)的概念,包括其定义、特性以及前序、中序、后序遍历。此外,还提供了一个完整的Java实现,包括节点类和二叉搜索树类,实现了插入、查找、删除节点等基本操作。通过示例展示了如何在二叉搜索树中进行增删查改,并给出了层次遍历和计算最大高度的方法。
摘要由CSDN通过智能技术生成

二叉搜索树(BST)

  • 二叉搜索树它是二叉树的一种类别,其节点按特定顺序排列。这也称为有序二叉树。
  • 在二叉搜索树中,左子树中所有节点的值小于根的值。
  • 类似地,右子树中所有节点的值大于或等于根的值。
  • 此规则将递归地应用于根的所有左子树和右子树。
    在这里插入图片描述

前序遍历:30,15,7,22,17,27,60,45,75
中序遍历: 7,15,17,22,27,30,45,60,75
后序遍历:7,17,27,22,15,45,75,60,30

二叉查找树的实现:
API设计:
1.节点类:
在这里插入图片描述

2.二叉搜索树类:
在这里插入图片描述在这里插入图片描述

//节点类
public class Node<K, V> {

    //为了方便使用,成员变量设置为public
    public Node left;   //记录左子节点
    public Node right;  //记录右子节点
    public K key;   //键
    public V value; //值

    public Node(K key, V value, Node left, Node right) {
        this.key = key;
        this.value = value;
        this.left = left;
        this.right = right;
    }
}
//K extends Comparable<K> 让我们的key具有排序的功能
public class BinaryTree<K extends Comparable<K>,V> {

    private Node root;  //记录根节点
    private int N;  //记录树中元素个数

    public BinaryTree() {}

    /**
     * 向树中插入一个节点
     * @param key 节点的键
     * @param value 节点的值
     */
    public void put(K key, V value){
        root = put(root, key, value);
    }

    /**
     * 向指定树x中插入一个节点
     * 1.如果x==null,则创建节点,作为x
     * 2.如果x!=null
     *      2.1 如果 key < x.key, 则往左子树插入
     *      2.2 如果 key > x.key, 则往右子树插入
     *      2.3 如果 key == x.key, 则将x.value 替换为 value
     * @param x 树x的根节点
     * @param key 节点的键
     * @param value 节点的值
     * @return 插入节点后的新树
     */
    private Node put(Node x, K key, V value){
        //1.如果x==null,则创建节点,作为x
        if(x == null){
            N++;
            return new Node<K,V>(key, value, null, null);
        }
        //2.如果x!=null
        int cmp = key.compareTo((K)x.key);
        if(cmp < 0){
            //2.1 如果 key < x.key, 则往左子树插入
            x.left = put(x.left, key, value);
        }else if(cmp > 0){
            //2.2 如果 key > x.key, 则往右子树插入
            x.right = put(x.right, key, value);
        }else{
            //2.3 如果 key == x.key, 则将x.value 替换为 value
            x.value = value;
        }
        return x;
    }


    /**
     * 根据key查找节点的值
     * @param key 要查找的节点的键
     * @return 返回查找到的节点的值
     */
    public V get(K key){
        return get(root, key);
    }

    /**
     * 从指定的树x中,找出key对应的值
     * 1.如果x==null,则返回null
     * 2.如果x!=null
     *      2.1 如果 key < x.key, 则往左子树查找
     *      2.2 如果 key > x.key, 则往右子树查找
     *      2.3 如果 key == x.key, 则找到,并返回value
     * @param x 指定的树的根节点
     * @param key 要查找的节点的键
     * @return 查找到的节点的值,未找到则返回null
     */
    private V get(Node x, K key){
        // 1.如果x==null,则返回null
        if(x == null) return null;
        // 2.如果x!=null
        int cmp = key.compareTo((K) x.key);
        if(cmp < 0){
            // 2.1 如果 key < x.key, 则往左子树查找
            return get(x.left, key);
        }else if(cmp > 0){
            // 2.2 如果 key > x.key, 则往右子树查找
            return get(x.right, key);
        }else{
            // 2.3 如果 key == x.key, 则找到,并返回value
            return (V) x.value;
        }
    }


    /**
     * 删除树中指定的key的节点
     * @param key  要删除的节点的key
     */
    public void delete(K key){
        root = delete(root, key);
    }

    /**
     * 从指定树x中删除指定key的节点
     * @param x 指定树x的根节点
     * @param key 要删除的节点的key
     * @return 返回删除后的新树
     */
    private Node delete(Node x, K key){
        //1.如果 x==null,返回null
        if(x == null) return null;
        //2.如果x != null
        int cmp = key.compareTo((K)x.key);
        if(cmp < 0){
            // 2.1 如果 key < x.key, 则往左子树查找
            x.left = delete(x.left, key);
        }else if(cmp > 0){
            // 2.2 如果 key > x.key, 则往右子树查找
            x.right = delete(x.right, key);
        }else{
            N--;
            // 2.3 如果 key == x.key,找到要删除的节点,删除该节点,有3种情况
            if(x.right == null){
                // 2.3.1 如果 右子树为null,则返回x节点的左子树
                return x.left;
            }else if (x.left == null){
                // 2.3.2 如果 左子树为null,则返回x节点的右子树
                return x.right;
            }else{
                // 2.3.3 x节点的左右子树都不为null,我们需要查找x节点的右子树中最小的节点 node
                //将该节点替换要删除的节点

                //2.3.3.1 查找x的右子树的最小节点node及其父节点pre
                Node<K,V> node = x.right, pre = null;
                while(node.left != null){
                    pre = node;
                    node = node.left;
                }
                if(pre != null) pre.left = null;    //断开node节点
                else x.right = null;

                //2.3.3.2 将node节点的左右指针指向x节点的左右子树
                node.left  = x.left;
                node.right = x.right;
                //2.3.3.3 将node节点 代替 原来的x节点
                x = node;
            }
        }
        return x;
    }

    /**
     * 获取树中节点的个数
     * @return 返回节点个数
     */
    public int size(){
        return N;
    }


    /**
     * 获取二叉搜素树的最小键
     * @return
     */
    public K min(){
        return (K) minNode(root).key;
    }

    /**
     * 查找树x的最小节点
     * @param x
     * @return
     */
    private Node minNode(Node x){
        if(x.left == null){
            return x;
        }
        return minNode(x.left);
    }

    /**
     * 获取二叉搜素树的最大键
     * @return
     */
    public K max(){
        return (K) maxNode(root).key;
    }

    /**
     * 查找树x的最大节点
     * @param x
     * @return
     */
    private Node maxNode(Node x){
        if(x.right == null){
            return x;
        }
        return maxNode(x.right);
    }


    /**
     * 中序遍历整个树
     */
    public void inOrder(){
        inOrder(root);
    }


    /**
     * 中序遍历
     * @param x 遍历的树的根节点
     */
    private void inOrder(Node x){
        if(x != null){
            inOrder(x.left);
            System.out.print("[" + x.key + "," + x.value + "] ");
            inOrder(x.right);
        }
    }

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

    /**
     * 前序遍历
     * @param x
     */
    private void preOrder(Node x){
        if(x != null){
            System.out.print("[" + x.key + "," + x.value + "] ");
            preOrder(x.left);
            preOrder(x.right);
        }
    }

    /**
     * 后序遍历
     */
    public void afterOrder(){
        afterOrder(root);
    }

    /**
     * 后序遍历
     * @param x
     */
    private void afterOrder(Node x){
        if(x != null){
            afterOrder(x.left);
            afterOrder(x.right);
            System.out.print("[" + x.key + "," + x.value + "] ");
        }
    }

    /**
     * 层次遍历
     */
    public void levelOrder(){
        levelOrder(root);
    }

    /**
     * 层次遍历
     * @param x
     */
    private void levelOrder(Node x){
        if(x == null) return;
        Queue<Node> qu = new ArrayDeque<Node>();
        qu.offer(x);
        //a:每一层的节点个数,b:统计每一层的节点个数
        int a = 1, b = 0;
        while(!qu.isEmpty()){
            Node pollNode = qu.poll();
            a--;
            System.out.print(pollNode.key+" ");
            if(pollNode.left != null){
                b++;
                qu.offer(pollNode.left);
            }
            if(pollNode.right != null){
                b++;
                qu.offer(pollNode.right);
            }
            if(a == 0){
                a = b;
                b = 0;
                System.out.println();
            }
        }
    }


    /**
     * 获取树的最大高度
     * @return
     */
    public int maxHeight(){
        return maxHeight(root);
    }

    /**
     * 获取树x的高度
     * @param x
     * @return
     */
    private int maxHeight(Node x){
        if(x == null) return 0;
        //左子树的高度
        int leftHeight = maxHeight(x.left);
        //右子树的高度
        int rightHeight = maxHeight(x.right);
        //返回左右子树高的 + 1
        return Math.max(leftHeight, rightHeight) + 1;
    }
}
以下是Java实现二叉搜索树的基本步骤和代码示例: 1.定义二叉搜索树节点 ```java class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } ``` 2.定义二叉搜索树 ```java class BST { private TreeNode root; public BST() { root = null; } // 向二叉搜索树中插入元素 public void insert(int val) { root = insert(root, val); } private TreeNode insert(TreeNode node, int val) { if (node == null) { return new TreeNode(val); } if (val < node.val) { node.left = insert(node.left, val); } else if (val > node.val) { node.right = insert(node.right, val); } return node; } // 在二叉搜索树中查找元素 public boolean search(int val) { return search(root, val); } private boolean search(TreeNode node, int val) { if (node == null) { return false; } if (val == node.val) { return true; } else if (val < node.val) { return search(node.left, val); } else { return search(node.right, val); } } // 删除二叉搜索树中的元素 public void delete(int val) { root = delete(root, val); } private TreeNode delete(TreeNode node, int val) { if (node == null) { return null; } if (val < node.val) { node.left = delete(node.left, val); } else if (val > node.val) { node.right = delete(node.right, val); } else { if (node.left == null) { return node.right; } else if (node.right == null) { return node.left; } TreeNode minNode = findMin(node.right); node.val = minNode.val; node.right = delete(node.right, node.val); } return node; } private TreeNode findMin(TreeNode node) { while (node.left != null) { node = node.left; } return node; } } ``` 3.测试代码 ```java public class TestBST { public static void main(String[] args) { BST bst = new BST(); bst.insert(5); bst.insert(3); bst.insert(7); bst.insert(1); bst.insert(9); System.out.println(bst.search(3)); // 输出:true bst.delete(3); System.out.println(bst.search(3)); // 输出:false } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值