Java实现二叉查找树

package com.wy.tree;

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

/**
 * @date 2018/3/28 19:12
 * 二叉搜索树
 */
public class BST<Key extends Comparable<Key>,Value> {
    public Node root; //二叉搜索树根节点

    private class Node{
        private Key key; //键
        private Value value; //值
        private Node left,right; //指向子树的链接
        private int N; //以该节点为根的子树中的总数节点

        public Node(Key key,Value value,int N){
            this.key = key;
            this.value = value;
            this.N = N;
        }
    }
    // 构造函数, 默认构造一棵空二分搜索树
    public BST() {
        root = null;

    }


    //获取树的元素个数
    public int size(){
        return size(root);
    }
    private int size(Node root){
        if(root==null)
            return 0;
        return root.N;
    }
    //插入数据
    public void put(Key key,Value value){
        //增加数据,找到则更新数据,否则创建一个新的节点
        root = put(root,key,value);
    }
    private Node put(Node root,Key key,Value value){
        if(root==null) {
            return new Node(key, value, 1);
        }
        int cmp = key.compareTo( root.key );//将待插入的数据的键与根节点的键比较
        if(cmp<0){ //如果待插入的键小于根节点的键,则在左边插入
            root.left = put(root.left,key,value);
        }else if(cmp>0){
            root.right = put(root.right,key,value);
        }else{ //待插入的数据的键与根节点的键相等
            root.key = key;
        }
        // 更新数的元素个数
        root.N = size(root.left)+size(root.right)+1;
        return root;
    }
    // 查找操作
    public Value get(Key key){
        return get(root,key);
    }
    private Value get(Node root,Key key){
        // 在以root为根节点的子树中查找并返回key对于的值
        if(root==null)
            return null;
        int cmp = key.compareTo(root.key);
        if(cmp<0){ //则在左子树中查找
            return get(root.left,key);
        }else if(cmp>0){
            return get(root.right,key);
        }else{
            return root.value;
        }
    }

    //前序遍历 使用递归
    public void preOrder(Node root){
        if(root!=null){
            System.out.print( root.value+" " );
            preOrder(root.left);
            preOrder(root.right);
        }
    }
    //中序遍历 使用递归
    public void inOrder(Node root){
        if(root!=null){
            inOrder(root.left);
            System.out.print( root.value+" " );
            inOrder(root.right);
        }
    }
    //后序遍历 使用递归
    public void postOrder(Node root){
        if(root!=null){
            postOrder(root.left);
            postOrder(root.right);
            System.out.print( root.value+" " );
        }
    }
    //层次遍历
    public void levelOrder(Node root){
        Queue<Node> queue = new LinkedList<Node>();
        if(root!=null){
            queue.offer(root);
        }
        while (!queue.isEmpty()){
            root = queue.poll(); //出队,并移除该元素
            System.out.print( root.value+" " );
            //把左右孩子入队
            if(root.left!=null)
                queue.offer( root.left );
            if(root.right!=null)
                queue.offer( root.right);
        }
    }

    //最小值
    public Key min(){
        if(root==null)
            return null;
        return min(root).key;
    }
    private Node min(Node root){ //可以尝试非递归的写法
        if(root.left==null)//如果树的左孩子为空,则最小值就是根
            return root;
        return min(root.left);
    }
    //最大值
    public Key max(){
        if(root==null)
            return null;
        return max(root).key;
    }
    private Node max(Node root){ //可以尝试非递归的写法
        if(root.right==null)//如果树的左孩子为空,则最小值就是根
            return root;
        return max(root.right);
    }

    //删除最小值
    public void deleteMin(){
        //删除最小值后返回一个新的节点
        root = deleteMin(root);
    }
    private Node deleteMin(Node root) {
        if(root.left==null) //如果左孩子为空,则说明最小值就是根节点,那么新的二叉搜索树就是右子树,直接返回即可
            return root.right;
        root.left = deleteMin(root.left);
        root.N = size(root.left)+size(root.right)+1;
        return root;
    }

    //删除最大节点
    public void deleteMax(){
        root = deleteMax(root);
    }
    private Node deleteMax(Node root){
        if(root.right==null)
            return root.left;
        root.right = deleteMax(root.right);
        root.N = size(root.left)+size(root.right)+1;
        return root;
    }
    //删除节点  Hibbard算法 时间复杂度为 O(logn)
    public void delete(Key key){
        root = delete(root,key);
    }
    private Node delete(Node root,Key key){
        if(root==null)
            return null;
        int cmp = key.compareTo(root.key);
        if(cmp<0){
            root.left = delete(root.left,key);
        }else if(cmp>0){
            root.right = delete(root.right,key);
        }else{
            if(root.right==null) //删除的是没有右子树的情况
                return root.left;
            if(root.left==null)
                return root.right;
            //向把待删除的键复制一份
            Node t = root;
            //以t为根节点找到他右子树的最小节点
            root = min(t.right);
            //然后删除右子树中最小的节点,返回这颗右子树
            root.right = deleteMin(root.right);
            root.left = t.left;
        }
        root.N = size(root.left)+size(root.right)+1;
        return root;
    }

