通过学习自定义集合,了解集合的数据结构。
本篇分别以链表的方式和以二分搜索树的方式实现了集合。
首先写一个集合的接口,描述其具有的基本功能。Set.java
然后写一个接口的实现类:
其中,方式一: 用的是链表的方式。 LinkedListSet.java
用到了 自定义链表 中的 LinkedList.java
方式二:用的是二分搜索树的方式。 BSTSet.java
用到了 二分搜索树 中的 BinarySearchTree.java
方式一与方式二的时间复杂度分析:
其中: 字母h代表树的深度。
| LinkedListSet | BSTSet 平均情况 最坏情况 | ||
add | O(n) | O(h) | O(log n) | O(n) |
contains | O(n) | O(h) | O(log n) | O(n) |
remove | O(n) | O(h) | O(log n) | O(n) |
此外还分:有序集合、无序集合、多重集合。
有序集合:元素具有顺序性。(基于搜索树的实现)
无序集合:元素没有顺序性。(基于哈希表的实现)
多重集合:元素可以重复。
包结构:
Set.java:
package SetAndMap;
public interface Set<E> {
void add(E e);//不可重复
boolean contains(E e);
void remove(E e);
int getSize();
boolean isEmpty();
}
方式一:
package SetAndMap;
public class LinkedListSet<E> implements Set<E> {
private LinkedList<E> list;//内部维护了一个自定义的链表。
/**
* 无参构造函数
*/
public LinkedListSet() {
list=new LinkedList<E>();
}
/**
* 向集合中添加元素
*
*/
@Override
public void add(E e) {
if(!list.contains(e)) {//去除重复元素
list.addFirst(e);
};
}
/**
* 判断是否包含指定元素
*/
@Override
public boolean contains(E e) {
return list.contains(e);
}
/**
* 删除指定元素
*/
@Override
public void remove(E e) {
list.removeElement(e);;
}
/**
* 获取集合大小
*/
@Override
public int getSize() {
return list.getSize();
}
/**
* 判断集合是否为空
*/
@Override
public boolean isEmpty() {
return list.isEmpty();
}
}
方式二:
package SetAndMap;
public class BSTSet<E extends Comparable<E>> implements Set<E> {
private BinarySearchTree<E> bst;//内部维护了一个自定义的二分搜索树。
/**
* 无参构造函数
*/
public BSTSet() {
bst=new BinarySearchTree<E>();
}
/**
* 向集合中添加元素
* 重复元素已舍弃
*/
@Override
public void add(E e) {
bst.add(e);
}
/**
* 判断是否包含指定元素
*/
@Override
public boolean contains(E e) {
return bst.contains(e);
}
/**
* 删除指定元素
*/
@Override
public void remove(E e) {
bst.remove(e);
}
/**
* 获取集合大小
*/
@Override
public int getSize() {
return bst.size();
}
/**
* 判断集合是否为空
*/
@Override
public boolean isEmpty() {
return bst.isEmpty();
}
}