在了解基本的数据结构基础之前,理解抽象数据类型(ADT)的概念很有必要.
Java 2软件开发包(SDK)提供了一些新类来支持大多数常用的ADT。这些类被称为Java集合类(类似于MFC中的集合类),它们协同工作从而形成Java 集合架构。这个集合架构提供了一套将数据表示成所谓的集合抽象数据的接口和类。
一个线性表是有限个元素的集合,其元素以线性的方式进行排列并提供对它的元素的直接访问(线性排列和存储地址是否连续一点关系没)。
一个堆栈是一个后进先出(LIFO)的有序线性表,元素从堆栈头加入,并从堆栈头取出。
一个队列是一个先进先出的有序线性表,元素从队列尾加入,并从队列头取出。
举例来讲, 线性表,堆栈和队列的内部结构可以用许多方式实现。例如,我们可以使用一个有序数组或者一个链表来实现每个结构。关键的一点是不论你如何实现其内部结构,它对外的接口总是不变的。这使得你能够修改或者升级底层的实现过程而不需要改变公共接口部分。
理解了ADT后,其实并不能很好的理解这句话: 程序=算法+数据结构, 毕竟这些抽象类型都是别人已经写好的,最起码我们得了解其实现机制,这样才能更好的使用.这也就是我认为学习数据结构的重点.
数组
数组最大的特点就是简单,寻址简单,
和链表的特点对比:
1、存取方式上,数组可以顺序存取或者随机存取,而链表只能顺序存取;
2、存储位置上,数组逻辑上相邻的元素在物理存储位置上也相邻,而链表不一定;
3、存储空间上,链表由于带有指针域,存储密度不如数组大;
4、按序号查找时,数组可以随机访问,时间复杂度为O(1),而链表不支持随机访问,平均需要O(n);
5、按值查找时,若数组无序,数组和链表时间复杂度均为O(1),但是当数组有序时,可以采用折半查找将时间复杂度降为O(logn);
6、插入和删除时,数组平均需要移动n/2个元素,而链表只需修改指针即可;
7、空间分配方面,数组在静态存储分配情形下,存储元素数量受限制,动态存储分配情形下,虽然存储空间可以扩充,但需要移动大量元素,导致操作效率降低,而且如果内存中没有更大块连续存储空间将导致分配失败;链表存储的节点空间只在需要的时候申请分配,只要内存中有空间就可以分配,操作比较灵活高效;
数组应用场景:
1、注重存储密度;
2、经常做的运算是按序号访问数据元素;
3、数组更容易实现,任何高级语言都支持;
4、构建的线性表较稳定。
链表应用场景:
1、对线性表的长度或者规模难以估计;
2、频繁做插入删除操作;
3、构建动态性比较强的线性表。
链表
链表和数组都相对很简单,知道是怎么回事,有啥特点就行.
在JAVA中,定义一个Node结点是采用类的形式.
//双向链表的结点
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
简单实现参考:
http://www.cnblogs.com/matrix1024/archive/2011/12/31/2308380.html
最后, 在线性表的实现上,数组和链表的实现有什么不同呢? 使用的时候有什么指导原则呢?
最大不同就是
ArrayList内部存储数据是 采用 private transient Object[] elementData;
初始数组大小是10 : private static final int DEFAULT_CAPACITY = 10;
LinkedList结点采取的上面的内部类:Node类.
使用的指导原则:
如果数据量不大,可以考虑采用线性表, 使用的时候可以参考2点:
1)如果数据量大小未知,可以考虑linkedList, 如果大小已经预知,可以采用ArrayList,
2)如果查询速度重要性比较重要,优先采用ArrayList; 相反,如果插入或者删除操作比较频繁,优先采用LinkedList