线性表
定义
- 由
n个相同数据类型的元素构成的有限序列
- n:元素个数确定
- 数据类型相同
- 序列:有先后顺序
- 除了表头表尾元素之外,其他元素都有唯一前驱和后继
- 表头元素只有后继,表尾元素只有前驱
- 线性表是逻辑结构,表示在脑里想象的时候是一条线串联起来的,而顺序表和链表则是存储结构,是在计算机内存中的。
- 线性表分为顺序表和链表。
顺序表和链表对比
- 详细对比了两个存储结构的优缺点
| 对比项目 | 顺序表 | 链表 |
| 存储结构 | 连续的内存空间(数组)存储数据 | 不连续的内存空间,通过指针连接节点 |
| 内存 | 可以动态扩容,但要把原数据全拷贝过去 | 需要增加数据就插入一个节点 |
| 查找 | 支持随机访问,通过下标 O(1) 获取元素 |
只能从头遍历,访问第 i 个元素需要 O(n) |
| 增删改 | O(n) |
O(1) |
| 特点 | 用空间换时间,查询快,插入删除慢 | 用时间换空间,插入删除快,查询慢。 |
ArrayList(顺序表)
小巧思
- 在c语言中实现顺序表通常使用结构体,在结构体中定义数组,和数组初始长度。
- 但是在Java中没有结构体,通常使用类进行定义顺序表,同样的可以在类中定义数组,数组初始长度。此外,类中还可以定义方法,对数组进行增删改查等操作。
- 我们还可以让顺序表类去继承其他的类/接口。
- 我们还可以去定义一个泛型类顺序表,当创建对象的时候在去指定顺序表中存储数据的数据类型,实现定义一个类,就有了可以存储所有类型数据的顺序表。
- 那么顺序表可以通过类去定义实现,链表如何实现?
- 在c语言中可以使用结构体,把结构体看成一个节点,节点中可以存储数据,还可以存储下一个节点的地址,Java中没有地址,这咋搞?(没有地址,我有引用)
- 那么是否可以把类看成节点?节点中也存储此节点的数据和下一个节点的引用,这不就行了吗。
优点
- 空间利用率高:节点内只存储数据,不存储下一个节点的地址
- 随机存取:可以通过数组下标
i,想访问哪个元素访问哪个- 访问元素快:通过下标访问,时间复杂度:
O(1)
基本操作
- 主要分为:List接口/MyArrayList类/test测试类
List接口
- 顺序表的父类,主要存储一些增删改查这些抽象方法。
java
package List;
//List接口中是对顺序表的增删改查操作
public interface List {
void add(int data);
//增加元素
void add(int pos,int data);
//构成重载,特定位置pos增加元素
void findData(int data);
//按值查找
void indexData(int pos);
//按位查找
void Empty();
//判空
void deletePosData(int pos);
//按位删除
void deleteData(int data);
//按值删除
void listLength();
//返回顺序表的长度
void PrintArrayList();
//输出顺序表
}
MyArrayList类
- 主要实现顺序表的类,重写接口中所有的方法。
java
package List;
//实现一个类似于Java自带的顺序表类
import java.util.Arrays;
public class MyArrayList implements List{
//设定数组长度
private int length = 5 ;
//存储元素数组
private int[] myArray;
//方法中当前长度
public int preLength = 0;
//让myArray引用指向对象中新开辟的数组空间
//对象中的引用指向一个数组对象
public MyArrayList(){
this.myArray = new int[length];
}
@Override
public void add(int data) {
//判断顺序表是否存满,存满则不可插入
if (preLength < length){
this.myArray[preLength] = data;
preLength++;
}else {
System.out.println("顺序表已经存满,无法存入数据");
}
//尾部插入元素
}
@Override
public void add(int pos, int data) {
// 检查位置是否合法
if (pos < 0 || pos > preLength) {
System.out.println("插入位置不合法");
return;
}
if (preLength < length) {
// 将pos及其后面的元素后移
for (int i = preLength; i > pos; i--) {
this.myArray[i] = this.myArray[i - 1];
}
this.myArray[pos] = data;
preLength++;
} else {
System.out.println("顺序表已经存满,无法存入数据");
}
}
@Override
public void findData(int data) {
for (int i = 0; i < this.myArray.length; i++) {
if (this.myArray[i] == data) {
System.out.println("按值查找的元素为:" + data);
}
}
//按值查找
}
@Override
public void indexData(int pos) {
for (int i = 0; i <this.myArray.length ; i++) {
if (i == pos) {
System.out.println("按位查找的元素index为:" + i);
}
}
//按位查找
}
@Override
public void Empty() {
if (preLength == 0) {
System.out.println("顺序表为空");
} else {
System.out.println("顺序表非空");
//判空,对象自己的数组,不需要传参,直接对象名.方法名进行判断
}
}
@Override
public void deletePosData(int pos) {
if (pos < 0 || pos >= preLength) {
System.out.println("删除位置不合法");
}
else if (preLength != 0) {
for (int i = 0; i < this.preLength-1; i++) {
if (i == pos){
for (int j = i; j < this.preLength-1; j++) {
this.myArray[j] = this.myArray[j+1];
}
}
this.myArray[preLength - 1] = 0;
System.out.println("删除后的顺序表为:" +Arrays.toString(myArray) );
preLength--;
//长度减1
}
}else {
System.out.println("删除失败");
}
}
@Override
public void deleteData(int data) {
//按值删除
if (preLength == 0) {
System.out.println("顺序表为空,无法删除");
}
if (preLength != 0) {
//顺序表非空才可以删除
for (int i = 0; i < this.preLength-1; i++) {
if (this.myArray[i] == data) {
for (int j = i ; j < this.preLength-1; j++) {
this.myArray[j] = this.myArray[j + 1];
//顺序表要求连续存放,数据之间不可以有null值。
}
this.myArray[preLength - 1] = 0;
System.out.println("删除后的顺序表为:" +Arrays.toString(myArray) );
preLength--;//删除成功
}
}
} else {
System.out.println("顺序表为空,无法删除");
}
}
@Override
public void listLength() {
System.out.println("当前顺序表长度为:" + this.preLength);
//返回顺序表的长度,对象自己的数组不需要传参,直接对象名.方法名就可以调用判断
}
@Override
public void PrintArrayList() {
System.out.println( Arrays.toString(myArray));
}
}
test类
- 测试结果输出
java
package List;
public class test {
static void main() {
MyArrayList myArrayList = new MyArrayList();
myArrayList.PrintArrayList();
myArrayList.listLength();
myArrayList.add(1);
myArrayList.add(1,20);
myArrayList.add(3);
myArrayList.add(3,40);
myArrayList.add(5);
myArrayList.PrintArrayList();
myArrayList.listLength();
System.out.println("插入功能测试成功");
myArrayList.findData(20);
myArrayList.indexData(3);
System.out.println("查找功能测试成功");
System.out.print("当前表内元素为:");
myArrayList.PrintArrayList();
myArrayList.deleteData(1);
myArrayList.deletePosData(-2);
}
}
/Users/mdj/Library/Java/JavaVirtualMachines/openjdk25/Contents/List.test
[0, 0, 0, 0, 0]
当前顺序表长度为:0
[1, 20, 3, 40, 5]
当前顺序表长度为:5
插入功能测试成功
按值查找的元素为:20
按位查找的元素index为:3
查找功能测试成功
当前表内元素为:[1, 20, 3, 40, 5]
删除后的顺序表为:[20, 3, 40, 5, 0]
删除位置不合法
Process finished with exit code 0