二叉搜索树(Java实现)

二叉搜索树基本操作

求树中的结点个数
判断节点是否为空
向树中插入新结点key-value
树中是否存在key
返回树中key对应的value值
先序遍历
中序遍历
后续遍历
层序遍历
求树中key最小的结点
求树中key最大的结点
删除树中key最小的结点
删除树中key最大的结点
树中删除一个结点

  代码:

/**
 * @param <Key> 键的泛型
 * @param <Value> 值的泛型
 */
public class BinarySearchTree<Key extends Comparable<? super Key>, Value> {
    private class Node {
        private Key key; // 键,相当于词典里的单词
        private Value value; // 值,相当于词典里的解释
        private Node left; // 左孩子结点
        private Node right;// 右孩子结点

        //结点的构造函数
        public Node(Key key, Value value) {
            this.key = key;
            this.value = value;
            this.left = null;
            this.right = null;
        }

        // getters  and  setters
        public Key getKey() {
            return key;
        }

        public void setKey(Key key) {
            this.key = key;
        }

        public Value getValue() {
            return value;
        }

        public void setValue(Value value) {
            this.value = value;
        }

        public Node getLeft() {
            return left;
        }

        public void setLeft(Node left) {
            this.left = left;
        }

        public Node getRight() {
            return right;
        }

        public void setRight(Node right) {
            this.right = right;
        }

