自定义树(2):二分搜索树(Binary Search Tree)

版权声明:转载请注明出处: https://blog.csdn.net/qq_34774655/article/details/85321798

二分搜索树也是一种二叉树。

二分搜索树的遍历:

层序遍历图解:

删除任意元素图解:

代码实现:

package BST;

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

public class BinarySearchTree<E extends Comparable<E>> {
	private class Node{
		public E e;//数据域
		public Node left,right;//指向左孩子、右孩子
		/**
		 * 带参构造函数
		 * @param e
		 */
		public Node(E e) {
			this.e=e;
			left=null;
			right=null;
		}
	}
	private Node root;//根元素
	private int size;//元素个数
	/**
	 * 无参构造函数
	 */
	public BinarySearchTree() {
		root=null;
		size=0;
	}
	/**
	 * 获取元素个数
	 * @return
	 */
	public int size() {
		return size;
	}
	/**
	 * 判断二分搜索树是否为空
	 * @return
	 */
	public boolean isEmpty() {
		return size==0;
	}
	/**
	 * 向二分搜索树中添加新的元素e
	 * @param e
	 */
	public void add(E e) {
		root=add(root,e);//调用内部的自定义的add方法
	}
	/**
	 * 向以node为根的二分搜索树中插入元素e,递归算法
	 * 返回插入新节点后二分搜索树的根
	 * @param node
	 * @param e
	 * @return
	 */
	private Node add(Node node,E e) {
		if(node==null) {//基本问题
			node=new Node(e);
			size++;
		}
		
		if(e.compareTo(node.e)<0) {//更小的同一问题
			node.left=add(node.left,e);
		}else if(e.compareTo(node.e)>0) {//更小的同一问题
			node.right=add(node.right,e);
		}
		return node;
	}
	/**
	 * 看二分搜索树中是否包含元素e
	 * @param e
	 * @return
	 */
	public boolean contains(E e) {
		return contains(root,e);
	}
	/**
	 * 看以node为根的二分搜索树中是否包含元素e, 递归算法
	 * @param node
	 * @param e
	 * @return
	 */
	private boolean contains(Node node,E e) {
		if(node==null) {
			return false;
		}
		if(e.compareTo(node.e)==0) {
			return true;
		}else if(e.compareTo(node.e)<0) {
			return contains(node.left,e);
		}else {
			return contains(node.right ,e);
		}
		
	}
	/**
	 *  二分搜索树的前序遍历
	 */
	public void preOrder() {
		preOrder(root);
	}
	/**
	 * 前序遍历以node为根的二分搜索树, 递归算法
	 * @param node
	 */
	private void preOrder(Node node) {
		if(node==null) {
			return;
		}
		System.out.println(node.e);
		
		preOrder(node.left);
		preOrder(node.right);
	}
	/**
	 *  二分搜索树的中序遍历
	 */
	public void inOrder() {
		inOrder(root);
	}
	/**
	 * 中序遍历以node为根的二分搜索树, 递归算法
	 * @param node
	 */
	private void inOrder(Node node) {
		if(node==null) {
			return;
		}
		inOrder(node.left);
		System.out.println(node.e);
		inOrder(node.right);
	}
	/**
	 * 二分搜索树的后序遍历
	 */
	public void postOrder() {
		postOrder(root);
	}
	/**
	 * 后序遍历以node为根的二分搜索树, 递归算法
	 * @param node
	 */
	private void postOrder(Node node) {
		if(node==null) {
			return;
		}
		postOrder(node.left);
		postOrder(node.right);
		System.out.println(node.e);
	}
	/**
	 * 二分搜索树的层序遍历
	 */
	public void levelOrder() {
		if(root==null) {
			return;
		}
		//使用队列
		Queue<Node> q=new LinkedList<Node>();
		q.add(root);//添加到队尾
		
		while(!q.isEmpty()) {
			Node cur=q.remove();//移除队头元素
			System.out.println(cur.e);
			
			if(cur.left!=null) {
				q.add(cur.left);
			}
			if(cur.right!=null) {
				q.add(cur.right);
			}
		}
		
	}
	/**
	 * 获取二分搜索树的最小元素
	 * @return
	 */
	public E minimum() {
		if(size == 0) {
            throw new IllegalArgumentException("二分搜索树为空");
		}
		
		
		return minimum(root).e;
	}
	/**
	 * 返回以node为根的二分搜索树的最小值所在的节点
	 *递归算法
	 * @param node
	 * @return
	 */
	private Node minimum(Node node) {
		
		if(node.left==null) {
			return node;
		}
		return minimum(node.left);
	}
	/**
	 * 获取二分搜索树的最大元素
	 * @return
	 */
    public E maximum(){
        if(size == 0)
            throw new IllegalArgumentException("BST is empty");

        return maximum(root).e;
    }

