设计背景
传统的数组可以存放重复的元素,且其存放有序,而有时我们不希望数据结构存储重复的元素,且我们不关注它的排序,例如IP访问量统计、文本字数统计等。这种存储无序且不重复元素的结构类型就被称之为集合(Set)。
结构分析
【底层实现】二分搜索树(BST)/ 链表(LinkedList)
【核心方法】
public void add(E e); //向集合添加元素
public void remove(E e); //移除集合中指定的元素
【差异分析】
因为使用链表实现的集合(LinkedListSet)进行增加、删除等操作时,都需要对链表元素进行遍历,故其性能较低(时间复杂度为O(n)级别);而使用二分搜索树实现的集合(BSTSet)在理想状态下(满二叉树)最多只会遍历h个元素(时间复杂度为O(h)级别,从数值上看为O(logn)级别),所以通常BSTSet的性能与LinkedListSet的性能差异巨大。
代码实现
1. 利用二分搜索树实现
public class BSTSet<E extends Comparable<E>> implements Set<E> {
/**
* 实例域:二分搜索树
*/
private BST<E> bst;
/**
* 无参构造器:对实例域进行初始化
*/
public BSTSet() {
bst = new BST<>();
}
@Override
public void add(E e) {
bst.add(e);
}
@Override
public void remove(E e) {
bst.remove(e);
}
@Override
public boolean contains(E e) {
return bst.contains(e);
}
@Override
public int getSize() {
return bst.getSize();
}
@Override
public boolean isEmpty() {
return bst.isEmpty();
}
}
2. 利用链表实现
public class LinkedListSet<E> implements Set<E> {
/**
* 实例域:链表
*/
private LinkedList<E> linkedList;
/**
* 无参构造器:对实例域进行初始化
*/
public LinkedListSet() {
linkedList = new LinkedList<>();
}
@Override
public void add(E e) {
linkedList.addFirst(e);
}
@Override
public void remove(E e) {
linkedList.remove(e);
}
@Override
public boolean contains(E e) {
return linkedList.contains(e);
}
@Override
public int getSize() {
return linkedList.size();
}
@Override
public boolean isEmpty() {
return linkedList.isEmpty();
}
}