    //floor操作
    public Key floor(Key key){
        Node x = floor(root,key);
        if(x==null)
            return null;
        return x.key;
    }
    private Node floor(Node root, Key key) {
        if(root==null)
            return null;
        int cmp = key.compareTo(root.key);
        if(cmp==0){ //表示根节点正式我们要找的元素
            return root;
        }else if(cmp<0){
            return floor(root.left,key); //在左子树中去查找
        }
        Node t = floor(root.right,key); //可能在右子树中
        if(t!=null){
            return t;
        }else{
            return root;
        }
    }
    //ceiling
    public Key ceiling(Key key){
        Node x = ceiling(root,key);
        if(x==null)
            return null;
        return x.key;
    }
    private Node ceiling(Node root,Key key){
        if(root==null)
            return null;
        int cmp = key.compareTo(root.key);
        if(cmp==0){ //表示根节点正式我们要找的元素
            return root;
        }else if(cmp>0){
            return ceiling(root.right,key); //在左子树中去查找
        }
        Node t = floor(root.left,key); //可能在右子树中
        if(t!=null){
            return t;
        }else{
            return root;
        }
    }
    // 返回排名第 k的节点
    public Key select(int k){
        return select(root,k).key;
    }
    private Node select(Node root,int k){
        if(root==null)
            return null;
        //计算左子树的元素个数
        int t = size(root.left);
        if(k<t){ //排名第k的元素在左子树中
            return select(root.left,k);
        }else if(k>t){ //在右子树中排名,减去左子树的个数在减 1
            return select(root.right,k-t-1);
        }else{
            return root;
        }
    }
    //键的排名
    public int rank(Key key){
        return rank(root,key);
    }
    private int rank(Node root,Key key){
        if(root==null)
            return 0;
        int cmp = key.compareTo(root.key);
        if(cmp<0){
            return rank(root.left,key);
        }else if(cmp>0){ //在右子树中,则需要加上左子树的个数
            return 1+size(root.left)+rank(root.right,key);
        }else { //与根节点相等,则只需要计算左子树元素个数即可
            return size(root.left)+1;
        }
    }

}


测试用例

package com.wy.tree;

/**
 * @date 2018/3/28 19:38
 */
public class BSTTest {

    public static void main(String[] args) {

        BST<Integer, Integer> bst = new BST<Integer, Integer>();
        bst.put(6,6);
        bst.put(3,3);
        bst.put(14,14);
        bst.put(16,16);
        bst.put(10,10);
        bst.put(9,9);
        bst.put(13,13);
        bst.put(11,11);
        bst.put(12,12);


        System.out.println( bst.size() );
        System.out.println( bst.get(6));
        //前序遍历
        bst.preOrder( bst.root );
        System.out.println();
        bst.levelOrder(bst.root);
        System.out.println();
        System.out.println( "16排名第"+bst.rank(16) );
        System.out.println(bst.floor(15));
        System.out.println( bst.ceiling(15) );

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉查找树(Binary Search Tree)是一种常见的数据结构,它的每个节点最多有两个子节点,左子节点的值小于父节点的值,右子节点的值大于父节点的值。Java 实现二叉查找树的代码如下: ``` public class BinarySearchTree { private Node root; private class Node { private int key; private Node left; private Node right; public Node(int key) { this.key = key; } } public void insert(int key) { root = insert(root, key); } private Node insert(Node x, int key) { if (x == null) { return new Node(key); } if (key < x.key) { x.left = insert(x.left, key); } else if (key > x.key) { x.right = insert(x.right, key); } return x; } public boolean contains(int key) { return contains(root, key); } private boolean contains(Node x, int key) { if (x == null) { return false; } if (key == x.key) { return true; } else if (key < x.key) { return contains(x.left, key); } else { return contains(x.right, key); } } public void delete(int key) { root = delete(root, key); } private Node delete(Node x, int key) { if (x == null) { return null; } if (key < x.key) { x.left = delete(x.left, key); } else if (key > x.key) { x.right = delete(x.right, key); } else { if (x.left == null) { return x.right; } else if (x.right == null) { return x.left; } else { Node t = x; x = min(t.right); x.right = deleteMin(t.right); x.left = t.left; } } return x; } private Node min(Node x) { if (x.left == null) { return x; } else { return min(x.left); } } private Node deleteMin(Node x) { if (x.left == null) { return x.right; } x.left = deleteMin(x.left); return x; } } ``` 这段代码实现二叉查找树的插入、查找和删除操作。其中,插入操作使用递归实现,查找和删除操作也是递归实现的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值