二叉查找树代码实现 java

2019.4.18更新

递归求深度

//递归求深度
	public int getDepth(){
		return getDepth(root);
	}
	public int getDepth(TreeNode node){
		if(node == null){
			return -1;
		}
		int leftDepth = getDepth(node.leftChild);
		int rightDepth = getDepth(node.rightChild);
		return leftDepth > rightDepth ? leftDepth + 1: rightDepth + 1;
	}

remove方法

    //删除节点
    public boolean remove(char c){
        if(contains(c)){
            root = remove(root, c);//通过函数重载来进行递归
            return true;
        }
        return false;
    }
    private TreeNode remove(TreeNode node, char c){
        //先进行比较找到该节点的位置
        int cmp = c - node.data;
        if(cmp < 0){
            node.leftChild = remove(node.leftChild, c);
        }else if(cmp > 0){
            node.rightChild = remove(node.rightChild, c);
        }else{
            if(node.leftChild == null && node.rightChild == null){          //没有子树直接删除该节点
                node = null;
            }else if(node.leftChild != null && node.rightChild != null){    //有两个子树的情况
                //找到右子树的最小节点
                TreeNode minOfRight = min(node.rightChild);
                //将该节点的右子树上的值赋值给该节点
                node.data = minOfRight.data;
                //继续通过递归调用删除这个右子树节点,因为上一步赋值过去就相当于把原先节点删除了,这时有两个右子树节点,所以得删除下面一个
                node.rightChild = remove(node.rightChild, minOfRight.data);
                //找到左子树的最大节点
                /*TreeNode maxOfLeft = max(node.leftChild);
                node.data = maxOfLeft.data;
                node.leftChild = remove(node.leftChild, maxOfLeft.data);*/
            }else{
                node = node.rightChild != null?node.leftChild:node.rightChild;

            }

        }
        return node;
    }

建树方法:用递归实现

//建树,上面的方法都是在树上操作的,建树时还没有树这个数据结构。所以应该是static方法
    //参数类型是给两个字符串,返回类型是二叉查找树
    public static BinarySearchTree buildTree(String preOrder, String inOrder){
        //首先是数据验证,这里太麻烦,假定给定的两个字符串格式正确

        //把字符串转换成字符数组
        char[] preArr = preOrder.toCharArray();
        char[] inArr = inOrder.toCharArray();

        //构建二叉查找树和根节点
        BinarySearchTree tree = new BinarySearchTree();
        tree.root = build(preArr, inArr);       //创建节点操作
        tree.size = preArr.size();//添加长度
        return tree;
        //tree.root = new TreeNode(preArr[0]);        //根节点是先序遍历第一个元素

        //递归构建左子树
        /*int index = 0;
        while(inArr[index] != preArr[0]){
            index ++;
        }
        char[] preOfLeft = Arrays.copyOfRange(preArr, 1, index+1);      //// 包左不包右 把一棵树复制到另一棵树中去
        char[] preOfRight = Arrays.copyOfRange(preArr, index + 1, preArr.length);
        char[] inOfLeft = Arrays.copyOfRange(inArr, 0, index);
        char[] inOfRight = Arrays.copyOfRange(inArr, index, inArr.length);*/

    }
    private static TreeNode build(char[] preArr, char[] inArr){
        if(preArr == null || preArr.length == 0){   //如果先序遍历字符串数组是空的,返回null
            return null;
        }
        TreeNode node = new TreeNode(preArr[0]);        //创建根节点
        int index = 0;
        while (inArr[index] != preArr[0]){              //找到根节点在中序遍历中的位置
            index ++;
        }
        char[] preOfLeft = Arrays.copyOfRange(preArr, 1, index + 1); // 包左不包右  创建先序遍历的左子树的字符数组
        char[] preOfRight = Arrays.copyOfRange(preArr, index + 1, preArr.length);       //创建先序遍历的右子树的字符数组
        char[] inOfLeft = Arrays.copyOfRange(inArr, 0, index);                          //创建中序遍历的左子树的字符数组
        char[] inOfRight = Arrays.copyOfRange(inArr, index + 1, inArr.length);          //创建中序遍历的右子树的字符数组
        // 递归构建左子树
        node.leftChild = build(preOfLeft, inOfLeft);
        // 递归构建右子树
        node.rightChild = build(preOfRight, inOfRight);
        return node;
    }

package com.wangdao.tree;

import com.cskaoyan.exception.EmptyTreeException;

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

/**
 * @author Yuechao Yang
 * @version 2019-04-17-16:25
 *
 */
