二分搜索树

本文详细介绍了二分搜索树的概念、基础结构、插入、查询、遍历及删除操作。二分搜索树是一种动态数据结构,具有高效查询和操作的特性。通过前序、中序和后序遍历,可以实现数据的排序。删除操作包括删除最大、最小元素和任意元素,其中删除任意元素时需要考虑节点的三种不同情况。此外,还提及了二分搜索树在层次遍历、支持重复元素等方面的应用。
摘要由CSDN通过智能技术生成

二分搜索树

1、为什么要有树结构

树结构本身是一种天然的组织结构;高效

二分搜索树、平衡二叉树:AVL and 红黑树 、堆、并查集、线段树、Trie

2、二分搜索树基础

二叉树:和链表一样,动态数据结构

class Node{

​ E e;

​ Node left,right;

}

二叉树具有唯一根节点,每个节点最多有两个孩子。

二叉树具有天然递归结构:每个节点的左子树和右子树也是二叉树。

二叉树不一定是“满”的,一个节点也是二叉树,空也是二叉树。

二分搜索树:是二叉树且每个节点的值大于其左子树的所有节点的值并小于其右子树所有节点的值。

二分搜索树支持的类型必须具有可比较性

public class BST<E extends Comparable<E>> {
	private class Node{
		public E e;
		public Node left,right;
		public Node(E e) {
			this.e=e;
			left=null;
			right=null;
		}
	}
	private Node root;
	private int size;
	public BST() {
		root=null;
		size=0;
	}
}

3、向二分搜索树添加元素

    //add:找位置,放进去。在null的位置添加新的结点。
	public void add(E e) {
		if(root==null) {
			root=new Node(e);
			size++;
		}
		else
			add(root,e);
	}
	private void add(Node node,E e) {
		if(e.equals(node.e))
			return;
		else if(e.compareTo(node.e)<0&&node.left==null) {
			node.left=new Node(e);
			size++;
			return;
		}
		else if(e.compareTo(node.e)>0&&node.right==null) {
			node.right=new Node(e);
			size++;
			return;
		}
		if(e.compareTo(node.e)<0)
			add(node.left,e);
		if(e.compareTo(node.e)>0) {
			add(node.right,e);
		}
	}

改进添加方法

	// 向二分搜索树中添加新的元素e
    public void add(E e){
        root = add(root, e);
    }
    // 向以node为根的二分搜索树中插入元素e,递归算法
    // 返回插入新节点后二分搜索树的根
    private Node add(Node node, E e){
        if(node == null){
            size ++;
            return new Node(e);
        }
        if(e.compareTo(node.e) < 0)
            node.left = add(node.left, e);//node.left为空,即为将插入新元素的位置
        else if(e.compareTo(node.e) > 0)
            node.right = add(node.right, e);
        return node;
    }

4、查询

public boolean contains(E e) {
		return contains(root, e);
}
private boolean contains(Node node,E e) {
		if(node==null)
			return false;
		if(e.compareTo(node.e)==0)
			return true;
		if(e.compareTo(root.e)<0)
			return contains(node.left,e);
		else
			return contains(node.right,e);
}

5、遍历

中序遍历是二分搜索树排序的结果。

	//前序遍历
	public void preOrder() {
		preOrder(root);
	}
	private void preOrder(Node node) {
		if(node==null)
			return;
		System.out.println(node.e);
		preOrder(node.left);
		preOrder(node.right);
	}
	//中序和后序遍历同理

二分搜索树的前中后序遍历都是按节点–左子树–右子树来进行访问,每个节点都被访问三次,前中后序分别对应在第一、二、三次访问时进行操作。

6、前序遍历的非递归方法

使用栈,先右子树入栈后左子树入栈。

public void preOrderNR() {
		Stack<Node> stack=new Stack<>();
		stack.push(root);
		while(!stack.isEmpty()) {
			Node cur=stack.pop();
			System.out.println(cur.e);
			if(cur.right!=null) {
				stack.push(cur.right);
			}
			if(cur.left!=null) {
				stack.push(cur.left);
			}
		}
}

遗留问题:中序、后序遍历的非递归实现

7、层次遍历

使用队列,访问某个节点并依次将其左右孩子入队。

广度优先遍历的意义:更快的找到问题的解,常用于算法设计中–最短路径。

public void levelOrder() {
		if(root==null)
			return;
		Queue<Node> q=new LinkedList<>();
		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);
		}
}

8、删除

(1)删除最大、最小元素

	//寻找最小元素
	public E minimum() {
		if(size==0) {
			throw new IllegalArgumentException("BST is empty");
		}
		Node minNode=minimum(root);
		return minNode.e;
	}
	public Node minimum(Node node) {
		if(node.left==null)//从根节点开始一直向左查找,某个节点的左子树为空,则就是最小的节点
			return node;
		return minimum(node.left);
	}
	//删除最小元素
	public E removeMin() {
		E ret=minimum();
		root=removeMin(root);
		return ret;
	}
	private Node removeMin(Node node) {
		if(node.left==null) {
			Node rightNode=node.right;
			size--;
			node.right=null;
			return rightNode;
		}
		node.left=removeMin(node.left);
		return node;
	}

(2)删除任意元素

public Node remove(Node node,E e) {
		if(node==null) {
			return null;
		}
		if(e.compareTo(root.e)<0) {
			node.left=remove(node.left,e);
			return node;
		}
		else if(e.compareTo(root.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;
		}
}

9、其他

  • 二分搜索树的floor和ceil

  • 二分搜索树的rank和select

  • 支持重复元素的二分搜索树

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值