    /**
     *    返回以node为根的二分搜索树的最大值所在的节点
      *  递归算法
     * @param node
     * @return
     */
    private Node maximum(Node node){
        if( node.right == null )
            return node;

        return maximum(node.right);
    }
	/**
	 * 从二分搜索树中删除最小值所在节点, 返回最小值
	 * @return
	 */
    public E removeMin() {
    	E min=minimum();
    	root=removeMin(root);//删除的内部实现
    	return min;
    }
    /**
      *  删除掉以node为根的二分搜索树中的最小节点
     *返回删除节点后新的二分搜索树的根
     * @param node
     * @return
     */
    private Node removeMin(Node node) {
    	if(node.left==null) {
    		Node rightNode=node.right;
    		node.right=null;
    		size--;
    		return rightNode;
    	}
    	node.left=removeMin(node.left);
    	return node;
    
    }
    /**
     * 从二分搜索树中删除最大值所在节点
     * @return
     */
    public E removeMax() {
    	E max=maximum();
    	root=removeMax(root);
    	return max;
    	
    }
    /**
      * 删除掉以node为根的二分搜索树中的最大节点
    *返回删除节点后新的二分搜索树的根
     * @param node
     * @return
     */
	private Node removeMax(Node node) {
		if(node.right==null) {
			Node leftNode=node.left;
			node=null;
			return leftNode;
		}
		node.right=removeMax(node.right);
		return node;
	}
    /**
     * 从二分搜索树中删除元素为e的节点
     * @param e
     * @return
     */
    public void remove(E e) {
    	root=remove(root,e);
    }
    /**
     * 删除掉以node为根的二分搜索树中值为e的节点, 递归算法
    *返回删除节点后新的二分搜索树的根
     * @param node
     * @param e
     * @return
     */
    private Node remove(Node node,E e) {
    	if(node==null) {
    		return null;
    	}
    	
    	if(e.compareTo(node.e)<0) {
    		node.left=remove(node.left,e);
    		return node;
    		
    	}else if(e.compareTo(node.e)>0) {
    		node.right=remove(node.right,e);
    		return node;
    	}else {// e.compareTo(node.e) == 0
    		
    		
    		// 待删除节点左子树为空的情况
    		if(node.left==null) {
    			Node rightNode=node.right;
    			node.right=null;
    			size--;
    			return rightNode;
    			
    		}
    		
    		 // 待删除节点右子树为空的情况
    		if(node.right==null) {
    			Node leftNode=node.left;
    			node.left=null;
    			size--;
    			return leftNode;
    		}
    		
    		// 待删除节点左右子树均不为空的情况
    		
    		
    		// 找到比待删除节点大的最小节点, 即待删除节点右子树的最小节点
            // 用这个节点顶替待删除节点的位置
    		//(这只是其中一种解决办法,也可以找到比待删除节点小的最大节点,相应的应去左子树找)
    		Node successor=minimum(node.right);
    		successor.right=removeMin(node.right);
    		successor.left=node.left;
    		node.left=node.right=null;
    		return successor;
    	}
    }
    
    
	
}

测试:

package BST;

import java.util.ArrayList;
import java.util.Random;

public class Test {

	public static void main(String[] args) {
		BinarySearchTree<Integer> bst=new BinarySearchTree<Integer>();
		//测试添加
		int[] nums = {5, 3, 6, 8, 4, 2};
        for(int num: nums) {
            bst.add(num);
        }
        
        //测试前序遍历
        bst.preOrder();
        System.out.println();
        //测试中序遍历
        bst.inOrder();//对二分搜索树,中序遍历相当于排序
        System.out.println();
        //测试后序遍历
        bst.postOrder();
        System.out.println();
        //测试层序遍历,并删除指定元素
        bst.levelOrder();
    
        System.out.println();
        
        //测试获取最大值
        System.out.println(bst.maximum());
        
      
        
        //测试删除最小值
        Random random=new Random();
        for(int i=0;i<100;i++) {
        	bst.add(random.nextInt(10000));
        }
        ArrayList<Integer> arrNums=new ArrayList<Integer>();
        while(!bst.isEmpty()) {
        	arrNums.add(bst.removeMin());
        }
        System.out.println(arrNums);
        
        
	}

}

控制台输出:

5
3
2
4
6
8

2
3
4
5
6
8

2
4
3
8
6
5

5
3
6
2
4
8

8
[2, 3, 4, 5, 6, 8, 108, 112, 287, 305, 321, 746, 764, 800, 911, 975, 1019, 1242, 1317, 1385, 1392, 1500, 1501, 1656, 1668, 1677, 1741, 1825, 1852, 2144, 2202, 2223, 2429, 2573, 2843, 2883, 2903, 3057, 3117, 3212, 3518, 3679, 3798, 3821, 3844, 3905, 3961, 3966, 4077, 4361, 4637, 4818, 5079, 5192, 5217, 5225, 5283, 5478, 5513, 5547, 5566, 5604, 5643, 5667, 5751, 5909, 5956, 6123, 6321, 6344, 6383, 6556, 6589, 6803, 6845, 6996, 7086, 7136, 7218, 7227, 7243, 7558, 7688, 7742, 7912, 7949, 8042, 8158, 8238, 8360, 8426, 8486, 8586, 8656, 8947, 8955, 9414, 9458, 9540, 9654, 9676, 9678, 9737, 9817, 9860, 9953]

猜你喜欢

转载自blog.csdn.net/qq_34774655/article/details/85321798