Day02——二叉搜索树BST

1、树的整体介绍

 

 2、二叉搜索树

1)定义一个二叉搜索树

//自定义一棵二叉搜索树,这棵树里面的内容是可以比较的泛型
public class BST <E extends Comparable<E>> {
	
	//1、定义一个节点
	private class Node{
		E e;
		Node left;
		Node right;
		
		//写一个构造函数,构造一个节点
		public Node(E e) {
			this.e = e;
			this.left = null;
			this.right = null;
		}
	}
	
	//2.定义二叉搜索树的属性
	private Node root;
	private int size;
	
	//3.提供一个获取二叉树长度的方法
	public int size() {
		return size;
	}
}

2)向BST里面添加元素

//自定义一棵二叉搜索树,这棵树里面的内容是可以比较的泛型
public class BST <E extends Comparable<E>> {

    //1、定义一个节点
    private class Node{
        E e;
        Node left;
        Node right;

        //写一个构造函数,构造一个节点
        public Node(E e) {
            this.e = e;
            this.left = null;
            this.right = null;
        }
    }

    //2.定义二叉搜索树的属性
    private Node root;
    private int size;

    //3.提供一个获取二叉树长度的方法
    public int size() {
        return size;
    }

    //4.写一个添加节点的方法
    public void addEle(E e) {
        if(root==null) {
            root = new Node(e);
        }else {
            addEle(root,e);
        }
    }
    /**
     * 将元素E添加到以node为根节点的树上
     * @param node
     * @param e
     */
    private void addEle(Node node , E e) {
        if(node.left==null && e.compareTo(node.e)<0) {
            node.left = new Node(e);
            size++;
            return;
        }
        if(node.right==null && e.compareTo(node.e)>0) {
            node.right = new Node(e);
            size++;
            return;
        }
        if(e.compareTo(node.e)<0) {
            addEle(node.left,e);
        }
        if (e.compareTo(node.e)>0) {
            addEle(node.right,e);
        }
    }

}
public class BSTTest {
    public static void main(String[] args) {
        BST bst = new BST();
        bst.addEle(7);
        bst.addEle(3);
        bst.addEle(10);
    }
}

上述方法的升级版

//4.写一个添加节点的方法
	public void addEle(E e) {
		root = addEle(root, e);
	}
	/**
	 * 将元素E添加到以node为根节点的树上
	 * return 返回的就是新插入节点后新子树的根节点
	 * @param node
	 * @param e
	 */
	private Node addEle(Node node , E e) {
		if(node == null) {
			size++;
			return new Node(e);
		}
		if(e.compareTo(node.e)<0) {
			node.left = addEle(node, e);
		}
		if(e.compareTo(node.e)>0) {
			node.right = addEle(node, e);
		}
	return node;
	}

3)查找一个值所在二叉树中的节点

public Node search(E e){
		return search(root,e);
	}

	/**
	 * 在以node为根的树上去查找元素e所在的节点
	 * @param node
	 * @param e
	 * @return
	 */
	private Node search(Node node, E e) {

		if(node==null){
			return null;
		}

		if(e.compareTo(node.e)==0){
			return node;
		}else if(e.compareTo(node.e)<0){
			return search(node.left,e);
		}else{
			return search(node.right,e);
		}
	}

 4) 查找某个元素所在节点的父节点是谁

public Node searchParent(E e){
		return searchParent(root,e);
	}

	/**
	 * 从以node为根的树中查找元素e所在节点的父节点
	 * @param node
	 * @param e
	 * @return
	 */
	private Node searchParent(Node node, E e) {
		//递归的退出条件
		if(node==null){
			return null;
		}
		if((node!=null && e.compareTo(node.left.e)<0) || (node!=null && e.compareTo(node.right.e)>0)){
			return node;
		} else {
			if (node.left != null && e.compareTo(node.e) < 0) {
				return searchParent(node.left, e);
			} else if (node.right != null && e.compareTo(node.e) > 0) {
				return searchParent(node.right, e);
			}else{
				return null;
			}
		}
	}

5) 二叉收索树深度优先遍历