        @Override
        public String toString() {
            return "Node{" +
                    "key=" + key +
                    ", value=" + value +
                    ‘}‘;
        }
    }

    private Node root; // 二叉搜索树的根节点
    private int size; //二叉搜索树中的结点个数

    //树的构造函数
    public BinarySearchTree() {
        this.root = null;
        this.size = 0;
    }

    //求树中的结点个数
    public int size() {
        return this.size;
    }

    //判断节点是否为空
    public boolean isEmpty() {
        return this.size == 0;
    }

    //以node结点为根的树(子树)中插入key-value
    private Node insert(Node node, Key key, Value value) {
        if (node == null) {
            size++;
            return new Node(key, value);
        } else if (node.key.compareTo(key) > 0) {
            node.setLeft(insert(node.getLeft(), key, value));
        } else if (node.key.compareTo(key) < 0) {
            node.setRight(insert(node.getRight(), key, value));
        } else { // 相等的时候
            node.value = value;
        }
        return node;
    }

    //向树中插入新结点key-value
    public void insert(Key key, Value value) {
        root = insert(root, key, value);
    }

    // node结点为根的树(子树)中是否存在key
    private boolean contain(Node node, Key key) {
        if (node == null) {
            return false;
        } else if (node.key.compareTo(key) == 0) {
            return true;
        } else if (node.key.compareTo(key) > 0) {
            return contain(node.getLeft(), key);
        } else {
            return contain(node.getRight(), key);
        }
    }

    //树中是否存在key
    public boolean contain(Key key) {
        return contain(root, key);
    }

    //返回node结点为根的树(子树)中key对应的value值
    private Value search(Node node, Key key) {
        if (node == null) {
            return null;
        } else if (node.getKey().compareTo(key) == 0) {
            return node.getValue();
        } else if (node.getKey().compareTo(key) > 0) {
            return search(node.getLeft(), key);
        } else {
            return search(node.getRight(), key);
        }
    }
    //返回树中key对应的value值
    public Value search(Key key) {
        return search(root, key);
    }

    //先序遍历
    private void preOrder(Node node) {
        if (node == null) return;
        System.out.println(node.key);
        preOrder(node.getLeft());
        preOrder(node.getRight());
    }

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

    //中序遍历
    private void inOrder(Node node) {
        if (node == null) return;
        inOrder(node.getLeft());
        System.out.println(node.getKey());
        inOrder(node.getRight());
    }

    //中序遍历
    public void inOrder() {
        inOrder(root);
    }

    //后续遍历
    private void postOrder(Node node) {
        if (node == null) return;
        postOrder(node.getLeft());
        postOrder(node.getRight());
        System.out.println(node.getKey());
    }

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

    //层序遍历
    public void levelOrder() {
        if (root == null) return;
        java.util.LinkedList<Node> queue = new java.util.LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            Node node = queue.pop();
            System.out.println(node);
            if (node.getLeft() != null) {
                queue.add(node.getLeft());
            }
            if (node.getRight() != null) {
                queue.add(node.getRight());
            }
        }
    }

    //以node为根的树中,key最小的结点
    private Node minNode(Node node) {
        if (node.getLeft() == null) return node;

        return minNode(node.getLeft());
    }

    //树中key最小的结点
    public Node minNode() {
        return minNode(root);
    }

    //以node为根的树中,key最大的结点
    private Node maxNode(Node node) {
        if (node.getRight() == null) return node;

        return maxNode(node.getRight());
    }

    //树中key最大的结点
    public Node maxNode() {
        return maxNode(root);
    }

    //删除node为根的树(子树)中key最小的结点
    private Node removeMin(Node node) {
        if (node == null) return null;
        if (node.getLeft() == null) {
            Node rightNode = node.getRight();
            node.setRight(null);
            size--;
            return rightNode;
        }
        node.setLeft(removeMin(node.getLeft()));
        return node;
    }

    //删除树中key最小的结点
    public void removeMin() {
        root = removeMin(root);
    }

    //删除node为根的树(子树)中key最大的结点
    private Node removeMax(Node node) {
        if (node == null) return null;
        if (node.getRight() == null) {
            Node leftNode = node.getLeft();
            node.setLeft(null);
            size--;
            return leftNode;
        }
        node.setRight(removeMax(node.getRight()));
        return node;
    }

    //删除树中key最大的结点
    public void removeMax() {
        root = removeMax(root);
    }

    //删除一个结点
    private Node remove(Node node, Key key) {
        if (node == null) return null;
        if (key.compareTo(node.key) < 0) {//如果比根小,去左子树删除,然后返回根
            node.setLeft(remove(node.getLeft(), key));
            return node;
        } else if (key.compareTo(node.key) > 0) {//如果比根大,去右子树删除,然后返回根
            node.setRight(remove(node.getRight(), key));
            return node;
        } else { //key == node.key //如果与当点子树的根key相等
            if (node.getLeft() == null) { //判断当前子树的根是否有左子树
                Node rightNode = node.getRight();
                node.setRight(null);
                size--;
                return rightNode;
            } else if (node.getRight() == null) {//判断当前子树的根是否有右子树
                Node leftNode = node.getLeft();
                node.setLeft(null);
                size--;
                return leftNode;
            } else { // 如果当前子树既有左子树,又有右子树
                Node successor = minNode(node.getRight());//寻找后继结点,也就是右子树中最小的结点
                successor = new Node(successor.getKey(), successor.getValue());//新建一个与后继结点一模一样的,为了替换
                size++;//相当于添加一个结点
                successor.setRight(removeMin(node.getRight()));//删除后继结点,然后连上原来的右边
                successor.setLeft(node.getLeft());//连上原来的左边
                node.left = node.right = null;//原来的结点已经被替换了,可以不要了。
                size--;//相当于删除一个节点
                return successor;//当前新的子树根就是successor
            }
        }
    }

    public void remove(Key key) {
        root = remove(root, key);
    }

    public static void main(String[] args) {
        //建立一颗二叉搜索树
        BinarySearchTree<String, String> bst = new BinarySearchTree<>();

        //插入数据
        bst.insert("dog", "狗,一种动物");
        bst.insert("password", "密码");
        bst.insert("cat", "猫,一种动物");
        bst.insert("cup", "杯子");
        bst.insert("tom", "汤姆,《猫和老鼠》中的猫");
        bst.insert("jerry", "杰瑞,《猫和老鼠》中的老鼠");
        bst.insert("a", "26个英文字母中的第一个");

        //search()
        System.out.println(bst.search("a"));//26个英文字母中的第一个
        System.out.println(bst.search("dog"));//狗,一种动物
        System.out.println(bst.search("ttttt"));//null

        //contain()
        System.out.println(bst.contain("cup"));//true
        System.out.println(bst.contain("tom"));//true
        System.out.println(bst.contain("tttttt"));//false

        //maxNode()
        System.out.println(bst.maxNode());//Node{key=tom, value=汤姆,《猫和老鼠》中的猫}

        //minNode()
        System.out.println(bst.minNode());//Node{key=a, value=26个英文字母中的第一个}

        //removeMax()
        bst.removeMax();
        System.out.println(bst.maxNode());//Node{key=password, value=密码}

        //removeMin()
        bst.removeMin();
        System.out.println(bst.minNode());//Node{key=cat, value=猫,一种动物}

        //size()
        System.out.println(bst.size());//5

        //levelOrder()
        bst.levelOrder();

        //remove();
        System.out.println("--------------");
        bst.remove("password");
        bst.preOrder();
    }
}

  

时间: 2024-11-06 03:54:03

二叉搜索树(Java实现)的相关文章

二叉搜索树JAVA实现

