用递归实现二叉搜索树

PS:这里推荐一个看生成二叉树的工具网站:
点我就可以

定义:

二叉搜索树的意思就是 左孩子 < 父节点 < 右孩子

可以打开这个网址一边看动画,一边看代码,方便理解。
那,话不多说,下面进入正题,下面利用递归的方式实现泛型二叉搜索树。支持任意可比较的数据类型。

1.首先先编写一个二叉树结点。

/**
 * 二叉搜索树
 * 
 * 1.支持任意可比较的数据类型
 * 2.也可以通过重写object类的
 *   compareTo方法实现
 *   
 * @author 137***81
 *
 * @param <T>
 */
public class Node <T extends Comparable<T>>{
	T data;
	Node<T> leftChild;
	Node<T> rightChild;
	
	public Node(T data) {
		this.data = data;
	}
	
	public Node(T data , Node<T> leftChild, Node<T> rightChild) {
		this.data = data;
		this.leftChild = leftChild;
		this.rightChild = rightChild;
	}
}

2.在编写一个二叉搜索树的类

public class SearchTree<T extends Comparable<T>>{
	
	//根节点
	Node<T> root;
	
	/**
	 * 向用户暴露插入方法
	 * @param data 插入的数据
	 * @throws Exception 
	 */
	public void insert(T data) throws Exception {
		if(root == null) root = new Node<T>(data,null,null);
		else addElement(new Node<T>(data) ,root);
	}
	
	/**
	 * 向用户暴露查询方法
	 * @param data 搜索的数据
	 * @return 没查到为null
	 * @throws Exception
	 */
	public Node<T> query(T data) throws Exception{
		if(root == null) throw new Exception("root is null");
		return query(data , root);
	}
	
	/**
	 * 向用户暴露删除方法
	 * @param data 要删除的数据
	 * @return 删除成功返回true,否则false
	 * @throws Exception
	 */
	public void delete(T data) throws Exception{
		if(root == null) throw new Exception("root is null");
		deleteNode(root,data);
	}
	
	/**
	 * 向用户暴露查找最小节点的方法
	 * @param node
	 * @return
	 */
	public Node<T> findMin() throws Exception{
		if(root == null) throw new Exception("root is null");
    	return findMin(root);
    }
	
	/**
	 * 判断是否是二叉搜索树
	 * @return
	 */
	public boolean isSearchTree() {
		return isSearchTree(root,null,null);
	}
	
	//私有化封装方法
	private Node<T> query(T data , Node<T> root) {
		if(root == null) return null;
		int compareResult = data.compareTo(root.data);
        if(compareResult > 0)
            return query(data, root.rightChild);
        else if(compareResult < 0)
            return query(data, root.leftChild);
        return root;
	}
	
	//私有化封装方法
    private Node<T> addElement(Node<T> node , Node<T> root) throws Exception {
    	if(root == null) return node;
        int compareResult = node.data.compareTo(root.data);
        if(compareResult > 0)
            root.rightChild = addElement(node, root.rightChild);
        else if(compareResult < 0)
            root.leftChild = addElement(node, root.leftChild);
        else throw new Exception("data is Exist!");
        return root;
    }
    
    //私有化封装方法
    private Node<T> deleteNode(Node<T> root, T key) {
        if (root == null) {
            return null;
        }
        int compareResult = key.compareTo(root.data);
        if (compareResult < 0) {
            // 待删除节点在左子树中
            root.leftChild = deleteNode(root.leftChild, key);
            return root;
        } else if (compareResult > 0) {
            // 待删除节点在右子树中
            root.rightChild = deleteNode(root.rightChild, key);
            return root;
        } else {
            if (root.leftChild == null) {
                // 返回右子树作为新的根
                return root.rightChild;
            } else if (root.rightChild == null) {
                // 返回左子树作为新的根
                return root.leftChild;
            } else {
                // 左右子树都存在,返回后继节点(右子树最左叶子)作为新的根
                Node<T> successor = min(root.rightChild);
                successor.rightChild = deleteMin(root.rightChild);
                successor.leftChild = root.leftChild;
                return successor;
            }
        }
    }
    
    /**
     * 返回最小节点
     * @param node
     * @return
     */
    private Node<T> min(Node<T> node) {
        if (node.leftChild == null) {
            return node;
        }
        return min(node.leftChild);
    }
    
    /**
     * 返回最小节点的右孩子
     * @param node
     * @return
     */
    private Node<T> deleteMin(Node<T> node) {
        if (node.leftChild == null) {
            return node.rightChild;
        }
        node.leftChild = deleteMin(node.leftChild);
        return node;
    }
    
    /**
     * 找到最小值
     * @param node 根节点
     * @return 返回最小的结点
     */
    public Node<T> findMin(Node<T> root){
    	if(root == null) return null;
    	else if(root.leftChild == null)
    		return root;
    	return findMin(root.leftChild);
    }
    
    //前序遍历
	public void preOrder(Node<T> root) {
	   if (root == null)
		    return;
       System.out.print(root.data + " ");
       preOrder(root.leftChild);
       preOrder(root.rightChild);
		
	}
	
	/**
	 * 二叉搜索的前序遍历就是 【升序】
	 * @param root
	 */
	public void midOrder(Node<T> root) {
	   if (root == null)
		    return;
	   midOrder(root.leftChild);
       System.out.print(root.data + " ");
       midOrder(root.rightChild);	
	}
	
	/**
	 * 判断是否是二叉搜索树
	 * @param root
	 * @param minNode
	 * @param maxNode
	 * @return
	 */
	private boolean isSearchTree(Node<T> root, Node<T> minNode,Node<T> maxNode) {
		if(root == null) return true;
		if((minNode!=null&&root.data.compareTo(minNode.data) <= 0)||
				(maxNode!=null&&root.data.compareTo(maxNode.data) >= 0)) {
			return false;
		}
		return isSearchTree(root.leftChild,null,root)&&isSearchTree(root.rightChild,root,null);
		
	}
}

3.接下来就是调用使用它了

public static void main(String[] args) throws Exception{
SearchTree<Integer> tree = new SearchTree<>();
			    tree.insert(33);
			    tree.insert(80);
			    tree.insert(20);
			    tree.insert(100);
			    tree.insert(49);
			    tree.insert(3);
			    //中序遍历
			    tree.midOrder(tree.root);
			    System.out.println();
			    //query
			    Node<Integer> node = tree.query(20);
			    if(node != null) {
			    	System.out.println("found one! value is:" + node.data);
			    }else {
			    	System.out.println("opps ! not found");
			    }
			    //findMin
			    Node<Integer> minNode = tree.findMin();
			    System.out.println("found one! minNode is:" + minNode.data);
			    //delete
			    tree.delete(80);
			    //验证一下是否删除成功
			    tree.midOrder(tree.root);
			    System.out.println();
			    System.out.println(tree.isSearchTree()?"true":"false");
	}

运行结果如下:

在这里插入图片描述

PS:纯属个人理解,希望指正!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值