1 概述
1.1 线性表
-
线性表定义:
-
线性表*(linear list)*是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。数据元素是一个抽象的符号,其具体含义在不同的情况下一般不同。[1]
-
相关概念:长度,空表,索引(位序),前驱元素,后继元素
-
线性表中的个数n定义为线性表的长度,n=0时称为空表。在非空表中每个数据元素都有一个确定的位置,如用ai表示数据元素,则i称为数据元素ai在线性表中的位序。[1]
线性表的相邻元素之间存在着序偶关系。如用(a1,…,ai-1,ai,ai+1,…,an)表示一个顺序表,则表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素。当i=1,2,…,n-1时,ai有且仅有一个直接后继,当i=2,3,…,n时,ai有且仅有一个直接前驱 。[1]
-
优点:线性表的逻辑结构简单,便于实现和操作。因此,线性表这种数据结构在实际应用中是广泛采用的一种数据结构。[2] -
分类:线性表中的存储方式可以是顺序存储,也可以是连式存储。根据存储方式的不同分为顺序表和链表。
1.2 顺序表
2 API设计
? 了解了顺序表的概念特点及应用后,我们自己来设计下顺序表的API。
类名 | SequenceList |
---|
构造方法 | 1. SequenceListJunior() 2. SequenceListJunior(int capacity) | 成员方法 | 1. public boolean add(E e) //添加 2. public void add(int i, E e) //指定位置添加元素 3. public void clear() //清空顺序表 4. public void ensureCapacity(int minCapacity) //确保顺序表容量 5. private void ensureCapacityInternal(int minCapacity) // 确保顺序表容量 6. private void ensureExplicitCapacity(int minCapacity) // 严格确保容量 7. private void grow(int minCapacity) // 数组扩容 8. public boolean isEmpty() //判断顺序表是否为空 9. public E remove(int i) //移除指定位置元素 10. public boolean remove(Object o) //移除元素 11. public int size() //获取顺序表大小 12. public String toString() | 成员变量 | 1. private static final int DEFAULT_CAPACITY = 10; //默认容量 2. private static final Object[] EMPTY_ELEMENTDATA = {}; //空顺序表 3. private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA={}; //默认空顺序表 4. transient Object[] elementData; 存储元素的数组 5. private int size; 顺序表大小 |
3 初级实现和测试
3.1 构造方法
3.2 成员方法
-
clear:情况顺序表 public void clear() {
if (this.size > 0) {
for (int i = 0; i < this.size; i++) {
this.elementData[i] = null;
}
this.size = 0;
}
}
-
isEmpty:判断顺序表是否为空
public boolean isEmpty() {
return this.size == 0;
}
- 如果顺序表对象为null呢?那么调用该方法就会报NullPointerException异常
-
size:获取顺序表大小,就是实际存储了多少个元素
public int size() { return this.size; }
-
add(E e):顺序表添加元素e
public boolean add(E e) {
this.elementData[size++] = e;
return true;
}
- 如果顺序表容量不够怎么办?
- 为啥方法要返回boolean呢?参考ArrayList源码
-
add(int index,E e):指定位置插入元素
public void add(int index, E e) {
for (int i = this.size; i > index; i--) {
this.elementData[i] = this.elementData[i - 1];
}
elementData[index] = e;
size++;
}
- 如果顺序表容量不够怎么办?
- 如果指定的索引index不在0~size内怎么办?
- 元素后移操作,i = this.size不会索引越界吗?下面改进
-
remove(int index):移除指定位置的元素
public E remove(int index) {
Object o = this.elementData[index];
for (int i = index; i < this.size - 1; i++) {
this.elementData[i] = this.elementData[i + 1];
}
this.elementData[size--] = null;
return (E) o;
}
- 索引index越界问题
- 元素迁移是否可以优化,元素迁移是否越界
-
toString(): @Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < this.size; i++) {
if (i == this.size - 1) {
sb.append(this.elementData[i]);
} else {
sb.append(this.elementData[i]).append(", ");
}
}
sb.append("]");
return sb.toString();
}
3.3 简单测试
public class TestSequenceList {
public static void main(String[] args) {
SequenceListJunior<Integer> slj = new SequenceListJunior<>(5);
slj.add(22);
slj.add(5242);
slj.add(52);
System.out.println(slj);
System.out.println("原数组大小: " + slj.size() );
System.out.println("====移除索引为0的元素: " + slj.remove(0));
System.out.println(slj);
System.out.println("移除后数组大小: " + slj.size());
}
}
4 后记
? 以上为顺序表的初级实现,有很多问题和不完善的地方,后面我们参考ArrayList源码对上述代码进行改进。完整源代码在下面代码仓库。
QQ:806797785
源代码仓库地址:https://gitee.com/gaogzhen/algorithm
参考:
[1]百度百科.线性表[EB/OL].2022-05-08/2022-10-02.
[2]百度百科.顺序表[EB/OL].2022-05-09/2022-10-02.
[3]黑马程序员.黑马程序员Java数据结构与java算法全套教程,数据结构+算法教程全资料发布,包含154张java数据结构图[CP/OL].2020-01-18/2022-10-02.
|