最近在恶补Hibernate,但是Hibernate懂得东西很浅没法写博客,但是手痒想写博客,就准备复习复习数据结构。
书籍——《数据结构与算法分析-Java语言描述》,这本书我买了快三年了,大二上的时候买的,当时完全看不懂,这些回头一看,研一的书籍。。。。
抽象数据类型
抽象数据结构(abstract data type ADT)是带有一组操作的一些对象的集合。抽象数据是数学的抽象;在ADT的定义中没有地方提到关于这组操作是如何实现的任何解释。诸如表集合、图以及与它们的各自的操作一起形成的这些对象都可以被看做是抽象数据类型。
表ADT
将A0、A1、A2…AN-1的一般表。我们说这个表的大小是N,大小为0的特殊表称为空表(empty list)。
表的简单实现——数组
对表的所有操作都可以通过使用数组来实现,数组的容量是固定的,在扩展的时候可以创建一个双倍的容量的新数组。
数组最经常与ArrayList进行对比,其最大的区别就是数组在内存上是一块连续的空间,而链表不是连续的空间。这就是导致了在创建数组的时,必须声明数组的长度,确保在内存中能找到一块合适的空间用来存放数组。
数组通过get、set方法时间复杂度为O(1),因为可以根据其索引定位地址查询。
查询一个元素需要遍历数组,时间复杂度为O(n)。
数组的添加和删除的成本是非常大的,当要操作位置0,需要在内存中后移或者前移所有的元素。
操作 | 效率 |
---|---|
find | O(n) |
get | O(1) |
delete | O(n) |
add | O(n) |
链表ArrayList
这是一个实现了List接口的方法,为了避免数组在添加和删除时造成的线性开销,链表在内存空间中不需要是连续的。通常可以认为ArrayList是一个基于动态数组的数据结构。
链表由一系列节点组成,这些节点不必在内存中相连。每一个节点均含有表元素和到包含该元素后继元的节点的链(link),最后一个单元的next链引用为null。
ArrayList的初始容量为10,ArrayList每次扩容1.5倍。
双向链表LinkedList
LinkedList是基于链表的数据结构
|操作|效率 |
|–|--|
| find| O(n) |
|get|O(n)|
|delete|O(n)|
|add|O(n)|
LinkedList在查询的时候有个特性,比如LinkedList长度为50,查询第20个元素的时候,会从头部开始查询;查询第40个元素从尾部开始查询。根据查询哪一个元素位置,自动选择较劲的一端。
Collection接口扩展了Iterable接口。实现了Interable接口的那些类可以拥有增强的for循环。实现Interable接口的集合必须提供一个称为iterable的方法,该方法返回一个Iterator类型的对象。
java.util.Iteraotr接口代码(jdk1.8代码):
public interface Iterator<AnyType>{
//判断是否还有下一项
boolean hasNext();
//返回集合的下一项
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
Iterator接口的思路是,通过Iterator方法,每个集合均可创建并返回一个给客户一个实现Interator接口的对象,并将当前位置的概念在对象内部储存下来。
如果正在被迭代器迭代的集合进行结构上的改变(add、remove、clear方法),那么迭代器就不再合法(并且在其后使用该迭代器时将会有ConcurrentMethodficationException异常被抛出)。为避免迭代器准备给出某一项作为下一项而该项此后被删除,或者也许一个新的项插入该项的前面这样一些情况,有必要记住这一法则。这就意味着,只有在需要立即使用一个迭代器的时候,我们才应该获取迭代器。然而,迭代器使用注解的remove方法,这个迭代器是合法的。
栈
栈是限制插入和删除只能在同一个位置上进行的表,该位置是表的末端,叫做栈顶。对栈的基本操作有push和pop,前者相当于插入,后者则是删除最后的插入元素。栈又叫做(LIFO)表。
未完待续…