搞懂数据结构-二叉搜索树
1.背景
如果在n个动态的整数中搜索某个整数
- 利用无序动态数组存放整数,搜索的平均复杂度是O(n)
- 利用有序动态数组存放整数,可以使用二分法,最坏时间复杂度是O(logn),但是维护有序数组,添加和删除的时间复杂度是O(n)
使用二叉搜索树可以是添加,删除和搜索的最坏时间复杂度优化到O(logn)
2.二叉搜索树的性质
- 任意一个节点的值都大于其左子树所有节点的值
- 任意一个节点的值都小于其右子树所有节点的值
- 它的左右子树也是一颗二叉搜索树
二叉搜索树存储的元素必须具备可比较性
- 比如int等
- 如果是自定义类型,需要指定比较的方式
- 不允许为null
3.接口设计
int size() // 元素的数量
boolean isEmpty() // 是否为空
void clear() // 清空所有元素
void add (E element) // 添加元素
void remove (E element) // 删除元素
boolean contains (E element) // 是否包含某元素
4.实现二叉搜索树
4.1比较
这里的设计思路很好,多理解
二叉搜索树要求元素必须具有比较性
第一种方法实现比较
//第一种方法,写一个比较接口,传入的元素必须遵守这个接口
//接口
public interface Comparable<E> {
int compareTo(E e);
}
//传入的元素必须遵守这个接口,在里面重写比较的方法
public class BinarySearchTree<E extends Comparable> {
}
但是上面的问题把一个类型的比较方式给写死了,例如重写的person的age比较,但是如果进行两次比较一次用age,一次不用age,这样就存在局限性。
优化比较
步骤:
- 判断是否传比较器
- 如果不传比较器则强制使用第一种方法
//定义各一个比较器接口
public interface Comparator<E> {
int compareTo(E e1, E e2);
}
//构造方法,可以定义传比较器和不传比较器
public class BinarySearchTree<E> {
//比较器
private Comparator comparator;
//不传比较器
public BinarySearchTree() {
this(null);
}
//传入比较器
public