public class BinarySearchTree {
    //fields
    private TreeNode root;
    private int size;
    //methods
    public void add(char ch){
        //递归实现
        //root = add(root, ch);
        //非递归实现 用循环去做
        if(root == null){
            root = new TreeNode(ch);
            size++;
            return;
        }
        TreeNode node = root;
        while (node!= null){
            int cmp = ch - node.data;       //先进行比较大小
            if(cmp < 0){                    //如果小于node
                if(node.rightChild == null){    //如果node没有左子树,创建一个
                    node.leftChild = new TreeNode(ch);
                    size++;
                    return;
                }
                node = node.leftChild;          //移到左子树
            }else if(cmp > 0){              //如果大于node
                if(node.rightChild == null){    //如果node没有右子树,创建一个
                    node.rightChild = new TreeNode(ch);
                    size++;                     //长度加一
                    return;
                }
                node = node.rightChild;     //移到右子树
            }else{                          //相等直接返回
                return;
            }

        }

    }
    //这里是add方法的重载,递归实现添加        实现重载的方法应该是私有的,无参是public,有参是私有,两个结合才能实现递归
    private TreeNode add(TreeNode node, char ch){
        if(node == null){
            node = new TreeNode(ch);        //新建节点不用输入这么多实参,只用ch就可以了。默认左右子树是null
            size++;                         //这里才是新创建一个节点,下面递归调用没有创建节点
            return node;
        }
        int cmp = ch - node.data;           //这里用减号,是比较Unicode码值的大小
        if(cmp < 0){
            node.leftChild = add(node.leftChild, ch);
        }else if(cmp > 0){
            node.rightChild = add(node.rightChild, ch);
        }
        return node;        //这里的node返回的是上一层的调用者,要记住递归的调用是很多层的,不是直接传递给无参方法中的root
                            //传递给root是root的下一层,这里的node说不定是很多层的
    }

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

    //树的元素个数
    public int size(){
        return size;
    }

    //访问节点
    public void visit(TreeNode node){
        System.out.println("data = " + node.data);
    }

    public void preOrderRecursion(){
        //先序遍历(递归)
        //preOrderRecursion(root);
        //先序遍历(用栈实现)栈是线程安全的,效率不高
        Stack<TreeNode> stack = new Stack<>();
        if(root == null){
            return;
        }
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode node = stack.pop();
            if(node.rightChild != null){
                stack.push(node.rightChild);
            }
            if(node.leftChild != null){
                stack.push(node.leftChild);
            }
            visit(node);
        }
        System.out.println();
    }
    private void preOrderRecursion(TreeNode node){
        if(node == null){
            return;
        }
        visit(node);
        preOrderRecursion(node.leftChild);
        preOrderRecursion(node.rightChild);
    }



    //中序遍历(递归)
    public void inOrderRecursion(){
        inOrderRecursion(root);
        System.out.println();
    }
    private void inOrderRecursion(TreeNode node){
        if(node == null){
            return;
        }
        inOrderRecursion(node.leftChild);
        visit(node);
        inOrderRecursion(node.rightChild);
    }
    //后序遍历(递归)
    public void postOrderRecursion(){
        postOrderRecursion(root);
        System.out.println();
    }
    private void postOrderRecursion(TreeNode node){
        if(node == null){
            return;
        }
        postOrderRecursion(node.leftChild);
        postOrderRecursion(node.rightChild);
        visit(node);
    }

    //层次遍历
    //借助队列实现
    public void levelOrder(){
        if(root == null){
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        TreeNode node;
        while((node = queue.poll()) != null){
            if(node.leftChild != null){
                queue.offer(node.leftChild);
            }
            if(node.rightChild != null){
                queue.offer(node.rightChild);
            }
            visit(node);
        }
    }

    //获取最小值
    public char min(){
        //非递归
        /*if(root == null){
            throw new EmptyTreeException();
        }
        TreeNode node = root;
        while(node.rightChild != null){
            node = node.leftChild;
        }
        return node.data;*/
        //递归
        if(root == null){
            throw new EmptyTreeException();
        }
        return min(root).data;
    }
    private TreeNode min(TreeNode node){
        if(node.leftChild != null){
            return min(node.leftChild);
        }
        return node;
    }

    //获取最大值
    public char max(){
        //非递归遍历
        /*if(root == null){
            throw new EmptyTreeException();
        }
        TreeNode node = root;
        while(node.rightChild != null){
            node = node.rightChild;
        }
        return node.data;*/
        //递归遍历
        if(root == null){
            throw new EmptyTreeException();
        }
        return max(root).data;
    }
    private TreeNode max(TreeNode node){
        if(node.rightChild != null){
           return max(node.rightChild);
        }
        return node;
    }

    //检查是否包含
    public boolean contains(char c){
        //递归方法
        //return contains(root, c);
        //非递归方法
        TreeNode node = root;
        while(node != null){
            int cmp = c - node.data;
            if(cmp < 0){
                node = node.leftChild;
            }else if(cmp > 0){
                node = node.rightChild;
            }else {
                return true;
            }
        }
        return false;
    }

    private boolean contains(TreeNode node, char c) {
        if(node == null){
            return false;
        }
        int cmp = c - node.data;
        if(cmp < 0){
            return contains(node.leftChild, c);
        }else if(cmp > 0){
            return contains(node.rightChild, c);
        }
        return true;
    }

    //节点
    private static class TreeNode{
        //fields
        private TreeNode leftChild;
        private char data;
        private TreeNode rightChild;
        //constructors
        public TreeNode() {
        }

        public TreeNode(char ch) {
            this.data = ch;
        }

        /*public TreeNode(TreeNode leftChild, char ch, TreeNode rightChild) {       //可以不用声明
            this.leftChild = leftChild;
            this.data = ch;
            this.rightChild = rightChild;
        }*/
    }
}

自定义异常类如下:

package com.wangdao.exception;

/**
 * @author Yuechao Yang
 * @version 2019-04-17-23:23
 */
public class EmptyTreeException extends RuntimeException {
    public EmptyTreeException() {
    }

    public EmptyTreeException(String message) {
        super(message);
    }
}

其中栈用来非递归实现先序遍历的思路下图所示:
二叉查找树代码实现 java
队列非递归实现层次遍历思路如下图所示:
二叉查找树代码实现 java
还有remove方法以后有时间补上