许多基础数据类型都和对象的集合有关。具体来说,数据类型的值就是一组对象的集合,所有操作都是关于添加、删除或是访问集合中的对象。
上面的意思是说,数据类型中的实例变量就是对象,而实例方法就是对此实例变量(对象 )进行操作以及查看此实例变量(对象)中的状态。
本节的目标是:
- 说明我们队集合中的对象的表示方式将直接影响到各种操作的效率。对于集合来说,我们将会设计适于表示一组对象的 数据结构并高效地实现所需的方法。
- 介绍泛型和迭代。它们是简单的java概念,是高级的编程语言机制,能通过它们写出简洁和优美的用例代码
- 介绍并说明,链式数据结构的重要性,特别是经典数据结构链表,有了它我们才能实现背包、队列和栈。理解链表是学习各种算法和数据结构中最关键的第一步。
对于本节这三种数据结构,我们会学习其API和用例,然后再讨论数据类型的值得所有可能的表示方法以及各种操作的实现。
API
- 泛型
集合类的抽象数据类型的一个关键特性是我们应该可以用它们存储任意类型的数据。java中称为泛型,也叫做参数化类型。
- 自动装箱 类型参数必须被实例化为引用类型(在用例代码中,不论是原始数据类型,泛型中使用的是引用类型,如果int 使用的是Integer),java中有一种机制类型来时泛型代码能够处理原始的数据类型。在处理 赋值语句、方法的参数和算术或逻辑表达式时,Java会自动在引用类型和对应的原始数据类型之间进行转换。 如一下公式
Stack<Integer> stack = new Stack<Integer>();
stack.push(13); 自动装箱(int --->Integer)
int num = stack.pop(); 自动拆箱(Integer---->int)
- 可迭代的集合类型
对于可迭代的集合类型中,要考虑实现的方式的不同
- 链表实现
- 数组实现
- 背包
背包是一种不支持从中删除元素的集合数据类型---它的目的就是帮助用例收集元素并迭代遍历所有收集到的元素。迭代的顺序不确定且与用例无关。
- 先进先出队列
先进先出队列是一种基于先进先出策略的集合类型。在应用程序中使用队列的主要原因是在用集合保存元素的同时保存它们的相对顺序:使它们入列顺序和出列顺序相同。
- 下压栈
集合类数据类型的实现
1.定容栈
表示容量固定的字符串栈的抽象数据类型。
栈的应用:
- 判断括号是否完整
- 计算括号中的运算
- 将中序表达式改为后序表达式
2.泛型
对于特殊类型的栈的缺点是,只能处理这一种类型的对象。如果需要别的值得栈,则需要用类似的代码实现另一个类。因为在java中是不允许创建泛型数组的。我们需要类型转换 Item[] a = (Item()) new Object[cap]; 即通过
3.调整数组大小
选择用数组表示栈内容因为着用例必须预估计栈的最大容量,
链表
链表是一种基础的数据结构,它是在集合类的抽象数据类型实现中表示数据的合适选择
链表是一种递归的数据结构,它或者为空(null),或者是指向一个结点(node)的引用。该节点含有一个泛型的元素和一个指向另一条链表的引用。结点是一个可能含有任意类型数据的抽象实体,它所包含的指向结点的应用显示了它在构造链表中的作用。
结点记录
一个Node对象含有两个实例变量,类型分别为Item(参数类型)和Node。我们会在需要使用Node类的类中,定义它并将它标记为private,因为它不是为用例准备的
结点的定义为一个嵌套类来定义结点的抽象数据类型:
private class Node
{
Item item;
Node next;
}
一个Node有两个实例变量 类型为Item(参数类型)和Node。 Item表示我们希望用链表处理任意的数据类型;Node类型的实例变量显示了这种数据结构的链式本质。为了强调我们在组织数据时,只是用了Node类,我们没有定义任何和方法且会在代码中直接引用实例变量。如果first是一个指向某个Node对象的变量,我们可以使用first.item 和first.node访问它的实例变量。
构造链表
根据递归定义,我们只需要一个Node类型的变量就能表示一条链表,只要保证它的值是null或者指向了另一个Node对象且该对象的next域指向了另一条链表即可。
- 需要注意的是数组也可以表示一列元素,不同之处在于链表的插入删除运算都更方便。
综述
在本节中,我们所学习的支持泛型和迭代的背包、队列和栈的实现所提供的抽象使我们能够编写简洁的用例程序来操作对象的集合。深入理解这些抽象数据类型非常重要,这是我们研究算法和数据结构的开始,原因有三:
- 我们将以这些数据类型为基石构造本书中的其他更高级的数据结构
- 他们展示了数据结构和算法关系以及同时满足多个有可能相互冲突的性能目标时所要面对的挑战。
- 我们将要学习的若干算法的实现重点就是需要其中的抽象数据类型能够支持对对象集合的强大操作。
数据结构
我们拥有两种对象集合的方式,即数组和链表。java内置了数组,链表也很容易使用java的标准方法实现。这两者都很基础,常常被称为顺序存储和链式存储。
在本书的后面部分,我们会在各种抽象数据类型的实现中将多种方式结归并扩展这些基本的数据结构。其中一种重要的扩展就是各种含有多个链接的数据结构。例如3.2和3.3节的重点就是被称为二叉树的的数据结构,它由含有两个链接的结点组成。另一个重要的扩展是复合型的数据结构:我们可以使用背包存储栈,用队列存储数组,等等。
注释:不管是什么数据结构进行组合,这需要将一切都是对象结合起来,
我们在本节中研究背包、队列和栈时描述数据结构和算法的方式是全书的原型。对于一个新的应用领域,我们将会按照以下步骤识别目标并使用数据抽象解决问题:
- 定义API;
- 根据特定的应用场景开发用例代码;
- 描述一种数据结构(一组指的表示方式),并在API所对应的的抽象数据类型的实现中根据它定义类的实例变量;
- 描述算法(实现一组操作的方式),并根据它实现类中的实例方法;
- 分析算法的性能特点;