public void preOrder(){
		preOrder(root);
	}

	/**
	 * 从根节点开始前序遍历
	 * @param node
	 */
	private void preOrder(Node node) {
		if(node == null){
			return;
		}
		System.out.println(node.e);
		preOrder(node.left);
		preOrder(node.right);
	}

	public void midOrder(){
		midOrder(root);
	}

	/**
	 * 中序遍历
	 * @param node
	 */
	private void midOrder(Node node) {
		if(node == null){
			return;
		}
		preOrder(node.left);
		System.out.println(node.e);
		preOrder(node.right);
	}

	public void lastOrder(){
		midOrder(root);
	}

	/**
	 * 后序遍历
	 * @param node
	 */
	private void lastOrder(Node node) {
		if(node == null){
			return;
		}
		preOrder(node.left);
		preOrder(node.right);
		System.out.println(node.e);
	}

6)二叉收索树非递归前序遍历,中序遍历,后序遍历

/**
	 * 非递归的前序遍历
	 */
	public void preOrderNR(){
		if(root==null){
			return;
		}
		Stack <Node> stack = new Stack();
		stack.push(root);
		while(!stack.isEmpty()){
			Node current = stack.pop();
			System.out.println(current.e);
			if(current.right!=null){
				stack.push(current.right);
			}
			if(current.left!=null){
				stack.push(current.left);
			}
		}
	}

7)二叉搜索树的广度优先遍历

/**
	 * 二叉树的广度遍历
	 */
	public void widthSearch(){
		if(root == null){
			return;
		}
		Queue <Node> queue = new LinkedList<>();
		queue.add(root);
		while(!queue.isEmpty()){
			Node current = queue.remove();
			System.out.println(current.e);
			if(current.left!=null){
				queue.add(current.left);
			}
			if(current.right!=null){
				queue.add(current.right);
			}
		}
	}

8)二叉搜索树的删除 

 

/**
	 * 删除节点:有三种情况
	 */
	public void delNode(E e){

		if(root == null) return;
		Node target = search(e);
		if (target == null) return;

		Node parent = searchParent(e);

		if(target.right==null && target.left==null){

			//这种情况说明是叶子节点,直接删除就好
			if(parent.left!=null && e.compareTo(parent.left.e)==0){
				parent.left = null;
				size--;
			}else if(parent.right!=null && e.compareTo(parent.right.e)==0){
				parent.right = null;
				size--;
			}

		}else if(target.right!=null && target.left!=null){
			//这种说明是有两个子树
            //找出目标节点右边节点的最小值,这里的意思就是说在目标结点的右子树上去找min,右子树的min肯定在子树的左边。
			Node minNode = minNode(target.right);
			delNode(minNode.e);
			//此处通过赋值的方式来达到节点交换的目的
			target.e = minNode.e;
		}else{
			//只有一个子树
			//只有左子树
			if(target.left!=null){

				if(e.compareTo(parent.left.e)==0){
					parent.left = target.left;
					size--;
				}else{
					parent.right = target.left;
					size--;
				}
			//只有右子树
			}else if(target.right!=null){
				if(e.compareTo(parent.right.e)==0){

					if(target.right!=null){
						parent.right = target.right;
						size--;
					}else{
						parent.right = target.left;
						size--;
					}

				}
			}

		}

	}

	private Node minNode(Node node) {
		if(node.left==null)
			return null;
		return minNode(node.left):
	}

删除的改进

/**
	 * 从以node为根的树中删除元素为e的节点,并将删除e节点后生成的新的子树的根返回
	 */
	public Node removeNode(Node node,E e){
		//递归的退出条件
		if(node==null){
			return null;
		}
		//判断去到左子树还是右子树上进行删除
		//去到左子树上删除
		if(e.compareTo(node.left.e)<0){
			node.left = removeNode(node.left, e);
			size--;
			return node;
		}
		//去到右子树山面删除
		else if(e.compareTo(node.right.e)>0){
			node.right= removeNode(node.right, e);
			size--;
			return node;
		}
		else{
			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 minNode = minNode(node.right);
			minNode.right = removeNode(node.right, minNode.e);
			minNode.left = node.left;
			node.left = node.right = null;
			return minNode;
		}
	}

    private Node minNode(Node node) {
		if(node.left==null)
			return null;
		return minNode(node.left);
	}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值