列表的定义
概念
列表又可以叫作线性表,顾名思义,它是一条线,结构是一维的。
数据组织结构和数组相同,把 n (n$\geq$0)个元素排成一列就组成了一个列表 a
。
列表中的每个单一数据我们称为
元素(Element)
,所以列表a
的所有元素是a[0], a[1], a[2]..., a[n-2], a[n-1]
;
注意第一个元素是a[0]
,这是因为在计算机科学里,我们习惯将第一位使用 0 来标记,也因此最后一个元素是a[n-1]
;
每个元素的前一位元素,我们称为前继,后一位元素,称为后继;
很明显,a[0]
只有后继没有前继;a[n-1]
只有前继,没有后继。
在上述概念的基础上,我们可以思考列表的存储方式,应该有两种:
- 画好格子,每个元素一个坑儿,丢进去就好;
- 所有元素“手牵手”,每个元素知道自己前后是谁,也能把它们组织成一个列表;
第一种,我们称之为顺序表,图形化表示如下:
0 | 1 | 2 | … | n-2 | n-1 |
---|---|---|---|---|---|
e0 | e1 | e2 | … | en-2 | en-1 |
第二种,我们称之为链表,图形化表示如下:
注意
null
表示空,无任何东西。
列表类抽象定义
Java 是面向对象的语言,所以我们有必要对 列表
类做个定义。
如何抽象出一个类呢?我们知道类应该有属性和动作(操作),我们只需要找到列表的属性和操作,套进去就行啦!
观察上面的表格,它有哪些属性?
- 很明显,它有一个长度(
length
)n
,对列表我们习惯叫作大小(size
)。但是顺序表和链表计算大小的方式应该是不同的,所以我们把它放到子类中; - 有元素存储的容器。顺序表与链表的存储又明显有不同
- 顺序表(
ArrayList
)需要有一元素数组(elementArray
)用来存储数据; - 链表由(
LinkedList
)一个个节点(Node
)串联在一起存储,并没有一个内部属性用于存储所有数据。
怎么找到所有数据呢?只需要记录链表头元素(headNode
)就可以依次获取到所有元素了,所以它有一个属性是头元素(headNode
);- 节点类(
Node
)的结构呢?它应该有值(val
),有后一个元素的引用(next
)。
- 节点类(
- 顺序表(
以上,我们可以先得到一个类图:
类图中的
<E>
是泛型,代表任意类型。用在此处表示List
可以保存任何类型的数据。但是声明时确认了E
的类型后,就不可再变更了。
比如我们建一个保存User
类的列表,可以如下声明:// 此处 E 即是实际类型 User List<User> userList = new List<User>();
列表有哪些操作呢?在 Java 类的行为/动作/操作,我们称为方法(method
),以下以方法称呼。
- 获取列表大小(
size()
) - 添加(
add(E e)
)元素 - 在指定位置添加(
add(int index, E e)
)元素 - 删除(
remove(E e)
)元素 - 删除指定位置(
remove(int index)
)元素 - 修改某个位置(
set(int index, E e)
)上的元素 - 查找某个位置(
get(int index)
)上的元素 - 列表是否包含(
contains(E e)
)某个元素
我们把这些基本方法补充进类图:
补充线性表-栈与队列
区分出栈与队列的并不是它们的数据组织方式,而是它们的方法(method
)与普通列表不同。
栈(Stack)
还是举"子弹夹"的例子,装弹时的动作,是从弹夹顶部压入子弹,发射时,是从弹夹顶部弹出子弹发射出去。
栈就是和弹夹一样的结构,我们把顶部称为"栈顶"。压入"子弹"(元素),称为入栈,方法命名为 push
;弹出"子弹"(元素),称为出栈,方法命名为 pop
;可能还需要一个检查顶部"子弹"(元素)又不把它发射出去的方法,命名为 peek
。
push(E e)
,会把元素压入栈;pop()
,会返回栈顶元素,并把它从栈中删除;peek()
,会返回栈顶元素,但是不删除。
如果栈使用简单数组(elementArray
)实现存储元素,那么它的类图如下:
队列(Queue)
通常来说,队列是与栈相反的一种数据结构,它是从队列头部取元素,添加元素时只能添加到队列尾部,这与我们日常生活中的排队是一样的,所以叫作队列。
add(E e)
,把元素添加到队列尾部;poll()
,返回队列头部元素,并把它从队列中删除;peek()
,返回队列头部元素,但是不删除。
根据队列的性质,可以发现使用队列来存储数据是最方便的。可以得到以下类图:
线性表小节
以上就是列表常见的数据结构,分析并画出了基本的类图,这为以后使用代码实现它们提供了思路。当然每种结构都还有一些变形,在以后代码实现中会再扩展到。
- 列表
- 顺序表(通常据说的列表)
- 链表
- 栈
- 队列