算法 | 最坏情况下的成本 | 平均情况下的成本 | 是否高效低支持有序性的相关操作 | 关键接口 | 内存使用 | ||
---|---|---|---|---|---|---|---|
查找 | 插入 | 查找 | 插入 | ||||
顺序查找(无序链表) | N | N | N/2 | N | 否 | equals() | |
二分查找(有序数组) | lgN | 2N | lgN | N | 是 | compareTo() | 16N |
二叉树查找 | N | N | 1.39lgN | 1.39lgN | 是 | compareTo() | 64N |
2-3树查找(红黑树) | 2LgN | 2lgN | 1.00lgN | 1.00lgN | 是 | compareTo() | 64N |
拉链法(链表数组) | <lgN <script type="math/tex" id="MathJax-Element-21"> | <lgN <script type="math/tex" id="MathJax-Element-22"> | N/(2M) | N/m | 是 | equals() hascode() | 48N+32M |
线性检测法(并行数组) | clgN | clgN | <1.5 | <2.5 | 是 | equals() hascode() | 32N~128N |
数组
如int[]
优点:占用空间小,代码简洁,使用方便。
缺点:查找困难,大小固定。
增补:基于顺序数组的二分查找可加快其性能。加速查找性能,但插入性能并未得到改善。
无序链表
JAVA实现的类:
Class ArrayList<E>
优点:可动态增长和缩减的序列集合。
缺点:无序性,查找不方便,线性级别耗时。
二叉查找树
优点:结合了二分查找数组的快速查找性能和无序链表的动态增减性能。
缺点:算法较为复杂,相较于红黑树最坏情况并未得到改善。删除操作是树的最复杂的部分。
2-3查找树/红黑树
JAVA实现的类:
Class TreeMap<K,V>
不使用对应值时仅仅考虑键时采用Set类,对应的JAVA类:
Class TreeSet<E>
优点:将查找和插入操作的性能降至的对数级别,由于是平衡树,所以最坏情况也可以保证性能。
缺点:算法更为复杂,删除操作仍然是最为复杂的部分。
散列表:
JAVA实现的类:
Class HashMap<K,V>
不使用对应值时仅仅考虑键时采用Set类,对应的JAVA类:
Class HashSet<E>
优点:
将键值信息充分利用,相比于普通数组,对键值无利用,仅仅按时间进行录入,浪费了信息的价值;相比于树集,对键值进行排序再用类似二分查找思想进行搜寻;散列表对键值进行了转换,使之和数组的下标对应,在查找时既不用顺序查找也不用二分查找,直接点对点利用下标搜寻。
缺点:
空间消耗较大,引入对时空消耗的衡量,空间越大,速度越快(上限为常数级别),空间越小,速度越慢。无序性。
补充:
散列表又拓展为两种方法:
链表型散列表,即对相同hash值的键值采用归为一组的方式进行(可归为数组,但大小固定;可归为链表);
探测型散列表,即建立一个比录入数据量更大的数据表,遇到相同情况则往后面空的地方填数据。探测型散列表也可以分为线性和非线性探测两种,即在遇到键值相同时,采用的步长不一样;
散列表的速度和hashCode()的计算成本有关。