引入: 二叉搜索树是这样的一种二叉树: (1)每个元素都有一个关键值,并且没有任意两个元素有相同的关键值 (2)根节点的左子树中任意元素的关键值小于根节点的关键值. (3)根节点的右子树中任意元素的关键值大于根节点的关键值. (4)根节点的左右子树也是二叉搜索树. 我们这里就用程序来实现这样一颗二叉搜索树. 分析: 从定义看出,二叉搜索树是一种特殊的二叉树,它给每个元素加上了序的概念,但又不同于最大最小堆,它总是 左<根<右的.我们分别看常用的几个操作. 查找: 关键值查找很简单,就是从根元素

Java数据结构之二叉搜索树

Java数据结构之二叉搜索树 1.二叉搜索树组成 二叉搜索树又称为二叉排序树,它或者是一颗空树,或者是一颗具有如下特性的非空二叉树,需要满足一下三个条件: (1)若它的左子树非空,则左子树上所有结点的关键字均小于根结点的关键字: (2)若它的右子树非空,则右子树上所有结点的关键字均大于(可以等于)根结点的关键字. (3)左子树右子树本身又各是一颗二叉搜索树 在算法描述中,均以结点值的比较来代表其关键字的比较,因为若结点的值为类类型时,该类必须实现系统提供的java.lang.comparable

平衡二叉搜索树(AVL树)的原理及实现源代码(有图文详解和C++、Java实现代码)

一.AVL树(平衡二叉搜索树)是什么? AVL树是根据它的发明者G.M. Adelson-Velsky和E.M. Landis命名的.AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树. 2.带有平衡条件:每个非叶子结点的左右子树的高度之差的绝对值(平衡因子)最多为1. 例如: 5             5 / \            /  \ 2   6         2   6 / \    \         / \ 1  4   7       1  4

二叉搜索树的Java实现

为了更加深入了解二叉搜索树,博主自己用Java写了个二叉搜索树,有兴趣的同学可以一起探讨探讨. 首先,二叉搜索树是啥?它有什么用呢? 二叉搜索树, 也称二叉排序树,它的每个节点的数据结构为1个父节点指针,1个左孩子指针,1个有孩子指针,还有就是自己的数据部分了,因为只有左右两孩子,所以才叫二叉树,在此基础上,该二叉树还满足另外一个条件:每个结点的左孩子都不大于该结点&&每个结点的右孩子都大于该结点.这样,我们队这棵树进行中序遍历,就能把key从小到大排序了…… 那么问题来了,我都有线性表有

Java实现二叉搜索树的添加,前序、后序、中序及层序遍历,求树的节点数,求树的最大值、最小值,查找等操作

什么也不说了,直接上代码. 首先是节点类,大家都懂得 /** * 二叉树的节点类 * * @author HeYufan * * @param <T> */ class Node<T extends Comparable<? super T>> { /** * 节点储存的值 */ private T data; /** * 左子节点 */ private Node<T> leftNode; /** * 右子节点 */ private Node<T>

二叉树、二叉搜索树、AVL树的java实现

数据结构一直都是断断续续的看,总是觉得理解的不够深入,特别是对树的理解,一直都很浅显,今儿又看了一遍,来做个总结吧. 首先,树中的一些概念: 1.树的节点包含一个数据元素,以及若干指向其子树的分支.节点拥有的子树的数量称为节点的度.节点的最大层次称为树的深度或高度. 2.二叉树是一种树形结构,其特点是每个节点至多有两棵子树,且子树有左右之分,次序不能随意颠倒. 3.满二叉树:一棵深度为k且有2^k - 1个节点的二叉树,称之为满二叉树. 4.完全二叉树:对一个深度为k,节点个数为n的二叉树,当且

剑指Offer面试题24(Java版):二叉搜索树的后序遍历序列

题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true,否则返回false.假设输入的数组的任意两个数字都互不相同. 例如输入数组{5,7,6,9,11,10,8}则返回true,因为这个整数序列是下图二叉树的后序遍历的结果.如果输入的数组是{7,4,6,5},由于没有哪颗二叉搜索树的后续遍历的结果是这个序列,因此返回false. 在后序遍历得到的序列中,最后一个数字是树的根节点的值.数组中前面的数字可以分为两部分:第一部分是左子树结点的值,它们都比根节点的值

【LeetCode-面试算法经典-Java实现】【096-Unique Binary Search Trees(唯一二叉搜索树)】

[096-Unique Binary Search Trees(唯一二叉搜索树)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given n, how many structurally unique BST's (binary search trees) that store values 1-n? For example, Given n = 3, there are a total of 5 unique BST's. 1 3 3 2 1 \ / / /

【LeetCode-面试算法经典-Java实现】【098-Validate Binary Search Tree(验证二叉搜索树)】

[098-Validate Binary Search Tree(验证二叉搜索树)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys le